2012-05-25 22 views
5

Bir ActiveRecord modelini (Vote) uygulamayıma bir mücevher (https://github.com/peteonrails/vote_fu) sağlamaya çalışıyorum. Benim ilk yaklaşım, bir dosya kodunu içerdiğini lib/extend_vote.rb denilen yaratmaktıBir mücevher tarafından sağlanan bir ActiveRecord modelini yeniden açın

(Yani, app/models hiçbir vote.rb yoktur):

Vote.class_eval do 
    after_create :create_activity_stream_event 
    has_one :activity_stream_event 

    def create_activity_stream_event 
    # something.. 
    end 
end 

bu ilk oy oluşturulduğunda çalışır, ancak ben çalıştığınızda Sonraki her oyu oluşturmak için TypeError (can't dup NilClass) hatasını aldım.

Bu hata Vote sınıf her istekten sonra otomatik olarak tekrar edilir, ancak bu has_one :activity_stream_event dernek tekinsizce davranmaya sunucu başlar ve neden olduğunda lib/extend_vote.rb kod sadece bir kez yüklenir gerçeğiyle kaynaklanır düşünüyorum.

config.to_prepare do 
    load 'extend_vote.rb' 
end 

:

Bu sorunu çözmek için (Ayrıca, sorun ben config.cache_classes = truedevelopment.rb belirlenen eğer uzağa gider), ben benim development.rb bir to_prepare blok ekleyerek uzantıları her istekte yeniden oylama yapmaya çalıştı Bu, (can't dup NilClass) sorununu çözer, ancak şimdi yeni bir oy oluşturduğumda, create_activity_stream_event geri arama ek süre çağrılır. İlk olarak, ilk oylama bir kez, ikinci kez iki kez, vb. Olarak adlandırılır. Yani to_prepare bloğu, ag'ı agresif olarak yeniden yükleyerek yinelenen geri aramalar ekliyor gibi görünüyor.

Bu Vote modeline yöntemler ve geri bildirimler eklemenin en iyi yolu nedir?

+1

"Vote.class_eval" yerine "sınıf oyu" kullanırsanız işe yarar mı? Yapabileceğin bir şey de kodu geminin kendisinde düzenlemek ve sadece değiştirilmiş versiyonunu kullanmak. – agmcleod

+0

'sınıf Oylama ', Vote.class_eval' ile aynı davranır - ne işe yaramıyor. Ben gem değiştirebilir sanırım, ama gerçekten gerçekten lol istemiyorum. Ne dağınıklık! –

+0

Oylama sınıfının yeniden yüklenmesinden neden sandınız? Reşitlik içinde, sınıf lib dizinindedir, bu yüzden sizden de aynıdır ... – Dougui

cevap

1

ben istiyorum Yorum önerilen ancak bunun yerine lib koyma, config/başlatıcıları/vote.rb koymak agmcleod deneyen: Elbette

class Vote 
    after_create :create_activity_stream_event 
    has_one :activity_stream_event 

    def create_activity_stream_event 
    # something.. 
    end 
end 

, sen mücevher çatal olabilir , değişikliklerinizi yapın ve Gemfile'daki çatallı sürümünüze bağlantı verin (bu benim tercihim). Bunun senin fonksiyonu ve arama fonksiyonlarını "after_create" ve "has_hone" katacak daha düşünmek

class Vote 
    after_create :create_activity_stream_event 
    has_one :activity_stream_event 

    def create_activity_stream_event 
     # something.. 
    end 
end 

:

+0

niçin 'lib' yerine' config/initializer '?'Load' deyimini' to_prepare' bloğunda tutmam gerektiğini mi tahmin ediyorum? –

+0

nope, başlatıcı dosyalarındaki öğeler tüm ortamlar için başlangıçta bir kez yüklendiğinden, bu yükleme ifadesine gerek duymamalıdır. – miked

+0

Bu işe yaramıyor - 'load '' to_prepare' bloğunda bırakılırsam, dosya 'lib''deyken aldığım aynı hatayı alıyorum. Yükü kaldırırsam, o zaman (NilClass'ı kaldıramıyor) hata –

0

böyle bir şey deneyebilirsin.

+0

Üzgünüm, agmcleod'un yorumunu görmedim. Muhtemelen aynı düşüncedir ... Çalışmalı ama değil. – Dougui

+0

heh, en azından benim yaptığım gibi bir oylama yapmadın ... ve önerilerimiz de aynıydı! lol – miked

+0

Bunun nedeni, bir başlatıcıya koymayı söylemeniz olabilir. Ya da, ben senin peşinden söyleyebilirim. – Dougui

4

Dikkatli olun: Bu çok eski bir gem (son işlem 3 yaşında) ve görünüşüne göre raylar ile çalışmayacak 3.x. Rails 3.x motorlarında bu tarz işleri kolaylaştırır.

Anladığım kadarıyla ilk durumda sorun, oy modelinin yeniden yüklenmemesi (bu olmamalı) değil, activity_stream_event modelinin yeniden yüklenmesidir. Oylama modeli yeniden yüklenmediğinden, ilişkilendirme yeniden yüklemeden önce activity_stream_event sınıfının sürümüne iliştirilir. Raylar, yeniden yüklenmeden önce sınıfları ortaya çıkardığından, bu sorunlara neden olur. Bu politika, taş birinden devraldığı kendi Oy sınıfı için izin olduğunu

#in config/initializers/abstract_vote.rb 
AbstractVote = Vote 
AbstractVote.abstract_class = true 
Object.send :remove_const, :Vote 

#in app/models/vote.rb 

class Vote < AbstractVote 
    after_create :create_activity_stream_event 
    has_one :activity_stream_event 

    def create_activity_stream_event 
    end 
end 

: madeninde Bununla

, bu kesmek deneyin.

Ama yine, ben bugüne kadar daha çok şey bulmak ya da (gem yakut sadece ~ 250 hatları) kendi rulo çağırıyorum

6

[GÜNCELLEME: modül varlık içerir önlemek için doğru çözüm olmalıdır Aynı sınıfta birkaç kez]

Modülün, birkaç kez çağrılan geri arama sonucunda birkaç kez dahil olmasını önlemek için ActiveSupport::Concern'u kullanabilirsiniz. örnek aşağıya bakın:

module VotePatch 
    extend ActiveSupport::Concern 

    included do 
    after_create :create_activity_stream_event 
    has_one :activity_stream_event 
    end 

    module InstanceMethods 
    def create_activity_stream_event 
     #your code here 
    end 
    end 

end 

Vote.send(:include, VotePatch) 
+0

cevabımı güncelledim, ActiveSupport :: Concern'in sorununuzu çözeceğine inanıyorum –

0

Kişisel Mesele, sen maymun sınıfını yama olmasından kaynaklanıyor olabilir. Raylar sabitlerini yeniden yüklemeye çalıştığında dosyanızı düşünmüyor.

Aşağıda verilen modül tekniğini kullanmayı deneyin.

ekle denilen bir başlatıcı

module VoteFuExtension 
    def self.included(base) 
    base.has_one :activity_stream_event 
    base.after_create :create_activity_stream_event 
    end 
    def create_activity_stream_event 
    # something.. 
    end 
end 
Vote.send(:include, VoteFuExtension) 

lib/vote_fu_extension.rb adlı bir dosya ekleyin config/initializers/vote_fu.rb

require "vote_fu_extension" 

Not

bu answer bakın Vote modeline sınıf yöntemleri eklemek istiyorsanız .

Utanmaz fiş: vote_fu geminin fork ürünümün bazı yeni özellikleri ve donanımları vardır.

1

Adrien Coquio, modelleri genişletmek için ActiveSupport::Concerns olan the Rails way ile doğru fikre sahiptir. Kodu işe yarayacak ve kullanmalısın.

Ancak bu, geliştirme sırasında her zaman çalışmayacaktır çünkü Rails bir dosya değiştiğinde sınıflarınızı yeniden yüklediğinde, #send satırını yeniden değerlendirmeyecektir. Eğer config true cache_classes ayarlarsanız üretiminde

if Rails.env.development? 
    ActionDispatch::Callbacks.to_prepare do 
    require_dependency "../../lib/vote_fu_extensions" 
    end 
end 

veya, yandınız: Ben dosyayı sağlamak için üretimde bir ActionDispatch callback'inde takılarak oldu bulabildiğim tek çözüm her sayfa yüklemesinden sonra-Gerekli yeniden olduğunu Bunu yapmam gerek.

İlgili konular