Reputation: 889
I'm trying to do something like this, where the send method's block has block arguments:
klass.attribute_names.each do |attribute|
klass.send(define_method("next_by_" + attribute) { object, user = nil
if user
klass.joins(:users).where("#{attribute} > ?", object.send(attribute)).where(users: {id: user.id}).first
else
klass.where("#{attribute} > ?", object.send(attribute)).first
end
})
end
Which isn't valid Ruby. Is this possible to do, and if so what is the best way to do so?
EDIT: I realize the reserved keyword "class" here. It is simply for illustration purposes. I've changed it to klass to prevent further confusion.
More detail, this is the entire file:
module Helpers::ResourceRecordHelper
# Remove this and call upon the module's methods to include instead to fix performance hit
def self.included(source)
define_class_methods(source)
end
def define_class_methods(source)
source.attribute_names.each do |attribute|
# These defined methods never reach the class
define_method("next_by_" + attribute) { object, user = nil
if user
self.class.joins(:users).where("#{attribute} > ?", object.send(attribute)).where(users: {id: user.id}).first
else
self.class.where("#{attribute} > ?", object.send(attribute)).first
end
}
define_method("previous_by_" + attribute) do object, user = nil
if user
self.class.joins(:users).where("#{attribute} < ?", object.send(attribute)).where(users: {id: user.id}).last
else
self.class.where("#{attribute} < ?", object.send(attribute)).last
end
end
end
def source.next(object, user = nil)
source.next_by_id(object, user)
end
def source.previous(object, user = nil)
source.previous_by_id(object, user)
end
end
extend self
end
Upvotes: 1
Views: 838
Reputation: 52347
You have few issues, like using reserved words, not understanding the self
(or rather not implementing your understanding correctly).
source.attribute_names.each do |attribute|
source.singleton_class.instance_eval do
define_method('next_by_' + attribute) do |object, user = nil|
if user
source.joins(:users)
.where("#{attribute} > ?", object.public_send(attribute))
.where(users: { id: user.id })
.first
else
source.where("#{attribute} > ?", object.public_send(attribute)).first
end
end
end
end
Upvotes: 1