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_many
与 Participant
: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
中找到了这个解决方案
之后participant_ratings保存就好了!
在我的 Rails 5 应用程序中,我有一个用于创建或更新我的模型的简单表单 Training
。在这个表单中,我已经为我的每个 Participant
设置了复选框以将它们分配给 Training
。现在我正在尝试为每个 Participant
添加一个单选按钮组(5 个用于从 1 到 5 的评级),因为每个都可以对 Training
进行评级。
Screen shot of the rendered form
我设法渲染了我想要的单选按钮,但不幸的是我只能 select 渲染所有单选按钮中的一个。它们甚至奇怪地连接到复选框,这可能是因为它们具有相同的输入法 participant_ids
,连接到 has_and_belongs_to_many
与 Participant
: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
如果我在我的 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
中找到了这个解决方案
之后participant_ratings保存就好了!