Question

I can't seem to understand how this association should look and work. I know I have not been very rails like with the naming convention, but neither is the source DB where I get the data, I do not have the freedom to change the primary keys as they relate also to the real source database, which I use ETL to load into my rails database.

These are my models:

class Eclass < ActiveRecord::Base
  has_many :elinks, :foreign_key => :concept_id
  has_many :eproperties, :through => :elinks
end

class Elink < ActiveRecord::Base
  belongs_to :eclass, :foreign_key => :concept_id
  belongs_to :eproperty, :foreign_key => :pconcept_id
end

class Eproperty < ActiveRecord::Base
  has_many :elinks, :foreign_key => :pconcept_id
  has_many :eclasses, :through => :elinks
end

And these are the MySQL table schemas:

mysql> DESC eclasses;
+--------------+--------------+------+-----+---------+----------------+
| Field        | Type         | Null | Key | Default | Extra          |
+--------------+--------------+------+-----+---------+----------------+
| id           | int(11)      | NO   | PRI | NULL    | auto_increment |
| class_id     | varchar(255) | YES  |     | NULL    |                |
| concept_id   | varchar(255) | NO   | PRI | 1       |                |
| concept_name | varchar(255) | YES  |     | NULL    |                |
| language_id  | varchar(255) | YES  |     | NULL    |                |
| created_at   | datetime     | YES  |     | NULL    |                |
| updated_at   | datetime     | YES  |     | NULL    |                |
+--------------+--------------+------+-----+---------+----------------+
7 rows in set (0.00 sec)

mysql> DESC elinks;
+-------------+--------------+------+-----+---------+----------------+
| Field       | Type         | Null | Key | Default | Extra          |
+-------------+--------------+------+-----+---------+----------------+
| id          | int(11)      | NO   | PRI | NULL    | auto_increment |
| schema_id   | varchar(255) | YES  |     | NULL    |                |
| concept_id  | varchar(255) | YES  |     | NULL    |                |
| pconcept_id | varchar(255) | YES  |     | NULL    |                |
| data_type   | varchar(255) | YES  |     | NULL    |                |
| language_id | varchar(255) | YES  |     | NULL    |                |
| sequence    | int(11)      | YES  |     | NULL    |                |
| created_at  | datetime     | YES  |     | NULL    |                |
| updated_at  | datetime     | YES  |     | NULL    |                |
+-------------+--------------+------+-----+---------+----------------+
9 rows in set (0.02 sec)

mysql> DESC eproperties;
+---------------+--------------+------+-----+---------+----------------+
| Field         | Type         | Null | Key | Default | Extra          |
+---------------+--------------+------+-----+---------+----------------+
| id            | int(11)      | NO   | PRI | NULL    | auto_increment |
| property_id   | varchar(255) | YES  |     | NULL    |                |
| pconcept_id   | varchar(255) | NO   | PRI | 1       |                |
| property_name | varchar(255) | YES  |     | NULL    |                |
| language_id   | varchar(255) | YES  |     | NULL    |                |
| created_at    | datetime     | YES  |     | NULL    |                |
| updated_at    | datetime     | YES  |     | NULL    |                |
+---------------+--------------+------+-----+---------+----------------+
7 rows in set (0.00 sec)

And here is the error I get back, looks like active record is executing a query with an empty column name:

