2

ActiveModel を含み、2 つの日付で構成されるフィルター クラスがあります。

class MealFilter
  include ActiveModel::Model

  attribute :day_from, Date
  attribute :day_to, Date
end

そのモデルは、次のような形式にレンダリングされます。

  <%= form_for(@filter) do |f| %>
      <div class="form-group form-group--date">
        <%= f.label :day_from %>
        <%= f.date_select :day_from %>
      </div>
      <div class="form-group form-group--date">
        <%= f.label :day_to %>
        <%= f.date_select :day_to %>
      </div>
  <% end %>

問題は、フォームが送信されると、このパラメーターがコントローラーに送信されることです。

{"utf8"=>"✓", "meal_filter"=>{"day_from(1i)"=>"2016", "day_from(2i)"=>"1", "day_from(3i)"=>"29", "day_to(1i)"=>"2016", "day_to(2i)"=>"1", "day_to(3i)"=>"30"}, "commit"=>"Filter"}

コントローラーのパラメーターを介して値を抽出します。

def meal_filter_params
  if params.has_key? :meal_filter
    params.require(:meal_filter).permit(:day_from, :day_to)
  end
end

params[:meal_filter]MealFilterクラスに割り当てると@filter = MealFilter.new(meal_filter_params)、日付フィールドが正しく更新されません。1i 、2i、3iの部分が日付に正しく割り当てられていないようです。

ただし、ActiveRecordクラスを使用する場合、これは正常に機能します。

私はいくつかのインクルードを見逃していますか? ではない場合、この魔法のマッピングが実装されている場所を知っている人はいActiveModel::Modelますか?

4

3 に答える 3

0

わかりました、解決策を見つけました。私が必要としていたのは、実際には ActiveRecord に実装されているが ActiveModel には実装されていない MultiparameterAssignment でした。

私が見る限り、この問題を解決するオープン プル リクエスト ( https://github.com/rails/rails/pull/8189 ) があります。

しかし、その間に、賢い人がモデルに含めることができるモジュールを書きました: https://gist.github.com/mhuggins/6c3d343fd800cf88f28e

あなたがする必要があるのは、懸念を含めて、class_for_attributeあなたの属性がマップされるべきクラスを返すメソッドを定義することだけです - 私の場合Date

于 2016-01-29T15:18:29.853 に答える
0

date_select ヘルパーから 1i、2i、および 3i パラメーターにアクセスし、それらを組み合わせて before_validation コールバックで新しい Date を作成するだけです。

class DateOfBirth
  include ActiveModel::Model
  include ActiveModel::Attributes
  include ActiveModel::Validations::Callbacks

  attribute :date_of_birth, :date
  attribute "date_of_birth(3i)", :string
  attribute "date_of_birth(2i)", :string
  attribute "date_of_birth(1i)", :string

  before_validation :make_a_date

  validates :date_of_birth, presence: { message: "You need to enter a valid date of birth" }

  def make_a_date
    year = self.send("date_of_birth(1i)").to_i 
    month = self.send("date_of_birth(2i)").to_i
    day = self.send("date_of_birth(3i)").to_i

    begin # catch invalid dates, e.g. 31 Feb
      self.date_of_birth = Date.new(year, month, day)
    rescue ArgumentError
      return
    end
  end
end
于 2020-06-09T18:43:14.597 に答える