views:

48

answers:

3

I need to access a legacy relational database via ActiveRecord and that database uses a column named "object_id" as a primary key in a table. Most things work but when I try specify a custom SQL query for an association (see below) ActiveRecord respectively the Ruby interpreter always retrieves the object_id of the Ruby base "Object" instead of the column value from the database.

I defined the following SQL query in a has_many declaration:

:finder_sql => "SELECT * FROM t_object WHERE object_id IN (SELECT end_object_id FROM t_object, t_connector WHERE t_object.object_id = #{object_id} AND start_object_id = #{object_id})

I already tried to solve it by working with an alias:

alias_attribute :my_oid, :object_id

and using "my_oid" in the SQL query. But I got the following error message:

NameError: undefined local variable or method `my_oid' for EaTObject(Table doesn't exist):Class

I also defined a method which returns the value of read_attribute("object_id") and put the method name into the SQL query instead of "object_id" but when the class was loaded I got the error message that that method name is not a column name in the database table.

Is there any solution to access a column called "object_id"?

+3  A: 

You can use this method:

read_attribute(:object_id)

The link in documentation :

http://api.rubyonrails.org/classes/ActiveRecord/AttributeMethods/Read.html#method-i-read_attribute

So if you want access to your object_id column whan you call oid you need delete your alias and define the oid method

def oid
  read_attribute(:object_id)
end
shingara
When I use #{read_attribute(:object_id)} in :finder_sql I get the error "NoMethodError: undefined method `read_attribute' for EaTObject(Table doesn't exist):Class".
zeppeli
it seems you haven't this table in your database
shingara
I tried the SQL query directly in the database with a concrete value for the object_id and it worked. The error message is only there when I don't put a column name into #{}.
zeppeli
I really don't understand your case. We need more code to understand. Update your question or ask another
shingara
You don't need other stuf than read_attributes. So delete your alias and use only read_attributes(:object_id) in your oid methode
shingara
A: 

You may use t_object.object_id in your SQL to specify object_id field, or you may alias your t_object table, e.g.

:finder_sql => "SELECT * FROM t_object AS t WHERE t.object_id IN..."
buru
Thanks. I tried it but it didn't work. In my opinion the problem is #{object_id} in the SQL query because this calls the inherited method object_id of the Ruby class "Object" and not the method generated by ActiveRecord::Base. I also could not replace #{object_id} by something else because ActiveRecord wants a column name in :finder_sql.
zeppeli
A: 

Another option is self[:object_id], but if you are getting "Table doesn't exist", then maybe there is something else wrong?

Edit: Try this:

:finder_sql => 'SELECT * FROM t_object WHERE object_id IN (SELECT end_object_id FROM t_object, t_connector WHERE t_object.object_id = #{id} AND start_object_id = #{id})'

NB! single quotes.

ormuriauga
When I put self[:object_id] into the :finder_sql query I get the same error message. I tried the SQL query directly in the database with a concrete value for the object_id and it worked. The error message is only there when I don't put a column name into #{}.
zeppeli
of what type are the `object_id` and `start_object_id`?
ormuriauga
Actually, I think you need to use `#{id}` instead of `object_id` and it will work. Try it
ormuriauga
Thanks, the single quotes are the solution.
zeppeli