Rails 4.0和动态字段

时间:2013-08-26 05:39:18

标签: ruby-on-rails

所以我正在重新编写/升级使用基于此专业Railscast http://railscasts.com/episodes/403-dynamic-forms的动态字段的3.0应用程序。

加载动态字段的方式是通过以下代码:

  <%= f.hidden_field :tour_type_id %>

  <%= f.fields_for :options, OpenStruct.new(@trip.options) do |builder| %>
     <% @trip.tour_type.type_fields.where(:variable => false).each do |field| %>
           <%= render "type_fields", field: field, f: builder %>
      <% end %>
    <% end %>

这正确地渲染了html。

当我通过控制台执行创建时,我传入的哈希:选项正确保存。但是,当我通过表单提交值时,它会将哈希值保存为nil。

我在想这可能是因为我在控制器中有强烈的参数。

  def trip_params
     params.require(:trip).permit(:options => {:id => :value})
  end

我也试过

  def trip_params
     params.require(:trip).permit(:options => {})
  end

params在rails服务器日志中看起来没问题,但是在更新发生之前,选项的值被设置为nil

  Processing by TripsController#update as HTML
  Parameters: {"utf8"=>"✓", "authenticity_token"=>"...", "trip"=>{"options"=>{"1"=>"400"}}, "commit"=>"Update Trip", "id"=>"1"}

 SQL (1.0ms)  UPDATE "trips" SET "updated_at" = $1, "options" = $2 WHERE "trips"."id" = 1  [["updated_at", Mon, 26 Aug 2013 05:13:35 UTC +00:00], ["options", "--- !ruby/hash:ActionController::Parameters\n'1': \n"]]

我还将序列化操作添加到模型

 class Trip < ActiveRecord::Base
   serialize :options, Hash
 end

我真的不知道为什么这个代码在Rails v 4,Ruby V 1.9.3中不起作用。

此代码以动态表单RailsCast为模型。

编辑:

我尝试了此处列出的解决方案http://guides.rubyonrails.org/action_controller_overview.html#outside-the-scope-of-strong-parameters

def trip_params
  params.require(:trip).permit(
    :admin_name, 
    :brochure_title, 
    :description, 
    :organized_by, 
    :start_date, 
    :end_date, 
    :tour_type_id, 
    :pay_by, 
    :extension
  ).tap do |whitelisted|
    whitelisted[:options] = params[:trip][:options]
  end
end

我现在得到一个未找到的参数:选项错误。

1 个答案:

答案 0 :(得分:0)

似乎strong_parameters不支持允许使用任意键进行哈希,我认为这是有充分理由的......

在rails github repo上建议了一个解决方案:https://github.com/rails/rails/issues/9454#issuecomment-14167664 RailsGuides http://guides.rubyonrails.org/action_controller_overview.html#outside-the-scope-of-strong-parameters

对于你的情况,它会是这样的

params.require(:trip).permit(:foo, :bar, :baz).tap do |whitelisted|
  whitelisted[:options] = params[:trip][:options]
end

如果optionsTrip的唯一属性,那么就像

一样好
params.require(:trip).permit!