2011-09-27 31 views
66

Tôi có một mô hình đặc biệt phức tạp với các xác nhận hợp lệ và các cuộc gọi lại được xác định. Nhu cầu kinh doanh hiện nay kêu gọi cho một kịch bản cụ thể, nơi thêm bản ghi mới yêu cầu bỏ qua các xác thực và gọi lại. Cách tốt nhất để làm điều này là gì?Rails 3 bỏ qua xác nhận và gọi lại

Trả lời

116

này hoạt động trong Rails 3:

Model.skip_callback(:create) 
model.save(:validate => false) 
Model.set_callback(:create) 

(API docsrelated question)

+5

Bạn không cần phải sử dụng '' 'set_callback (: create)' ''? Tôi đã bị ấn tượng rằng '' 'skip_callback''' vô hiệu hóa nó cho đến khi được kích hoạt lại. –

+1

Tôi nghĩ có, tôi không bao giờ sử dụng phương pháp này, thông tin thêm http://api.rubyonrails.org/classes/ActiveSupport/Callbacks/ClassMethods.html#method-i-skip_callback – Dinatih

+19

Đây không thể là chủ đề an toàn? nó sẽ là tốt đẹp để có thể thiết lập nó trên một mức độ thể hiện .. –

1

gì về việc thêm một phương pháp để mô hình của bạn mà cho phép của bạn bỏ qua callbacks?

class Foo < ActiveRecord::Base 
    after_save :do_stuff 

    def super_secret_create(attrs) 
    self.skip_callback(:create) 
    self.update_attributes(attrs) 
    self.save(:validate => false) 
    self.set_callback(:create) 
    end 
end 

Nếu bạn kết thúc bằng cách sử dụng một cái gì đó như thế này, tôi khuyên bạn nên tự sử dụng phương pháp thay vì tên mẫu để tránh sự kết nối của tên.

tôi cũng chạy qua một ý chính từ Sven Fuchs mà có vẻ tốt đẹp, đó là here

+1

Tôi thích cách tiếp cận này nhưng 'skip_callback' hiển thị như một phương thức lớp trong khi' update_attributes' là một phương pháp thể hiện, là những gì bạn dự định? Hmm Tôi không hiểu, tài liệu API nói 'skip_callback' là phương thức thể hiện nhưng nó không nằm trong bảng điều khiển Rails, lẻ. –

2

mất của tôi là như thế này (lưu ý: đây vô hiệu hóa callbacks trên tạo, cập nhật, xóa và những người khác bạn cần phải thêm chúng vào mảng).

begin 
     [:create, :save].each{|a| self.class.skip_callback(a) } # We disable callbacks on save and create 

     # create new record here without callbacks, tou can also disable validations with 
     # .save(:validate => false) 
    ensure 
     [:create, :save].each{|a| self.class.set_callback(a) } # and we ensure that callbacks are restored 
    end 
+0

Được thăng hạng, nhưng sau đó nó không hoạt động cho ứng dụng 3.2.6 của tôi. Tôi đã gọi Model.skip_callback (: create,: after) – TuteC

+0

Đây là giải pháp cho 3.0+ Nó sẽ không hoạt động trên 2.x - nhưng tôi đã nhớ khi tôi đang tìm kiếm giải pháp cho điều này tôi đã vấp khi giải pháp cho 2 .x không hoạt động cho 3.x –

29

Sử dụng ActiveRecord::Persistence#update_column, như thế này:

Model.update_column(field, value) 
+0

Theo tài liệu bạn đã liên kết: "Số lần gọi lại được gọi." – eggie5

+5

Tôi nghĩ bạn đã xem tài liệu về 'update_attribute', không phải cho' update_column'. Nếu bạn xem tài liệu cho 'update_column', nó tương đương với' update_columns' cho một cột đơn. Các tài liệu cho 'update_columns' nêu rõ rằng các xác nhận hợp lệ và các cuộc gọi lại bị bỏ qua. – bowsersenior

+0

Tiết kiệm cuộc sống của tôi! Tôi đã thử skip_callback và các phương thức khác, không may mắn. Những công việc này! –

0

Hack này làm việc cho tôi cuối cùng (định nghĩa lại _notify_comment_observer_for_after_create phương pháp cho đối tượng):

if no_after_create_callback 
    def object._notify_comment_observer_for_after_create; nil; end 
end 
1

tôi đã viết một viên ngọc đơn giản để bỏ qua xác thực adhoc, nhưng nó có thể có thể được cập nhật để bao gồm bỏ qua các cuộc gọi trở lại là tốt.

https://github.com/npearson72/validation_skipper

Bạn có thể lấy can_skip_validation_for trong đá quý và thêm chức năng cho cũng bỏ qua callbacks. Có thể gọi phương thức can_skip_validation_and_callbacks_for

Mọi thứ khác sẽ hoạt động tương tự. Nếu bạn muốn được giúp đỡ, hãy cho tôi biết.

1

Tôi khuyên bạn KHÔNG nên sử dụng phương pháp skip_callback vì nó không phải là chủ đề an toàn. Tuy nhiên, sneaky save gem là vì nó chỉ chạy sql thẳng. Lưu ý điều này sẽ không kích hoạt xác nhận, do đó bạn sẽ phải tự gọi chúng (ví dụ: my_model.valid?).

Dưới đây là một số mẫu từ tài liệu của họ:

# Update. Returns true on success, false otherwise. 
existing_record.sneaky_save 

# Insert. Returns true on success, false otherwise. 
Model.new.sneaky_save 

# Raise exception on failure. 
record.sneaky_save! 
7

Nếu mục tiêu là để chỉ cần chèn hoặc cập nhật một kỷ lục mà không callbacks hoặc kiểm chứng thực, và bạn muốn làm điều đó mà không cần phải dùng đến đá quý bổ sung, thêm điều kiện kiểm tra, sử dụng RAW SQL hoặc tương thích với mã thoát của bạn theo bất kỳ cách nào, có thể sử dụng "đối tượng bóng" trỏ đến bảng db hiện tại của bạn. Giống như vậy:

class ImportedUser < ActiveRecord::Base 
    # To import users with no validations or callbacks 
    self.table_name = 'users' 
end 

Điều này làm việc với mọi phiên bản Rails, an toàn, hoàn toàn loại bỏ mọi xác thực và gọi lại mà không sửa đổi mã hiện tại của bạn.Chỉ cần nhớ sử dụng lớp mới của bạn để chèn đối tượng, như:

ImportedUser.new(person_attributes) 
+1

điều này rất thông minh. đã cứu tôi đau đầu! –

0

Không có điều nào trong số này sẽ hoạt động nếu xác thực của bạn được ghi vào cơ sở dữ liệu.

+------------------------------------+--------------------------------------------------+------+-----+--------------------+----------------+ 
| Field        | Type            | Null | Key | Default   | Extra   | 
+------------------------------------+--------------------------------------------------+------+-----+--------------------+----------------+ 
| status        | enum('Big','Small','Ugly','Stupid','Apologetic') | NO |  | Stupid    |    | 
Các vấn đề liên quan