Rails:将日期从表单参数映射到ActiveModel对象中

问题描述 投票:1回答:2

我有一个包含ActiveModel的过滤器类,它包含两个日期:

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中执行此魔术映射,则在哪里实现?

ruby-on-rails rails-activerecord ruby-on-rails-5
2个回答
0
投票
确定,找到了解决方案。我需要的是MultiparameterAssignment,它实际上是在ActiveRecord中实现的,而不是在ActiveModel中实现的。

据我所知,有一个开放拉取请求(https://github.com/rails/rails/pull/8189)应该可以解决此问题。

但是与此同时,一些聪明的人写了一个可以包含在模型中的模块:https://gist.github.com/mhuggins/6c3d343fd800cf88f28e

[您需要做的就是包括关注点并定义一个class_for_attribute方法,该方法返回应将属性映射到的类-在我的情况下是Date


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 your 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

© www.soinside.com 2019 - 2024. All rights reserved.