2

あるプロジェクトで、ログインしたユーザーに会社に基づいた特定のデータを要求する必要があるという要件に遭遇しました。この特定のデータは会社固有であり、必須または一意である可能性があります。これが私が取ったアプローチです。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. 個別の検証ブロックを定義する代わりに、ここで検証ヘルパーを使用するにはどうすればよいですか?

4

1 に答える 1