2016-07-06 23 views
13

Bir find_by özelliği için birkaç yöntem oluşturmak istiyorum. Aynı şeyi tekrar tekrar yazmak istemiyorum, bu yüzden meta programlamayı kullanmak istiyorum.define_method: Bağımsız değişkenlerle yöntemler dinamik olarak nasıl oluşturulur

Ad olarak bulmak için bir argüman olarak ismini kabul etmek için bir yöntem oluşturmak istediğimi varsayalım. Bunu nasıl yaparım? Geçmişte define_method kullandım, ancak almanın yöntemi için herhangi bir argümanım yoktu. İşte benim (kötü) bir yaklaşım

["name", "brand"].each do |attribute| 
    define_method("self.find_by_#{attribute}") do |attr_| 
     all.each do |prod| 
     return prod if prod.attr_ == attr_ 
     end 
    end 
    end 

Herhangi bir düşünce var? Şimdiden teşekkürler.

+0

Tümünün büyük bir veri kümesinin olup olmadığına dikkat edin, bunun performans sorunlarına neden olabileceğini unutmayın. Ayrıca içtenlikle, rayların zaten her bir özellik için 'find_by_XXX' değerini uyguladığı için rayların dışında kalmasını umuyorum. – engineersmnky

+1

Not: Bu, 'self.find_by_name' ve' self.find_by_brand' adlı iki yöntemi tanımlayacaktır. Bu yöntemlerin oluşturulması mümkün olsa da, normal yöntem çağırma sözdizimini kullanarak bunları çağırmak imkansızdır, çünkü '.' bir tanımlayıcıda yasal bir karakter değildir. Bir yöntemi yasal olmayan bir adla tanımlamak istediğiniz belirli bir neden var mı? –

+0

@engineersmnky Ray değil! hepsi sadece bir Oyuncak mağazasının envanter sistemi için bir 'Ürünler 'dizisi döndürür. Udacity'deki Ruby Nanodegree'nin final projesi için. –

cevap

19

aynıdır:

class Product 
    class << self 
    [:name, :brand].each do |attribute| 
     define_method :"find_by_#{attribute}" do |value| 
     all.find {|prod| prod.public_send(attribute) == value } 
     end 
    end 
    end 
end 

(all yönteminin bir Enu döndürdüğünü varsayalım . Merable)

üzerinde bu gibi iki sınıf yöntemleri tanımlayan daha fazla veya daha az eşdeğerdir:

class Product 
    def self.find_by_name(value) 
    all.find {|prod| prod.name == value } 
    end 

    def self.find_by_brand(value) 
    all.find {|prod| prod.brand == value } 
    end 
end 
+0

Bu benim için çalışıyor ama ... Burada nasıl olduğunu açıklayabilir misiniz? “Sınıf << kendini” aradım ve bir sınıf açtığını ve davranışını değiştirdiğini gördüm, ama neden bunu sınıfın içinde yapmam gerekiyordu? –

+1

Bir sınıf yöntemi tanımlamak istediğiniz için bunu yapmanız gerekir. Bu olmadan "define_method" bir örnek yöntemi ve "define_method (" self ") tanımlayacaktır.foo "), örneğinizdeki gibi çalışmıyor. –

+0

Çok teşekkür ederim! Meta programlamasında daha rahat olabilmek için daha fazla bakacağım ama şimdilik bana çok yardımcı oldunuz! :) –

1

It Bunu bir bulacaksınız burada http://apidock.com/ruby/Module/define_method örnekler okursanız:

define_method(:my_method) do |foo, bar| # or even |*args| 
    # do something 
end 

Sorunuzu doğru anladıysam, böyle bir şey istiyorum

def my_method(foo, bar) 
    # do something 
end 
+1

Bu bana bir NoMethodError vermeyi sürdürüyor:/ –

1

Bunu yaparken: define_method("self.find_by_#{attribute}") yanlış

. Define_method argümanı, tek kelimeli bir semboldür.

Sana birkaç doğru kodu göstereyim, umarım bu net olacak:

class MyClass < ActiveRecord::Base 
    ["name", "brand"].each do |attribute| 
    define_method(:"find_by_#{attribute}") do |attr_| 
     first(attribute.to_sym => attr_) 
    end 
    end 
end 

Bu find_by_brand ve find_by_name için sınıf yöntemleri üretecek.

Meta programlamaya bakıyorsanız, bu metod_missing için iyi bir kullanım vakası olduğunu unutmayın. here's a tutorial method_missing için kullanacağınız aynı işlevselliği uygulamak için (find_by_<x>)

+2

olduğunu belirtmek için teşekkürler Eğer bu, bu daha fazla raylar ise, "find_by_XXX" olduğundan işe yaramaz bir egzersiz Ayrıca tanımlanan "define_method" sorunu olmayan bir String'i de kabul edebilir – engineersmnky

+0

'method_missing' nefret ettiğim bir şeydir.Bu şekilde tanımlanan yöntemleri bulmanın kolay bir yolu yoktur.Mümkün olanı engelleyin – akostadinov

+0

@akostadinov –

İlgili konular