Ruby 在动态条件下使用lambda
我定义了一个与这样的动态条件有很多关联的函数:Ruby 在动态条件下使用lambda,ruby,ruby-on-rails-3,associations,conditional-statements,Ruby,Ruby On Rails 3,Associations,Conditional Statements,我定义了一个与这样的动态条件有很多关联的函数: class Checkin < ActiveRecord::Base has_many :evaluations, :conditions => proc {"evaluations.placement_id = #{self.placement_id}"} end 由于我更喜欢lambdas而不是procs,因此我尝试用lambda替换关联条件,但此尝试会导致错误: :conditions => lambda {"eval
class Checkin < ActiveRecord::Base
has_many :evaluations, :conditions => proc {"evaluations.placement_id = #{self.placement_id}"}
end
由于我更喜欢lambdas而不是procs,因此我尝试用lambda替换关联条件,但此尝试会导致错误:
:conditions => lambda {"evaluations.placement_id = #{self.placement_id}"}
> Checkin.find(1).evaluations.to_sql
ArgumentError: wrong number of arguments (1 for 0)
通过向lambda块提供参数,可以轻松修复该错误:
:conditions => lambda {|a| "evaluations.placement_id = #{self.placement_id}"}
> Checkin.find(1).evaluations.to_sql # a is nil inside of this lambda call!
=> "SELECT \"evaluations\".* FROM \"evaluations\" WHERE \"evaluations\".\"checkin_id\" = 1 AND (evaluations.placement_id = 2)"
传递参数没有区别,lambda的参数始终为零:
:conditions => lambda {|a| puts "a: #{a || 'undefined'}"; "evaluations.placement_id = #{self.placement_id}"}
Checkin.find(1).evaluations(5) # => has no effect on produced sql
a: undefined
# and here are returned evaluations
这种行为是由于
ActiveRecord::Associations::Association#interpolate
,当Rails根据条件确定关联范围时调用该函数。这个电话看起来像:
scope = scope.where(interpolate(condition))
以下是interpolate
方法的全文(来自3.2源代码:):
在该方法中,sql
是lambda条件,owner
计算为Checkin
实例
lambda响应到_proc
,因此满足条件。所以真正发生的事情是这样的:
Checkin.find(1).instance_exec(nil) {"evaluations.placement_id ... "}
这不起作用,因为nil
是一个参数,所以块应该有一个参数(您已经知道lambdas检查算术)。如果执行lambda{a |…}
,a
是nil
,因为record
是nil
(因为它的值没有传递给interpolate
方法,而nil
是默认值)。此行为是由于ActiveRecord::Associations::Association::Association
,当Rails确定与条件的关联范围时调用。这个电话看起来像:
scope = scope.where(interpolate(condition))
以下是interpolate
方法的全文(来自3.2源代码:):
在该方法中,sql
是lambda条件,owner
计算为Checkin
实例
lambda响应到_proc
,因此满足条件。所以真正发生的事情是这样的:
Checkin.find(1).instance_exec(nil) {"evaluations.placement_id ... "}
这不起作用,因为nil
是一个参数,所以块应该有一个参数(您已经知道lambdas检查算术)。当您执行lambda{a |…}
时,a
是nil
,因为record
是nil
(因为它的值没有传递给interpolate
方法,nil
是默认值)