2009-06-29 13 views
22

acts_as_nested_set çatal kullanan bir modelim var ve modeli kaydetmek ve düğümü bir işlemde kümeye taşımak için modele bir yöntem ekledim. Bu yöntem, doğru veya yanlış döndüren hareketin geçerli olduğundan emin olmak için bir doğrulama yöntemini çağırır. Doğrulama başarısız olursa, kaydetme yöntemimin işlemi geri almak için ActiveRecord::Rollback'u yükseltmesini istiyorum, ancak aynı zamanda arayan kişiye yanlış geri dönmesini istiyorum. Ben başarısız olacak bir durumda tasarruf çağırdığınızda, işlem geri alınır, AncakActiveRecord :: Rollback istisnası nasıl yükseltilir ve bir değer birlikte mi döndürülür?

class Category < ActiveRecord::Base 
    acts_as_nested_set :dependent => :destroy, :scope => :journal 

    def save_with_place_in_set(parent_id) 
    Category.transaction do 
     return false if !save_without_place_in_set 

     if !validate_move parent_id 
     raise ActiveRecord::Rollback and return false 
     else 
     place_in_nested_set parent_id 
     return true 
     end 
    end 
    end 

    alias_method_chain :save, :place_in_set 

    def validate_move(parent_id) 
    # return true or false if the move is valid 
    # ... 
    end 

    def place_in_nested_set(parent_id) 
    # place the node in the correct place in the set 
    # ... 
    end 
end 

ancak işlev nil döndürür::

Benim modelim şöyle Çünkü

>> c = Category.new(:name => "test") 
=> #<Category id: nil, name: "test" parent_id: nil, lft: nil, rgt: nil> 
>> c.save_with_place_in_set 47 
=> nil 
>> c.errors.full_messages 
=> ["The specified parent is invalid"] 

cevap

26

Sen bir değişkene işlevinden döndürülen istediğiniz değeri saklamak ve işlem bloğu dışında olduğunu geri dönebilirler. Örneğin. diğer yöntemlerden biridir inanıyorum ActiveRecord::Rollback yükseltir eğer başlangıçta bu hareket kümesinin çıkabiliriz sadece diğer yolu olarak false dönen_değer kurdum

def save_with_place_in_set(parent_id) 
    return_value = false 
    Category.transaction do 
     if !save_without_place_in_set 
     return_value = false 
     elsif !validate_move parent_id 
     return_value = false 
     raise ActiveRecord::Rollback 
     else 
     place_in_nested_set parent_id 
     return_value = true 
     end 
    end 
    return return_value 
    end 

olduğunu.

+0

+1, esasen aynı sonuca vardım. –

+0

TEŞEKKÜR EDERİZ! Rails 3.2.8'de hala geçerlidir. İşlemin bitiminden sonra ActiveRecord :: Rollback'in yükselmesini [belge] 'den (http://api.rubyonrails.org/classes/ActiveRecord/Rollback.html) bana açıklayamadım. Rollback'in program akışını hiç kesintiye uğratmadığı gibi, sadece düşüyormuş gibi görünüyordu. –

10

ActiveRecord::Rollback istisnası işlenir, ancak ActiveRecord::Transaction tarafından yeniden yükseltilmez, dönüşümü işlem bloğundan çıkarabilir ve böylece işlem geri alındıktan sonra bir değer döndürür. Biraz üstlenmeden ile

:

def save_with_place_in_set(parent_id = nil) 
    Category.transaction do 
    return false if !save_without_place_in_set 
    raise ActiveRecord::Rollback if !validate_move parent_id 

    place_in_nested_set parent_id 
    return true 
    end 

    return false 
end 
-1

Biraz geç olabileceğini biliyorum, ama aynı soruna rastladım ve sadece öğrendim ki, bir işlem bloğu içinde bir İstisnayı yükseltebilir ve kurtarırsın ... Rails örtülü olarak tüm işlemi geri alır. Yani ActiveRecord :: Rollback'e gerek yoktur. Örneğin

: Ben Raylar 3.2.15 ve Ruby 1.9.3 ile çalışıyorum

def create 
    begin 
    Model.transaction do 
     # using create! will cause Exception on validation errors 
     record = Model.create!({name: nil}) 
     check_something_afterwards(record) 
     return true 
    end 
    rescue Exception => e 
    puts e.message 
    return false 
    end 
end 

def check_something_afterwards(record) 
    # just for demonstration purpose 
    raise Exception, "name is missing" if record.name.nil? 
end 

.

İlgili konular