سؤال

أريد تحديد طريقة الفصل التي لديها حق الوصول إلى متغير محلي. لذلك سيكون هذا مختلفا عن كل حالة من الفصل. أعلم أنه يمكنك جعل طريقة الفصل الديناميكية مع Lambda مثل عند استخدامه مع Named_scope. ولكن هل يمكن القيام بذلك للقيم المحددة بمثيل؟

بالتفصيل، إنها طريقة HAS_ATTACHED_FILE للمكون الإضافي PaperClip في القضبان. أرغب في اجتياز Lambda لصالح الأنماط بحيث يمكن أن تعتمد أنماط الصور من سمات الكائن المخزن في DB. هل هذا ممكن؟

هل كانت مفيدة؟

المحلول

تنصل: أولا، السؤال (يمكنك تمرير النفس إلى لامبادا؟) والمشكلة التي تحاول حلها (أنماط ديناميكية مع PaperClip) لا تتطابق تماما. لن أجيب على السؤال الأصلي لأنه غير مرتبط تماما بمشكلتك، واتخذت Rampion طعنة بساطة في ذلك.

سأجيب بدلا من ذلك عن سؤالك الوربي.

بالتفصيل هو has_attached_file طريقة للحصول على البرنامج المساعد PaperClip في القضبان. أرغب في اجتياز Lambda لصالح الأنماط بحيث يمكن أن تعتمد أنماط الصور من سمات الكائن المخزن في DB. هل هذا ممكن؟

نعم هذا ممكن. في paperclip، :styles الخيار يمكن أن تأخذ proc. عند تهيئة المرفق، إذا تم استخدام بروك، يتم تمرير المرفق نفسه إلى Proc. يحتوي المرفق على إشارة إلى كائن ActiverCord المقترن، حتى تتمكن من استخدام ذلك لتحديد أنماط ديناميكية.

على سبيل المثال، الخاص بك 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

نصائح أخرى

حسنا، أنت غير واضح.

المتغيرات المحلية في روبي تبدأ بحرف صغير (مثل foo, bar, ، أو steve)، ومجموعة معجمية (مثل C المتغيرات). ليس لديهم علاقة "بمثيل فئة"

المتغيرات المثلية في روبي تبدأ ب @ سيجيل (مثل @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.

الكلمة lambda في روبي عادة ما يعني lambda الكلمة الرئيسية، التي يتم استخدامها لصنع كتل في Freestanding، وظيفة مثل الكائنات (والتي تشار إليها عادة باسم lambdaس، procS، أو Procس).

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