Rails 5 简单表单在模型属性中保存表单提交的哈希值

Rails 5 Simple Form Save Hash Value Submitted by a Form in Model Attribute

在我的 Rails 5 应用程序中,我有一个用于创建或更新我的模型的简单表单 Training。在这个表单中,我已经为我的每个 Participant 设置了复选框以将它们分配给 Training。现在我正在尝试为每个 Participant 添加一个单选按钮组(5 个用于从 1 到 5 的评级),因为每个都可以对 Training 进行评级。

Screen shot of the rendered form

我设法渲染了我想要的单选按钮,但不幸的是我只能 select 渲染所有单选按钮中的一个。它们甚至奇怪地连接到复选框,这可能是因为它们具有相同的输入法 participant_ids,连接到 has_and_belongs_to_manyParticipant :participants 的关联。

<%= simple_form_for @training do |f| %>
...
  <div id="participants-ratings-container">
    <div id="participants-container" style="display: inline-block; vertical-align: top; width: 8em">
    <%= f.label t('activerecord.models.participant') %>
    <%= f.collection_check_boxes :participant_ids, Participant.all.order(:name), :id, :name, {:item_wrapper_class => 'checkbox-container'}  %>
  </div>

  <div id="ratings-container" style="display: inline-block; vertical-align: top">
    <%= f.label t('trainings._form.ratings') %>
    <% Participant.all.order(:name).each do |p| %>
    <%= f.input :participant_ids, collection: 1..5, as: :radio_buttons, label: false%>
    <% end %>
  </div>
...
<% end %>

我尝试了很多东西,但我再也没有想法了。如果可能的话,我想在我的 Training class 中以 "participant.name" => 评级值的方式填充哈希 participant_ratings

谁能告诉我如何实现这一点?如果没有选中相应的 Participant,甚至可以告诉我如何禁用单选按钮组?

提前致谢!

更新

我设法调整了我的表格,甚至集成了 jQuery raty 插件来为每个 Participant 输入评级值。每个评级都以其对应的参与者 ID 作为哈希值发送到服务器,例如像这样:

"participant_ratings"=>{"3"=>"5", "1"=>"3.5", "2"=>""}.

如果相应的参与者复选框未选中,则每个评分都会被禁用并且其值设置为 0。这是我的查看代码:

<div id="ratings-container" style="display: inline-block; vertical-align: top">
    <%= f.label t('trainings._form.ratings') %>
    <% Participant.all.order(:name).each do |p| %>
      <span class="checkbox_container">
        <% current_rating = @training.participant_ratings[p.id].nil? ? '' : @training.participant_ratings[p.id] %>
           <label id='star<%= "#{p.id}" %>' data-rating='<%= "#{current_rating}" %>' style="margin-bottom: 12px;" ></label>
        <input id="rating<%= "#{p.id}" %>" name="participant_ratings[<%= "#{p.id}" %>]" type="hidden" value="<%= "#{@training.participant_ratings[p.id]}" %>" />
      </span>
        <script>
            $('#star<%= "#{p.id}" %>').raty({
                score: function() {
                    return $(this).attr('data-rating');
                },
                half  : true,
                readOnly: <%= !@training.participants.include?(p) %>,
                path: '/assets',
                click : function(score, evt) {
                    $('#rating<%= "#{p.id}" %>').val(score);
                }
            });
            $('#training_participant_ids_<%= "#{p.id}" %>').change(function () {
                var star = $('#star<%= "#{p.id}" %>');
                if(document.getElementById('training_participant_ids_<%= "#{p.id}" %>').checked) {
                    star.raty('readOnly', false);
                } else {
                    star.raty('cancel');
                    star.raty('readOnly', true);
                    $('#rating<%= "#{p.id}" %>').val("");
                }
            })
        </script>
    <% end %>
</div>    

New screen shot of the rendered form

最后我似乎想不通的是如何在相应的模型属性:participant_ratings

中保存participant_ratings散列

如果我在我的 trainings_controller.rb 中允许参数 :participant_ratings 但没有保存任何内容。所以我添加了

@training.participant_ratings = params[:participant_ratings]

现在我得到了错误

Attribute was supposed to be a Hash, but was a ActionController::Parameters. -- <ActionController::Parameters {"3"=>"5", "1"=>"3.5", "2"=>""} permitted: false>

我的方法trainings_controller.rb:

class TrainingsController < BaseController
...
  def update
    @training = Training.find(params[:id])
    @training.updated_date_time = DateTime.now
    @training.participant_ratings = params[:participant_ratings]

    if @training.update(training_params)
      flash[:notice] = t('flash.training.updated')
      redirect_to @training
    else
      render 'edit'
    end
  end

  private
    def training_params
      params.require(:training).permit(:village, :topic, :user_id, :start_time, :end_time, {:participant_ids => []}, :participant_ratings)
    end
end

如何在模型的属性中保存表单发送的哈希?我哪里错了?
我能以某种方式将 participant_ratings 定义为参数中类似于数组 participant_ids 的散列吗?

首先,我必须确保 participants_rating-hash 在我的表单提交时位于 training-hash 内,因此我必须更改隐藏表单输入中的名称属性以获取评级:

<input id="rating<%= "#{p.id}" %>" name="training[participant_ratings][<%= "#{p.id}" %>]" type="hidden" value="<%= "#{@training.participant_ratings[p.id]}" %>" />

其次,我不得不将我的 participant_ratings-hash 的密钥列入白名单,以便允许使用它们:

def training_params
  ratings_keys = params[:training].try(:fetch, :participant_ratings, {}).keys
  params.require(:training).permit(:village, :topic, :user_id, :start_time, :end_time, {:participant_ids => []}, participant_ratings: ratings_keys )
end

我在 this rails thread

中找到了这个解决方案

之后participant_ratings保存就好了!