构造一个Rails表单,捕获属于另一个的对象

时间:2016-05-24 20:06:24

标签: ruby-on-rails forms ruby-on-rails-4 belongs-to

我正在使用Rails 4.2.3。我有以下型号

class MyObject < ActiveRecord::Base
  belongs_to :user
  has_many :my_object_times
end

class MyObjectTime < ActiveRecord::Base
  belongs_to :my_object
end

在我的PostGres数据库中,MyObjectTime对象有一个time_in_ms字段。那么如何构建一个包含MyObject对象和MyObjectTime对象属性的表单?具体来说,我想捕获time_in_ms字段。

我试过这个:

<%= form_for @my_object do |f| %>
  <% if @my_object.errors.any? %>
    <div id="error_explanation">
      <h2><%= pluralize(@my_object.errors.count, "error") %> prohibited this hack from being saved:</h2>

      <ul>
      <% @my_object.errors.full_messages.each do |message| %>
        <li><%= message %></li>
      <% end %>
      </ul>
    </div>
  <% end %>

  <div class="field">
    <%= f.label :name %><br>
    <%= f.text_field :name %>
  </div>
  <div class="field">
    <%= f.label :day %><br>
    <%= f.text_field :day, class: 'datepicker' %>
  </div>
  <div class="field">
    <%= f.label "Time" %>
    <%= select_tag('my_object[hour]', options_for_select((0..12).to_a), {:prompt => 'Select Hour'} ) %> hrs
    <%= select_tag('my_object[minute]', options_for_select((0..60).to_a), {:prompt => 'Select Minutes'} ) %> min
    <%= select_tag('my_object[second]', options_for_select((0..60).to_a), {:prompt => 'Select Minutes'} ) %> sec
    <%#= f.number_field :time_in_ms %>
  </div>

  <div class="actions">
    <%= button_to "Save", { :action => "create" }, :method => :post, :class => 'button' %>
  </div>
<% end %>

但是当我提交表单时,在尝试使用params构建模型时,我得到了控制器中的错误:

def create
  @my_object = MyObject.new(my_object_params)
....
end
...
  private

    def my_object_params
      # Main Code goes here
      params[:my_object][:time_in_ms] = (params[:my_object][:hour].to_i * 60 * 60 + params[:my_object][:minute].to_i * 60 + params[:my_object][:second].to_i) * 1000
      params.require(:my_object).permit(:time_in_ms, :name)
    end

2 个答案:

答案 0 :(得分:0)

如果您要在多个案例中一起使用这些对象,我会在MyObject模型中添加一个虚拟属性(attr_accessor :time_in_ms),以便可以将其与标准字段一起处理。这也将摆脱“未知属性”错误。然后在MyObject模型中,您可以添加逻辑,将控制器中的param分配给它并根据需要进行处理。如果这是您希望能够同时使用这两者的唯一实例,并且在rails应用程序的任何其他位置都没有这种情况,那么您应该执行Boltzor建议的操作,并在相应的控制器/操作中处理它。

答案 1 :(得分:0)

您可以使用fields_for,因为您的两个模型都是关联的:

<%= f.fields_for :my_object_time do |mot| %>
  <%= mot.number_field :time_in_ms %> 
<% end %>

然后在MyObject模型中添加accepts_nested_attributes_for

class MyObject < ActiveRecord::Base
  belongs_to :user
  has_many :my_object_times
  attr_accessible :hour, :minute, :second


  accepts_nested_attributes_for :my_object_times
end

修改MyObjects中的my_object_time控制器,白名单my_object_params

def my_object_params
  params[:my_object][:my_object_times_attributes][:time_in_ms] = (params[:my_object][:hour].to_i * 60 * 60 + params[:my_object][:minute].to_i * 60 + params[:my_object][:second].to_i) * 1000
  params.require(:my_object).permit(:name, my_object_times_attributes: [:time_in_ms])
end

现在,由于关联,您可以在保存MyObjectTime时保存关联的MyObject