2010-10-07 14 views
5

Temel olarak yapmak istediğim, MyModelLog tablosunda MyModel'de bir işlem yapmak.Başarısız ActiveRecord doğrulamalarından sonra veritabanına bir şeyler nasıl kaydedilir?

class MyModel < ActiveRecord::Base 
    validate :something 

    def something 
    # test 
    errors.add(:data, "bug!!") 
    end 
end 

Ben de bir modeli bu gibi bakarak var: İşte bazı sözde kod

class MyModelLog < ActiveRecord::Base 

    def self.log_something 
    self.create(:log => "something happened") 
    end 

end 

denedim oturum açabilmek için:

  • arasında something yönteminde MyModelLog.log_something Ekle MyModel

  • numaralı telefonu arayın. o doğrulama işleminde çünkü doğrulama başarısız olduğunda MyModel

ait after_validation Geri aramadaHer iki durumda da yaratılması döndürülüyor. Tabii ki, doğrulamalar başarısız olduğunda da kayıt olmak istiyorum. Aslında bir dosyaya veya veritabanından başka bir yere giriş yapmak istemiyorum çünkü diğer modellerle günlük girişlerinin ilişkilerine ve istekleri gerçekleştirebilme yeteneğine ihtiyacım var.

Seçeneklerim nelerdir?

+0

Benzer türde soru: http://stackoverflow.com/questions/3685912/how-do-i-exclude-a-model-from-a-transaction-in-activerecord/3686035#3686035 – Shadwell

cevap

0

Yuvalanmış bir işlem kullanabilirsiniz. Bu şekilde geri aranmanızdaki kod, başarısız doğrulamadan farklı bir işlemde çalışır. ActiveRecord::Transactions::ClassMethods için Rails belgeleri bunun nasıl yapıldığını tartışıyor.

+2

Anlayamayabilirim senin nokta, ama ben log_something için iç içe geçmiş bir işlem yaparsanız, o zaman "ebeveyn" işlemi geri alır, çocuk da cevabınız için geri – marcgg

1

Sizin için geçerli olup olmadığından emin değilim, ancak denetleyicinizden bir model kaydetmeye/oluşturmaya çalıştığınızı varsayalım. Denetleyicide, bu eylemin sonucunu kontrol etmek kolaydır ve büyük olasılıkla kullanıcıya kullanışlı bir flaş sağlamak için zaten yaparsınız; böylece uygun bir mesajı kolayca kaydedebilirsiniz.

Ayrıca, herhangi bir açık işlem kullanmadığınızı varsayıyorum, bu nedenle denetleyicide tutarsanız, işlemin dışında kalır (her işlem kendi işlemlerinde kaydedilir ve yok edilir).

Ne düşünüyorsunuz?

+0

geri yuvarlanır ama ben farklı yerlerde bu günlükleri bir sürü ile sonuçlanabilir Bu yüzden onları benim modelimde tutmayı tercih ederim – marcgg

+0

Denetleyicide yapmanın avantajı, açık olması ve bir hata işlemine ait olmasıdır. Çok fazla kod çoğaltmasını önlemek için, davranışı karıştırabilir, hatayı kaydeden bazı yöntemleri yapabilir ve örneğin bir komutta flaşı ayarlarsınız. Öte yandan, gözlemciler fikrini de beğenirim, farklı bir işlemde olsalar da emin değilim. – nathanvda

3

Bu Observer için uygun mu? Emin değilim, ama bu işlemin dışında var olduğunu umuyorum ... Güncelleme sırasında bir kaydı silmek isteyebileceğim benzer bir ihtiyacım var ...

+0

İyi bir fikir, düşünmeye çalışacağım ve ne yapmaya çalıştığımı anlayacağım – marcgg

+1

Daha ileri araştırmalar bunun işe yaramayacağını gösteriyor - Hatta gözlemciler işlemin içinde yer alıyorlar. İşlemden sonra bir şey çalıştırmak için raylara 3 sonra bakın ... cevap için de bir after_rollback var – DGM

8

İç içe geçmiş işlemler MySQL'de çalışıyor gibi görünüyor . İşte

ben proje (MySQL ile) Yeni oluşturulan raylarda çalıştı budur:

./script/generate model Event title:string --skip-timestamps --skip-fixture 

./script/generate model EventLog error_message:text --skip-fixture 

class Event < ActiveRecord::Base                                  
    validates_presence_of :title                                   
    after_validation_on_create :log_errors                                

    def log_errors                                      
    EventLog.log_error(self) if errors.on(:title).present?                            
    end                                         
end 

class EventLog < ActiveRecord::Base                                  
    def self.log_error(event)                                    
    connection.execute('BEGIN') # If I do transaction do then it doesn't work. 
    create :error_message => event.errors.on(:title)                        
    connection.execute('COMMIT')                                  
    end                                         
end 

# And then in script/console: 
>> Event.new.save 
=> false 
>> EventLog.all 
=> [#<EventLog id: 1, error_message: "can't be blank", created_at: "2010-10-22 13:17:41", updated_at: "2010-10-22 13:17:41">] 
>> Event.all 
=> [] 

Belki bunu basitleştirilmiş, ya da eksik bir noktada üzerinde var.

+0

. Ancak bu mysql çok bağımlı görünüyor ve uygun bir çözüm olacağını emin değilim. Ayrıca, yalnızca hataların içeriğini değil, bazı API çağrılarının sonuçlarını da kaydedemediğimden, doğrulama yöntemleri içindeki hataları günlüğe kaydetmek istiyorum. Hala, iyi bir nokta – marcgg

1

MyModelLog.log_something farklı bir bağlantı kullanılarak yapılmalıdır.

MyModelLog modelini her zaman kurmak_kullanıcısını kullanarak farklı bir bağlantı kullanarak yapabilirsiniz.

class MyModelLog < ActiveRecord::Base 
    establish_connection Rails.env # Use different connection 

    def self.log_something 
    self.create(:log => "something happened") 
    end 
end 

Bu, günlük kaydı yapmanın doğru yolu olup olmadığından emin değil !!

2

Ruby'nin değişken kapsam belirleme özelliğinden yararlanarak böyle bir sorunu çözdüm. Temel olarak, bir işlem bloğu dışında bir error değişkenini bildirdim, sonra yakala, günlük mesajını sakla ve hatayı tekrar kaldır. değişkenin içeriği işlem çıkıldı sonra bile devam işlem kapsamı error değişken dışında ilan ederek

def something 
    error = nil 
    ActiveRecord::Base.transaction do 
     begin 
      # place codez here 
     rescue ActiveRecord::Rollback => e 
      error = e.message 
      raise ActiveRecord::Rollback 
     end 
    end 
    MyModelLog.log_something(error) unless error.nil? 
end 

:

Bu şuna benzer.

İlgili konular