Trong bài đăng blog tuyệt vời của Bryan Helmkamp có tên "7 Patterns to Refactor Fat ActiveRecord Models", anh đề cập đến việc sử dụng Form Objects
để trừu tượng các biểu mẫu nhiều lớp và ngừng sử dụng accepts_nested_attributes_for
.trên đối tượng ActiveModel, làm cách nào để kiểm tra tính duy nhất?
Chỉnh sửa: xem below để biết giải pháp.
Tôi đã gần như chính xác nhân đôi mẫu mã của mình, như tôi đã có cùng một vấn đề để giải quyết:
class Signup
include Virtus
extend ActiveModel::Naming
include ActiveModel::Conversion
include ActiveModel::Validations
attr_reader :user
attr_reader :account
attribute :name, String
attribute :account_name, String
attribute :email, String
validates :email, presence: true
validates :account_name,
uniqueness: { case_sensitive: false },
length: 3..40,
format: { with: /^([a-z0-9\-]+)$/i }
# Forms are never themselves persisted
def persisted?
false
end
def save
if valid?
persist!
true
else
false
end
end
private
def persist!
@account = Account.create!(name: account_name)
@user = @account.users.create!(name: name, email: email)
end
end
Một trong những điều khác nhau trong mảnh của tôi về mã, là tôi cần phải xác nhận tính duy nhất của tên tài khoản (và email người dùng). Tuy nhiên, ActiveModel::Validations
không có trình xác thực uniqueness
vì nó được cho là biến thể không được cơ sở dữ liệu được hỗ trợ là ActiveRecord
.
I figured có ba cách để xử lý này:
- Viết phương pháp riêng của tôi để kiểm tra này (cảm thấy không cần thiết)
- Bao gồm ActiveRecord :: validations :: UniquenessValidator (cố gắng này, đã không nhận được nó hoạt động)
- Hoặc thêm các hạn chế trong lớp lưu trữ dữ liệu
tôi muốn sử dụng cuối cùng. Nhưng sau đó tôi vẫn tự hỏi cách Tôi sẽ thực hiện điều này.
tôi có thể làm một cái gì đó giống như (Lập trình meta, tôi sẽ cần phải sửa đổi một số lĩnh vực khác):
def persist!
@account = Account.create!(name: account_name)
@user = @account.users.create!(name: name, email: email)
rescue ActiveRecord::RecordNotUnique
errors.add(:name, "not unique")
false
end
Nhưng bây giờ tôi đã hai kiểm tra chạy trong lớp học của tôi, lần đầu tiên tôi sử dụng valid?
và sau đó tôi sử dụng một tuyên bố rescue
cho các ràng buộc lưu trữ dữ liệu.
Có ai biết cách tốt để xử lý vấn đề này không? Nó có thể là tốt hơn để có thể viết validator của riêng tôi cho điều này (nhưng sau đó tôi muốn có hai truy vấn cơ sở dữ liệu, nơi lý tưởng nhất là đủ).
Nếu đây có thể giúp bất cứ ai: trong một tình huống tương tự như tôi bao gồm "ActiveRecord :: validations" thay vì "ActiveModel :: validations" - theo cách này * validates_uniqueness_of * là có sẵn – Mat