PG::UndefinedTable: ERROR: relation «productsrules» does not exist

4.4k views Asked by At

I'm having this issue with one of my PG DB table. I have a table, whose name is "hproducts_rules". This is supposed to have a "belongs_to" relation with the "hproducts_matchs" table.

This is my tables schema:

hproducts_match

has_many :productsrule
default_scope order: 'id'
attr_accessible :productsrule_attributes, :product_id, :company_id, :product_key, :description, :condition
accepts_nested_attributes_for :productsrule, :reject_if => :all_blank, :allow_destroy => true
self.table_name = "hproducts_matchs"

hproducts_rule

belongs_to :productsmatch
default_scope order: 'id'
attr_accessible :productsmatch_id, :company_id, :product_key, :origen_comp, :line, :connector, :char_start, :char_end, :modeprize_id, code_opc, :ochar_start, :onchar_end self.table_name = "hproducts_rules"

When I try to add a partial in my "products_match" form, I get the following error:

PG::UndefinedTable: ERROR: relation «productsrules» does not exists
LINE 5:              WHERE a.attrelid = '"productsrules"'::regclas...
                                        ^
:             SELECT a.attname, format_type(a.atttypid, a.atttypmod),
                     pg_get_expr(d.adbin, d.adrelid), a.attnotnull, a.atttypid, a.atttypmod
              FROM pg_attribute a LEFT JOIN pg_attrdef d
                ON a.attrelid = d.adrelid AND a.attnum = d.adnum
             WHERE a.attrelid = '"productsrules"'::regclass
               AND a.attnum > 0 AND NOT a.attisdropped
             ORDER BY a.attnum

I first thought it was because my table name was "hproducts_match" and my reference field was "productsmatch_id" on my "products_rules" table, so I changed the name to "hproductsmatch_id" and got the same. Then I change the whole table name to be "products_rules" instead of "hproducts_rules" and still the same. I even added a foreign_key constraint on the table and the model, and still the same.

I'm not sure if the relation is supposed to be named "hproductsrules" OR "productsrules" so maybe that's the issue. Where could I change that?

I made some research around and majority of them were related to migration. I hadn't use migration on my DB development, i manually added the table just like I've done with every single one. Others were about rspec, out of my scope.

Anyone knows why this may be happening? This only shows up when I work with the partial within the form.

Thanks in advance.

EDIT TO SHOW MY ANSWER

Ok, for some apparent reason my application was assuming that my table name was "productsrules" instead of "hproducts_rules" so what i did was changing the "self.table_name" line to the top of my model and then everything went ok.

Not sure if this is the correct answer for this question, but its what helped me fix it.

I reverted my model back to the original state (one i had at the start of this question) the only difference is as follows:

class Productsrule < ActiveRecord::Base
  self.table_name = "hproducts_rules"
  belongs_to :productsmatch
  default_scope order: 'id'
  attr_accessible :productsmatch_id, :company_id, :product_key, :origen_comp, :line,     :connector, :char_start, :char_end, :modeprize_id, code_opc, :ochar_start, :onchar_end
end

As you can see, the self.table_name line was at the start of the model.

Thanks everyone who replied :)

2

There are 2 answers

1
usha On

When you are not following rails naming convention for association, you will have to specify the foreign key and class name explicitly. Similar to how you are setting the table name explicitly

hproducts_match

has_many :products_rules, :foreign_key => "productsmatch_id", :class_name => "HproductsRule"
default_scope order: 'id'
attr_accessible :productsrule_attributes, :product_id, :company_id, :product_key, :description, :condition
accepts_nested_attributes_for :productsrule, :reject_if => :all_blank, :allow_destroy => true
self.table_name = "hproducts_matchs"

hproducts_rule

belongs_to :products_match, :foreign_key => "productsmatch_id", :class_name => "HproductsMatch"
default_scope order: 'id'
attr_accessible :productsmatch_id, :company_id, :product_key, :origen_comp, :line, :connector, :char_start, :char_end, :modeprize_id, code_opc, :ochar_start, :onchar_end self.table_name = "hproducts_rules"
1
nathanvda On

If you write the relations like you do, rails will try to derive class names and table names based on the relation name.

So if you write

has_many :productsrule

you write it singular? That is weird nr 1. But rails will look for table productsrules and model Productsrule.

Instead if you write:

has_many :hproducts_rules

it will look for model HproductsRule and table hproducts_rules. This seems to be what you want. Now for the referential key, it will look for a foreign-key in the format <model-name>_id, so in your case that would be hproducts_match_id, and that field is not there as well.

So if you want to maintain the current situation you could write:

class HproductsMatch

  has_many :hproducts_rules, :foreign_key => 'productsmatch_id`

  default_scope order: 'id'
  attr_accessible :hproducts_rule_attributes, :product_id, :company_id, :product_key, :description, :condition
  accepts_nested_attributes_for :hproduct_rules, :reject_if => :all_blank, :allow_destroy => true
  self.table_name = "hproducts_matchs" 
end


class HproductsRule

  belongs_to :hproducts_match, :foreign_key => 'productsmatch_id'
  default_scope order: 'id'
  attr_accessible :productsmatch_id, :company_id, :product_key, :origen_comp, :line, :connector,
end

but since you seem to have full control over your database model, why not write:

class ProductsMatch
  has_many :products_rules
  accepts_nested_attributes_for :products_rules
end

class ProductsRule
  belongs_to :products_match
end

in which case you have table products_rules with foreign_key products_match_id and table products_matches.