Kobus Post Kobus Post - 1 month ago 6
Ruby Question

Static scope inside has_many in Rails 4

I'm having the following issue. I want to set a certain amount of has_many relations in a model, with names taken from a passed array (or in this case, the keys of a hash). Like this:

object_class_names = {:foo => FooClass, :bar => BarClass}

for key_name in object_class_names.keys
has_many "#{key_name}_objects".to_sym,
-> {where(var: key_name)},
:class_name => object_class_names[key_name]
end


This results in two has_many relations:
some_object.foo_objects
&
some_object.bar_objects
. Both have a specific class_name and a specific scope, set in the where clause in the lambda. However, because the scope is a lambda it gets the key_name in the where clause dynamically. This is the last known key_name variable, which is the last one in the loop, in this case 'bar'. So both
foo_objects
and
bar_objects
return a set of objects scoped with
where(var: "bar")
.

Usually the lambda makes a great way to pass in dynamic scopes in has_many relations, but in this case I don't really need it. Is it possible to set a static scope inside a has_many relation?

Answer

You might use Hash#each_pair here:

object_class_names.each_pair do |key_name, klass|
  has_many :"#{key_name}_objects", -> { where(var: key_name) }, class_name: klass.to_s
end