当前位置:  开发笔记 > 编程语言 > 正文

你能把自己传给lambda的铁轨吗?

如何解决《你能把自己传给lambda的铁轨吗?》经验,为你挑选了2个好方法。

我想定义一个可以访问局部变量的类方法.因此,对于每个类的实例,这将是不同的.我知道你可以使用lambda创建一个类方法动态,就像你在named_scope中使用它一样.但是,这可以针对特定于实例的值完成吗?

详细说明,它是rails中paperclip插件的has_attached_file方法.我想为样式哈希传递lambda,以便图像样式可以基于存储在DB中的对象的属性.这可能吗?



1> Ryan McGeary..:

免责声明:首先,问题(你能将自己传递给lambda吗?)和你试图解决的问题(使用回形针的动态样式)并不完全匹配.我不会回答原来的问题,因为它与你的问题并不完全相关,而且猖獗地对它进行了勇敢的抨击.

我会回答你的回形针问题.

详细地说,它是has_attached_file轨道中的回形针插件的方法.我想为样式哈希传递lambda,以便图像样式可以基于存储在DB中的对象的属性.这可能吗?

对的,这是可能的. 在回形针中,该:styles选项可以采用Proc.初始化附件时,如果使用Proc,附件本身将传递给Proc.附件具有对关联的ActiveRecord对象的引用,因此您可以使用它来确定动态样式.

例如,您的has_attached_file声明可能看起来像这样(假设用户和头像场景,用户可以自定义其头像的大小):

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



2> rampion..:

好的,你还不清楚.

在红宝石局部变量以小写字母开头(如foo,barsteve),并词法范围(如C变量).它们与"一个类的实例"无关

ruby中的实例变量以@sigil(如@foo,, @bar@carl)开头,并且只要当前值self是它们存储的对象,它们就在范围内.

如果您想要一个可以直接访问对象的实例变量的方法,那就称为实例方法.例如,battle_cry并且initialize都是实例方法:

class Character
  def initialize(name)
    @name=name
  end
  def battle_cry
    @name.upcase + "!!!"
  end
  def Character.default
    new("Leeroy Jenkins")
  end
end

相反,类方法是Class对象的方法,并且不能访问该对象的任何实例变量.在上面的例子中, 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_attacks仍然在我们传递它的块中(在此分隔do ... end),因此我们可以增加它. attack能够将值传递到块中,在这里它们被捕获到saying变量中.该块还将值传递回方法,该方法显示为返回值yield.

lambdaruby中的单词通常表示lambda关键字,用于使块成为独立的,类似于对象的函数(它们本身通常称为lambdas,procs或Procs).

bounce = lambda { |thing| puts "I'm bouncing a #{thing}" }
bounce["ball"]
bounce["frog"]

所以我认为你所要问的是你是否可以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)

但是,它可能会使用其他一些Hash特定的方法,或者多次调用相同的键,这会产生奇怪的结果:

monster = Character.new("Frankenstein's Monster")
monster.set_stats(lambda do |stat_name|
  rand(20)
end)

monster.stats[:dex] #=> 19
monster.stats[:dex] #=> 1

在这种情况下,您可能最好在中间散列中缓存请求.这很容易,因为a Hash可以有一个初始化块.因此,如果我们将上述内容更改为:

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

结果缓存在哈希中

要了解更多关于Hash块初始化,请参阅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"]

推荐阅读
mobiledu2402851173
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有