irb(main):002:0> @eclass.eproperties
  ←[1m←[35mEproperty Load (0.0ms)←[0m  SELECT `eproperties`.* FROM `eproperties`
 INNER JOIN `elinks` ON `eproperties`.`` = `elinks`.`pconcept_id` WHERE `elinks`
.`eclass_id` IS NULL
Mysql2::Error: Unknown column 'elinks.eclass_id' in 'where clause': SELECT `epro
perties`.* FROM `eproperties` INNER JOIN `elinks` ON `eproperties`.`` = `elinks`.`pconcept_id` WHERE `elinks`.`eclass_id` IS NULL
ActiveRecord::StatementInvalid: Mysql2::Error: Unknown column 'elinks.eclass_id'
 in 'where clause': SELECT `eproperties`.* FROM `eproperties` INNER JOIN `elinks` ON `eproperties`.`` = `elinks`.`pconcept_id` WHERE `elinks`.`eclass_id` IS NULL

I would like to return The properties for a given class.

UPDATE: I added the foreign key declarations per one answer. But still recieve a similar error. This is the new error.

irb(main):001:0> @eclass = Eclass.first
  ←[1m←[36mEclass Load (140.6ms)←[0m  ←[1mSELECT `eclasses`.* FROM `eclasses` LIMIT 1←[0m
=> #<Eclass id: 1, class_id: "0161-1#TM-005740#1", concept_id: "0161-1#01-004609#1", concept_name: "ACTUATOR ASSEMBLY,STEERING COLUMN", language_id:
 "0161-1#LG-000001#1", created_at: "2009-06-08 20:28:00", updated_at: "2009-02-03 08:14:00">
irb(main):002:0> @props = @eclass.eproperties
  ←[1m←[35mEproperty Load (0.0ms)←[0m  SELECT `eproperties`.* FROM `eproperties` INNER JOIN `elinks` ON `eproperties`.`` = `elinks`.`pconcept_id` WH
ERE `elinks`.`concept_id` IS NULL
Mysql2::Error: Unknown column 'eproperties.' in 'on clause': SELECT `eproperties`.* FROM `eproperties` INNER JOIN `elinks` ON `eproperties`.`` = `el
inks`.`pconcept_id` WHERE `elinks`.`concept_id` IS NULL
ActiveRecord::StatementInvalid: Mysql2::Error: Unknown column 'eproperties.' in 'on clause': SELECT `eproperties`.* FROM `eproperties` INNER JOIN `e
links` ON `eproperties`.`` = `elinks`.`pconcept_id` WHERE `elinks`.`concept_id` IS NULL
        from c:/Ruby192/lib/ruby/gems/1.9.1/gems/activerecord-3.1.0/lib/active_record/connection_adapters/mysql2_adapter.rb:687:in `query'
        from c:/Ruby192/lib/ruby/gems/1.9.1/gems/activerecord-3.1.0/lib/active_record/connection_adapters/mysql2_adapter.rb:687:in `block in exec_qu
ery'
        from c:/Ruby192/lib/ruby/gems/1.9.1/gems/activerecord-3.1.0/lib/active_r
        from c:/Ruby192/lib/ruby/gems/1.9.1/gems/activesupport-3.1.0/lib/active_
        from c:/Ruby192/lib/ruby/gems/1.9.1/gems/activerecord-3.1.0/lib/active_r
        from c:/Ruby192/lib/ruby/gems/1.9.1/gems/activerecord-3.1.0/lib/active_r
        from c:/Ruby192/lib/ruby/gems/1.9.1/gems/activerecord-3.1.0/lib/active_r
        from c:/Ruby192/lib/ruby/gems/1.9.1/gems/activerecord-3.1.0/lib/active_r
ect_all'
        from c:/Ruby192/lib/ruby/gems/1.9.1/gems/activerecord-3.1.0/lib/active_r

        from c:/Ruby192/lib/ruby/gems/1.9.1/gems/activerecord-3.1.0/lib/active_r
        from c:/Ruby192/lib/ruby/gems/1.9.1/gems/activerecord-3.1.0/lib/active_r
        from c:/Ruby192/lib/ruby/gems/1.9.1/gems/activerecord-3.1.0/lib/active_r
        from c:/Ruby192/lib/ruby/gems/1.9.1/gems/activerecord-3.1.0/lib/active_r
et'
        from c:/Ruby192/lib/ruby/gems/1.9.1/gems/activerecord-3.1.0/lib/active_r
        from c:in `load_target'
        from c:/Ruby192/lib/ruby/gems/1.9.1/gems/activerecord-3.1.0/lib/active_r
        from c:/Ruby192/lib/ruby/gems/1.9.1/gems/railties-3.1.0/lib/rails/comman
        from c:/Ruby192/lib/ruby/gems/1.9.1/gems/railties-3.1.0/lib/rails/comman
        from c:/Ruby192/lib/ruby/gems/1.9.1/gems/railties-3.1.0/lib/rails/comman
        from script/rails:6:in `require'
Was it helpful?

Solution

I think you'll want to set the correct primary keys for each table, so I think it would look something like this.

class Eclass < ActiveRecord::Base
  set_primary_key :concept_id
  has_many :elinks, :foreign_key => :concept_id
  has_many :eproperties, :through => :elinks
end

class Elink < ActiveRecord::Base
  belongs_to :eclass, :foreign_key => :concept_id, :primary_key => :concept_id
  belongs_to :eproperty, :foreign_key => :pconcept_id, :primary_key => :pconcept_id
end

class Eproperty < ActiveRecord::Base
  set_primary_key :pconcept_id
  has_many :elinks, :foreign_key => :pconcept_id
  has_many :eclasses, :through => :elinks
end

OTHER TIPS

In the Elinks class I think you need to add the foreign key to the relationship:

has_many :elinks, :foreign_key => :concept_id
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top