2012-07-27 31 views
6

Tôi có một mẫu đăng ký.Rails 3: rollback cho after_create

Khi người dùng đăng ký, ứng dụng được cho là lưu dữ liệu trong bảng enrollments và trong bảng users. (Tôi cần sự tách biệt này vì hồ sơ của người dùng có thể thay đổi nhưng dữ liệu anh ta nhập cho đăng ký cụ thể đó phải được lưu trữ. Vì vậy, ngay cả khi sau này người dùng thay đổi họ của anh ấy, trong biểu mẫu đăng ký, tôi sẽ có thông tin ban đầu của anh ấy.)

vì vậy, tôi đã suy nghĩ về tiết kiệm dữ liệu trong bảng enrollments sau đó có một cuộc gọi after_create, như thế này ...

class Enrollment < ActiveRecord::Base 

    after_create :save_corresponding_user 

    def save_corresponding_user 
    user = User.new 
    user.full_name = self.user_full_name 
    user.email = self.user_email 
    user.mobile_phone = self.user_mobile_phone 
    user.save 
    end 
end 

vấn đề là, nếu tiết kiệm cho người sử dụng không vì lý do nào. Làm cách nào để khôi phục và hủy dữ liệu đã lưu từ bảng enrollments?

+0

thể một người dùng ghi danh nhiều lần? Nếu không, tôi chỉ cần thêm các trường bổ sung trực tiếp trong bảng người dùng. –

+0

Thực tế, đó là phụ huynh/người giám hộ đăng ký một đứa trẻ đến nhà trẻ. Vì vậy, có, cha mẹ có thể đăng ký một đứa trẻ nhiều lần. – leonel

+0

Với tôi, có vẻ như việc đặt save_corresponding_user trong after_create sẽ là một vấn đề. Điều gì xảy ra khi người dùng đăng ký lại? Bạn sẽ không muốn tạo một đối tượng người dùng mới cho họ. Ngoài ra, bảng đăng ký có thể có cột user_id không? Điều đó sẽ không được phổ biến trong mã của bạn ở trên. Nếu đó là tôi, tôi sẽ chỉ quấn việc tạo đăng ký và người dùng trong một giao dịch, điều này sẽ xử lý việc quay lại cả hai trong trường hợp có lỗi. –

Trả lời

12

after_create là một phần của giao dịch lưu mô hình hiện tại. Do đó, nếu mã của bạn bị lỗi hoặc nếu after_create trả về false, nó sẽ khôi phục giao dịch hiện tại và vô hiệu hóa việc tiết kiệm enrollment.

Nếu bạn muốn mô phỏng này, thêm video này vào after_create của bạn và xem nếu mọi thứ hoạt động như mong đợi:

raise Exception.new("CRASH") 
+0

rollback không xảy ra nếu bạn đang sử dụng một cơ sở dữ liệu không giao dịch như mongodb –

+3

Nếu after_create trả về false không xuất hiện để rollback giao dịch hoặc là (chỉ là ngoại lệ). Ít nhất trong Rails 4. – djburdick

+0

@djburdick Một giao dịch theo mặc định chỉ nên khôi phục nếu một ngoại lệ được nâng lên. Vì vậy, đây là hành vi mong đợi. Tôi nghĩ câu trả lời này hơi sai về chi tiết đó. – leishman

1

Như @anthonyalberto đề cập, after_create đã là một phần của giao dịch. Để xác định một giao dịch bạn sẽ sử dụng một cái gì đó như thế này trong điều khiển của bạn:

Enrollment.transaction do 
    @enrollment.save! 
end 

Đó thực sự là tất cả các bạn cần phải làm, nếu tiết kiệm ghi danh thất bại hoặc tiết kiệm của người dùng không nó sẽ quay trở lại toàn bộ giao dịch của bạn. Dưới đây là thông tin khác: http://api.rubyonrails.org/classes/ActiveRecord/Transactions/ClassMethods.html

7

Trả lại false từ after_create sẽ không làm gì cả.

Toàn bộ chuỗi cuộc gọi được gói trong giao dịch. Nếu bất kỳ phương thức callback nào trả về chính xác false hoặc làm tăng một ngoại lệ, chuỗi thực hiện sẽ bị dừng và một ROLLBACK được phát hành; sau khi gọi lại chỉ có thể thực hiện điều đó bằng cách tăng một ngoại lệ.

Ngoài ra, bạn phải raise ActiveRecord::Rollback:

Bất kỳ ngoại lệ mà không ActiveRecord :: Rollback sẽ được tái huy động bằng Rails sau chuỗi gọi lại phải dừng lại. Tăng một ngoại lệ khác với ActiveRecord :: Rollback có thể phá vỡ mã mà không mong đợi các phương thức như save và update_attributes (thường cố gắng trả về true hoặc false) để tăng một ngoại lệ.

http://guides.rubyonrails.org/active_record_callbacks.html#halting-execution

tôi làm điều gì đó như thế này:

after_create do 
    if condition 
    errors.add(:attr, 'Blah blah blah.') 
    raise ActiveRecord::Rollback 
    end 
end 

Đối với Rails 3: http://guides.rubyonrails.org/v3.2.13/active_record_validations_callbacks.html#halting-execution