Ruby on rails 你能把赛尔夫传给轨道上的兰姆达吗?
我想定义一个可以访问局部变量的类方法。因此,对于类的每个实例,这都是不同的。我知道,可以使用lambda使类方法成为动态的,就像在命名的\u范围中使用它一样。但是,对于特定于实例的值,可以这样做吗Ruby on rails 你能把赛尔夫传给轨道上的兰姆达吗?,ruby-on-rails,ruby,ruby-on-rails-plugins,paperclip,Ruby On Rails,Ruby,Ruby On Rails Plugins,Paperclip,我想定义一个可以访问局部变量的类方法。因此,对于类的每个实例,这都是不同的。我知道,可以使用lambda使类方法成为动态的,就像在命名的\u范围中使用它一样。但是,对于特定于实例的值,可以这样做吗 具体来说,它是rails中回形针插件的has_attached_file方法。我想为样式散列传递一个lambda,这样图像样式就可以基于数据库中存储的对象的属性。这可能吗?好的,你还不清楚 ruby中的局部变量以小写字母开头(如foo,bar,或steve),并且在词汇范围内(如C变量)。它们与“类的
具体来说,它是rails中回形针插件的has_attached_file方法。我想为样式散列传递一个lambda,这样图像样式就可以基于数据库中存储的对象的属性。这可能吗?好的,你还不清楚 ruby中的局部变量以小写字母开头(如
foo
,bar
,或steve
),并且在词汇范围内(如C
变量)。它们与“类的实例”无关
ruby中的实例变量以@
符号开头(如@foo
、@bar
或@carl
),只要self
的当前值是它们存储的对象,它们就在范围内
如果您想要一个可以直接访问对象实例变量的方法,那就称为实例方法。例如,battle\u cry
和initialize
都是实例方法:
class Character
def initialize(name)
@name=name
end
def battle_cry
@name.upcase + "!!!"
end
def Character.default
new("Leeroy Jenkins")
end
end
相比之下,类方法是类
对象的方法,并且不能访问该对象的任何实例变量。在上面的例子中,
default
是一个类方法
如果您想要一个(类或实例)方法来触发当前范围中的更改或从当前范围中获取值,ruby将使用一种称为块的回调类型
class Character
ATTACKS = [ "Ho!", "Haha!", "Guard!", "Turn!", "Parry!", "Dodge!", "Spin!", "Ha", "THRUST!" ]
def attack
ATTACKS.inject(0) { |dmg, word| dmg + yield(word) }
end
end
person = Character.default
puts person.battle_cry
num_attacks = 0;
damage = person.attack do |saying|
puts saying
num_attacks += 1
rand(3)
end
puts "#{damage} points of damage done in #{num_attacks} attacks"
在上面的示例中,attack
使用yield
关键字调用传递的块
去吧。当我们调用attack
时,局部变量num\u attacks
仍然是
在块的作用域中,我们传递它(在这里由do…end
分隔),因此我们可以
增加它<代码>攻击可以在此处将值传递到块中
它们被捕获到saying
变量中。块还传递值
返回方法,它显示为yield
的返回值
ruby中的lambda
一词通常指lambda
关键字,使用该关键字
使块成为独立的、功能类似的对象(通常是
称为lambda
s、proc
s或proc
s)
所以我想你要问的是你是否可以通过Proc
来代替Hash
用于方法的参数。答案是“视情况而定”。如果只使用方法
是否曾经使用过#[]
方法,然后是:
class Character
attr_accessor :stats
def set_stats(stats)
@stats = stats
end
end
frank = Character.new("Victor Frankenstein")
frank.set_stats({ :str => 7, :dex => 14, :con => 9, :int => 19, :wis => 7, :cha => 11 })
monster = Character.new("Frankenstein's Monster")
monster.set_stats(lambda do |stat_name|
rand(20)
end)
但是,它可能会使用一些其他的散列
特定方法,或者多次调用同一个键,
这会产生奇怪的结果:
monster = Character.new("Frankenstein's Monster")
monster.set_stats(lambda do |stat_name|
rand(20)
end)
monster.stats[:dex] #=> 19
monster.stats[:dex] #=> 1
在这种情况下,最好将请求缓存在中间哈希中。这相当容易,,
因为散列
可以有初始值设定项块。因此,如果我们将上述内容更改为:
monster.set_stats(Hash.new do |stats_hash, stat_name|
stats_hash[stat_name] = rand(20)
end)
monster.stats[:dex] #=> 3
monster.stats[:dex] #=> 3
结果缓存在散列中
要查看有关哈希
块初始值设定项的更多信息,请参阅ri Hash::new
:
-------------------------------------------------------------- Hash::new
Hash.new => hash
Hash.new(obj) => aHash
Hash.new {|hash, key| block } => aHash
------------------------------------------------------------------------
Returns a new, empty hash. If this hash is subsequently accessed
by a key that doesn't correspond to a hash entry, the value
returned depends on the style of new used to create the hash. In
the first form, the access returns nil. If obj is specified, this
single object will be used for all default values. If a block is
specified, it will be called with the hash object and the key, and
should return the default value. It is the block's responsibility
to store the value in the hash if required.
h = Hash.new("Go Fish")
h["a"] = 100
h["b"] = 200
h["a"] #=> 100
h["c"] #=> "Go Fish"
# The following alters the single default object
h["c"].upcase! #=> "GO FISH"
h["d"] #=> "GO FISH"
h.keys #=> ["a", "b"]
# While this creates a new default object each time
h = Hash.new { |hash, key| hash[key] = "Go Fish: #{key}" }
h["c"] #=> "Go Fish: c"
h["c"].upcase! #=> "GO FISH: C"
h["d"] #=> "Go Fish: d"
h.keys #=> ["c", "d"]
免责声明:首先,问题(你能把self传递给lambda吗?)和你试图解决的问题(带回形针的动态样式)并不完全匹配。我不会回答最初的问题,因为它与你的问题并不完全相关,而兰皮恩对此进行了勇敢的尝试 我来回答你的回形针问题。 详细地说,这是rails中回形针插件的
附加了文件方法。我想为样式散列传递一个lambda,这样图像样式就可以基于数据库中存储的对象的属性。这可能吗
是的,这是可能的。在回形针中,:styles
选项可以执行一个过程。初始化附件时,如果使用了Proc,则附件本身将传递给Proc。附件引用了关联的ActiveRecord对象,因此您可以使用它来确定动态样式
例如,您的has_attached_文件
声明可能如下所示(假设用户和化身场景中,用户可以自定义其化身的大小):
class用户lambda{| attachment |
user=attachment.instance
维度=“#{user.avatar_width}x#{user.avatar_height}”
{:custom=>dimensions}
}
结束
您能澄清一下吗?这个lamdba是否由has\u attached\u文件代码调用,因此您无法控制?因为您可以在调用lamdba时将参数传递给它们,并且可以像传递其他参数一样轻松地传递“self”。谢谢Ryan,这正是我想要的。@bwizzy-您应该单击Ryan答案旁边的复选标记,注意:(1)他回答了您的问题,(2)奖励他这么做。谢谢,抱歉,这是我的第一篇帖子。感谢所有的快速回复和详细信息。我面临着同样的问题,并使用@ryan mcgeary建议的方法解决了它。但我还需要使用延迟的_作业,所以实例变量无法工作。我怎样才能解决这个问题?
-------------------------------------------------------------- Hash::new
Hash.new => hash
Hash.new(obj) => aHash
Hash.new {|hash, key| block } => aHash
------------------------------------------------------------------------
Returns a new, empty hash. If this hash is subsequently accessed
by a key that doesn't correspond to a hash entry, the value
returned depends on the style of new used to create the hash. In
the first form, the access returns nil. If obj is specified, this
single object will be used for all default values. If a block is
specified, it will be called with the hash object and the key, and
should return the default value. It is the block's responsibility
to store the value in the hash if required.
h = Hash.new("Go Fish")
h["a"] = 100
h["b"] = 200
h["a"] #=> 100
h["c"] #=> "Go Fish"
# The following alters the single default object
h["c"].upcase! #=> "GO FISH"
h["d"] #=> "GO FISH"
h.keys #=> ["a", "b"]
# While this creates a new default object each time
h = Hash.new { |hash, key| hash[key] = "Go Fish: #{key}" }
h["c"] #=> "Go Fish: c"
h["c"].upcase! #=> "GO FISH: C"
h["d"] #=> "Go Fish: d"
h.keys #=> ["c", "d"]
class User < ActiveRecord::Base
has_attached_file :avatar, :styles => lambda { |attachment|
user = attachment.instance
dimensions = "#{user.avatar_width}x#{user.avatar_height}#"
{ :custom => dimensions }
}
end