あるプロジェクトで、ログインしたユーザーに会社に基づいた特定のデータを要求する必要があるという要件に遭遇しました。この特定のデータは会社固有であり、必須または一意である可能性があります。これが私が取ったアプローチです。1. ラベル (文字列)、必須 (ブール値)、一意 (ブール値) の 3 つのフィールドを持つモデルを定義します。2. 会社の管理者は、必要なフィールドに入力できます。例: Label => "Employee number", Mandatory => true, Unique => false using a simple form.
3. このデータは、ログインしているユーザーのモデル引き換えクーポンの別のレコードを作成するときに尋ねられる必要があります。4. したがって、Redeemed Coupon モデルの初期化中、クラスを再開し、ログインしているユーザーの会社を確認します。
class RedeemedCoupon
def initialize(attrs = nil, options = nil)
super
if Merchant.current #this is set in the application controller as thread specific variable
coupon_custom_field = CouponCustomField.where(:merchant_id => Merchant.current).first
if coupon_custom_field and coupon_custom_field.custom_fields.size > 0
coupon_custom_field.custom_fields.each do |custom_field|
class_eval do
field custom_field.label.to_sym, :type => String
attr_accessible custom_field.label.to_sym
end
if custom_field.unique
class_eval do
index custom_field.label.to_sym
#validates_uniqueness_of custom_field.label.to_sym, :case_sensitive => false
end
end
if custom_field.mandatory
class_eval do
#validates_presence_of custom_field.label.to_sym
end
end
end
end
end
終わり
ただし、検証はの存在を検証し、一意性は機能せず、失敗メッセージが表示されます: コールバックが定義されていません。is_valid? の場合、これは保存前にスローされます。オブジェクトと呼ばれます。カスタム検証を入れることを回避するには
validate :custom_mandatory_unique
def custom_mandatory_unique
if Merchant.current
coupon_custom_field = CouponCustomField.where(:ira_merchant_id => Merchant.current).first
if coupon_custom_field and coupon_custom_field.custom_fields.size > 0
coupon_custom_field.custom_fields.each do |custom_field|
field_value = self.send(custom_field.label.to_sym)
self.errors.add(custom_field.label.to_sym, "cannot be blank") if !field_value.present? and custom_field.mandatory
if field_value.present? and custom_field.unique
if RedeemedCoupon.where(custom_field.label.to_sym => field_value, :merchant_id => Merchant.current).size > 0
self.errors.add(custom_field.label.to_sym, "already taken")
end
end
end
end
end
終わり
私の質問: 1. これが最善の方法ですか。2. すでに存在する宝石はありますか (検索しましたが、何も取得できませんでした)? 3. 個別の検証ブロックを定義する代わりに、ここで検証ヘルパーを使用するにはどうすればよいですか?