dynamically get rails association
Asked Answered
P

3

10

If I have an association name as a string, is there a way I can get a handle on the association object?

For example:

o = Order.first

o.customer will give me the customer object that this order belongs to.

If I have:

o = Order.first
relationship = 'customer'

i would like to do something like:

customer = eval("o.#{relationship}")

I know eval is a terrible option and I should avoid it. What is the best way to do this (as eval does not work in this example).

I did have this working:

customer = o.association(relationship)

I later found out that the association is not part of the public API and should not be used. Because when I took a line of code I had higher up the page off (that referenced that relationship) it stopped working.

Any ideas would be awesome!

Pedicab answered 2/7, 2013 at 18:4 Comment(0)
N
20

What about just doing this?

customer = o.send(relationship)
Nagual answered 2/7, 2013 at 18:8 Comment(4)
The call to #to_sym isn't needed; send can handle strings.Corella
Wow, like magic! Is send a rails or ruby method? I couldn't find documentation on it. Incidentally, i've never used it so i have no idea how this is working. Thanks again!Pedicab
Send is a ruby method. It can also take arguments. You can find the documentation on #send here: ruby-doc.org/core-2.0/Object.html#method-i-sendNagual
Your answer was so quick it wont even let me accept it yet, I will in a few min, thanks!Pedicab
M
6

For those who fears using send:

o.association(relationship).scope
Minicam answered 2/5, 2019 at 7:59 Comment(0)
D
3

You can use try() which will allow you manage any undefined method errors if the relationship doesn't exist.

relationship = 'customer'
foo = 'foo'

customer = o.try(relationship)
# > [
#     [0] #<Customer...

customer = o.try(foo)
# > nil

vs send():

customer = o.send(relationship)
# > [
#     [0] #<Customer... 

customer = o.send(foo)
# > NoMethodError: undefined method `foo' for #<Order...
Drennen answered 26/9, 2015 at 0:55 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.