質問

ローカル変数にアクセスできるクラスメソッドを定義したいと考えています。したがって、これはクラスのインスタンスごとに異なります。ラムダを使用して、named_scope で使用する場合と同様に、クラスメソッドを動的にできることはわかっています。しかし、インスタンスに固有の値に対してこれを実行できるでしょうか?

詳細には、rails のペーパークリップ プラグインの has_attached_file メソッドです。DB に保存されているオブジェクトの属性に基づいて画像スタイルを作成できるように、スタイル ハッシュのラムダを渡したいと考えています。これは可能でしょうか?

役に立ちましたか?

解決

免責事項: まず、質問(自分自身をラムダに渡すことはできますか?)と解決しようとしている問題(ペーパークリップを使用した動的スタイル)は完全には一致しません。元の質問にはお答えしません。それはあなたの問題と完全に関係がないためです。Rampion はそれに果敢に挑戦しました。

代わりに、あなたのペーパークリップの質問に答えます。

詳しく言えばそれは、 has_attached_file レールのペーパークリッププラグインのメソッド。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

他のヒント

[OK]を、あなたが不明確であることだ。

ルビーにおけるローカル変数は、(foobar、またはsteveなど)小文字で始まり、字句(C変数のように)スコープされています。彼らは、「クラスのインスタンス」とは何の関係もありません。

@の現在値がそれらが格納されているオブジェクトであるときはいつでも、

ルビーでインスタンス変数(@foo@bar、又は@carlなど)selfのシギルで始まり、および範囲内にある。

あなたが直接、オブジェクトのインスタンス変数にアクセスすることができます方法をしたい場合は、

、それはインスタンスメソッドと呼ばれています。例えば、battle_cryinitialize両方インスタンスメソッドである

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

クラスメソッドは、対照的に、Classオブジェクトのメソッドであり、そのオブジェクトのインスタンス変数のいずれかへのアクセス権を持っていません。上記の例では、 defaultは、クラスメソッドである。

あなたが変更をトリガーするか、現在のスコープから値を取得します(クラスまたはインスタンス)メソッドを使用する場合は、

、ルビーは、ブロックと呼ばれるコールバックのタイプを使用します。

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の戻り値として表示方法に関する。

ルビーのワードlambdaは通常使用されている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

その場合、あなたは、中間ハッシュでリクエストをキャッシュしたほうが良いかもしれません。これは、かなり簡単です。 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"]
ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top