2010-09-16 34 views
5

Tôi đang cố gắng hiểu các Callback Active Record, nhưng chúng không hoạt động, như tôi muốn.Làm cách nào để đặt thuộc tính trong đối tượng ActiveRecord trước khi tôi lưu?

ví dụ:

Mẫu

Checklist<ActiveRecord... 
attr_accessible :item1, :item2, :done # they are all boolean 

before_save :check_done 

private 
def check_done 
    if item1 && item2 
    write_attribute :done, true 
    else 
    write_attribute :done, false 
    end 
end 

này không hoạt động nếu tôi nhanh chóng một đối tượng trong giao diện điều khiển và cố gắng tiết kiệm nó, tiết kiệm hoạt động trở lại "false" :(

Có gì sai với mã này? cảm ơn trước :)

EDIT: Dường như có cái gì đó sai với "before_save" cuộc gọi, nếu tôi sử dụng "after_save", mã hoạt động ... nhưng các thuộc tính không được lưu (rõ ràng). Đó là thực sự lạ

EDIT 2 Weird ... các bản ghi sự phát triển cho thấy điều này

FROM sqlite_master 
WHERE type = 'table' AND NOT name = 'sqlite_sequence' 
[0m 
    [1m[35mChecklist Load (0.2ms)[0m SELECT "checklists".* FROM "checklists" ORDER BY checklists.id DESC LIMIT 1 
WARNING: Can't mass-assign protected attributes: id 

nhưng đó là thực sự kỳ lạ, bởi vì nếu tôi loại bỏ các dòng attr_accessible tôi vẫn nhận được lỗi này ...

CHỈNH SỬA 3 Nếu có ai hỏi, vâng tôi đang cố cập nhật bản ghi hiện tại.

EDIT 4 Vâng, tôi muốn sửa Nếu tôi gõ vào console

c.save => # false 
c.errors => #<OrderedHash {}> 
+0

Tại sao bạn có nghĩa là điều này không hiệu quả, các lỗi là gì? Bạn có thể kiểm tra bằng cách gọi cho yourobject.errors sau khi yourobject.save – Mike

+0

oh, okay Tôi nhận được myobject.errors # tabaluga

+0

Làm thế nào về 'myobject.errors.inspect' ?? – PeterWong

Trả lời

8

Sự cố với gọi lại của bạn là vấn đề trả về false nếu item1 hoặc item2 là sai.

Từ các tài liệu Active Record Callbacks:

Nếu giá trị trả về của một callback before_validation có thể được đánh giá để false, quá trình này sẽ được hủy bỏ và Base#save sẽ trở lại false.

Giải pháp rất đơn giản; trả lại true ở cuối cuộc gọi lại của bạn, như vậy:

def check_done 
    self.done = (item1 && item2) 
    return true 
end 
+3

thankyou, thankyou, thankyou! BTW. cho tất cả các bạn nếu bạn đến Berlin, hãy thả cho tôi một dòng, bạn kiếm được đồ uống :) – tabaluga

+0

Điều này thực sự tuyệt vời, tôi bắt đầu mất đi sự tỉnh táo khi tôi cố in/đặt/p vào cuối cuộc gọi lại phương pháp và nhận ra rằng làm như vậy sẽ trả về nil mà sẽ thổi lên gọi lại. thở dài! Cảm ơn! –

0

hãy thử:

def check_done 
    if item1 && item2 
    done = true 
    else 
    done = false 
    end 
end 
+0

hmmmm, không hoạt động: ( nhưng cảm ơn vì đã giúp :) – tabaluga

0

Trong phương pháp riêng của bạn, hãy thử

def check_done 
    self.done = (self.item1 && self.item2) ? true : false 
end 
+0

Buhuuu, điều đó không hoạt động ... nhưng nhờ nỗ lực của bạn :) – tabaluga

+0

Bạn có thử bằng cách thêm tham chiếu tự trong giải pháp @PeterWong? – Yannis

+1

Bạn nên tương đương với tôi ... Sẽ có những vấn đề khác. @tabaluga, Có 'item1',' item2' được đặt chính xác (đúng và sai như bạn mong đợi). Và cột 'done' có giá trị boolean không? hoặc bạn có muốn thêm một số bản ghi gỡ lỗi để xem các biến có thay đổi như bạn mong đợi không? – PeterWong

2
before_save { |record| 
    record.done = item1 && item2 
} 
+1

thankyou, thankyou, thankyou – tabaluga

Các vấn đề liên quan