Ruby on rails 你能把赛尔夫传给轨道上的兰姆达吗?

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变量)。它们与“类的

我想定义一个可以访问局部变量的类方法。因此,对于类的每个实例,这都是不同的。我知道,可以使用lambda使类方法成为动态的,就像在命名的\u范围中使用它一样。但是,对于特定于实例的值,可以这样做吗


具体来说,它是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