I’m pretty new with Ruby and have been struggling for a while how to
make work a join between tables on a non-standard schema. I know the
proper way of doing it would be migrating the schema and using the
ActiveRecord convention but as long as I’m using this to consume
existing data for testing purposes, that’s not an option.
Tables:
AGREEMENTS
AGREEMENT_TYPES
Both tables contain a column ‘AGREEMENT_TYPE_ID’ that could be used for
the join. It is also the primary key for the ‘AGREEMENT_TYPES’ table.
This is the models definition:
class Agreement < ActiveRecord::Base
self.table_name = ‘AGREEMENTS’
self.primary_key = ‘AGREEMENT_ID’
has_one :AgreementType, :primary_key => ‘AGREEMENT_TYPE_ID’,
:foreign_key => ‘AGREEMENT_TYPE_ID’
end
class AgreementType < ActiveRecord::Base
self.table_name = ‘AGREEMENT_TYPES’
self.primary_key = ‘AGREEMENT_TYPE_ID’
belongs_to :Agreement, :primary_key => ‘AGREEMENT_TYPE_ID’,
:foreign_key => ‘AGREEMENT_TYPE_ID’
end
What I wanted to achive is to consume a field called ‘name’ from the
AGREEMENT_TYPES table. This is the instantiation:
puts Agreements.joins(:Agreement_Types).explain
EXPLAIN for: SELECT “AGREEMENTS”.* FROM “AGREEMENTS” INNER JOIN
“AGREEMENT_TYPES” ON “AGREEMENT_TYPES”.“AGREEMENT_TYPE_ID” =
“AGREEMENTS”.“AGREEMENT_ID”
Using include also seems to list only the AGREMENTS fields:
irb(main):081:0> puts @agr.name
NoMethodError: undefined method `name’ for #Array:0x1cfb258
There’s a reason to use meaningful names
In this case your variable should be @agreements (plural) because
an ActiveRecord find all returns an array, which of course has no
‘name’ method though e.g. @agreements.first.name should work.
Note that the error message is telling you exactly that
Which returned:
NoMethodError: undefined method name' for #<Agreement:0x1571ac0> from C:/tools/Ruby193/lib/ruby/gems/1.9.1/gems/activemodel-3.2.7/lib/active_model/attribute_methods.rb:407:inmethod_missing’
from
C:/tools/Ruby193/lib/ruby/gems/1.9.1/gems/activerecord-3.2.7/lib/active_record/attribute_methods.rb:149:in method_missing' from (irb):25 from C:/tools/Ruby193/bin/irb:12:in’
But if I try
@agreements.first.agreement_id U(which is a field on the Agreements
table), it works correctly.
This is probably not gonna be helpful, but… have you tried using an
ORM that isn’t inherently broken, for example Sequel? I’ve used it
once for interfacing with external database and had no problems
setting up a join across eight tables with variously named fields. I
can post bits of my code if you wish.
@Hassan I thought I should use AgreementType in the has_one clause as
this is how I’m naming the class I’m refering to. I’m a bit lost now.
@Matma, thanks for the advice. I’m gonna give it a try a couple more
hours and if I don’t progress I will go back to Sequel, which is was I
was using before. Just wanted to take the oportunity to learn a bit
about AR, but it’s maybe worth doing so when creating a new schema.
@Hassan I thought I should use AgreementType in the has_one clause as
this is how I’m naming the class I’m refering to. I’m a bit lost now.
Please read the Rails guide for ActiveRecord relationships,specifically
the “has_one”/“belongs_to” examples. Look at which one of those is
applied to the model that includes the foreign key. And of course look
at the syntax of the entries.
AR will handle your schema fine, if you set up your models properly.
This forum is not affiliated to the Ruby language, Ruby on Rails framework, nor any Ruby applications discussed here.