Reputation: 5996
In a Rails (5.0) app, I have the following
class Batch < ApplicationRecord
belongs_to :zone, optional: false
end
class Zone < ApplicationRecord
scope :lines, -> { where(kind: 'line') }
end
Now I need to define in Batch
a scope for each Zone
which is a line. Something like the code below works.
Zone.lines.map(&:name).each do |name|
scope "manufactured_on_#{name}".to_sym, -> { joins(:zone).where("zones.name = '#{name}'") }
end
The issue is that the code above is evaluated when the app boots and at that time the scopes are created. If I add a newZone
of kind line
, the scope is not created.
Is there a way to solve this issue?
Upvotes: 0
Views: 365
Reputation: 3251
If you really need the scope name to be dynamic you can use method_missing as below:
class Batch < ApplicationRecord
belongs_to :zone, optional: false
def self.method_missing(name, *args)
method_name = name.to_s
if method_name.start_with?('manufactured_on_')
zone_name = method_name.split('manufactured_on_')[1]
joins(:zone).where(zones: { name: zone_name } )
else
super
end
end
def self.respond_to_missing?(name, include_private = false)
name.to_s.start_with?('manufactured_on_') || super
end
end
Now, you can call this scope as normal:
Batch.manufactured_on_zone_a
Upvotes: 0
Reputation: 9002
You can look into documentation and search for method_missing
.
But this does not seem a good approach to me.
Instead, define scope in following way:
class Batch < ApplicationRecord
scope :manufactured_on, ->(line) { joins(:zone).where("zones.name = '#{name}'") }
end
Then simply use
Batch.manufactured_on(zone.name)
Upvotes: 0
Reputation: 1238
You could pass the zone's name as a scope param
scope :manufactured_on, -> (name) { joins(:zone).where(zones: { name: name } ) }
Upvotes: 3