如何在Rails Simple Form中展示Kids与Lessons的键值关联模型?
解决Rails Simple Form中关联表的课程分数录入问题
嘿,这事儿不难,咱们一步步来搞定!首先得把模型关联和嵌套属性配置好,然后用Simple Form就能轻松实现你要的表单样式。
第一步:配置模型关联与嵌套属性
首先确保你的Kid和Lesson模型之间的关联正确,并且开启嵌套属性支持(这是在一个表单里处理关联模型的关键):
Kid模型(app/models/kid.rb)
class Kid < ApplicationRecord has_many :lessons, dependent: :destroy accepts_nested_attributes_for :lessons, allow_destroy: true end
Lesson模型(app/models/lesson.rb)
class Lesson < ApplicationRecord belongs_to :kid end
第二步:在控制器中预构建课程记录
在KidsController的new方法里,给新的Kid对象预创建你需要的5门课程对应的Lesson实例,这样表单就能自动生成对应的输入框:
Kids控制器(app/controllers/kids_controller.rb)
class KidsController < ApplicationController def new @kid = Kid.new # 定义你需要的5门课程,这里以数学、英语、语文、科学、历史为例 courses = ["math", "english", "chinese", "science", "history"] courses.each do |course_key| @kid.lessons.build(key: course_key) end end def create @kid = Kid.new(kids_params) if @kid.save redirect_to kids_path, notice: "孩子信息和课程分数保存成功!" else render :new end end private def kids_params params.require(:kid).permit(:name, lessons_attributes: [:id, :key, :value]) end end
第三步:编写Simple Form表单
现在就可以在视图里写表单了,用fields_for遍历预构建的lessons,同时把英文的课程key转成中文显示:
表单视图(app/views/kids/new.html.erb)
<%= simple_form_for @kid do |f| %> <%= f.error_notification %> <!-- 孩子姓名输入框 --> <%= f.input :name, placeholder: 'Kid Name', label: '姓名' %> <!-- 课程分数输入区域 --> <% @kid.lessons.each do |lesson| %> <%# 根据key显示对应的中文课程名 %> <% course_name = case lesson.key when "math" then "数学" when "english" then "英语" when "chinese" then "语文" when "science" then "科学" when "history" then "历史" end %> <%= f.fields_for :lessons, lesson do |lesson_f| %> <%# 隐藏字段存储课程key,用户不需要修改 %> <%= lesson_f.hidden_field :key %> <%= lesson_f.input :value, label: course_name, placeholder: 'Score' %> <% end %> <% end %> <%= f.button :submit, '保存' %> <% end %>
补充:如果要手动指定name属性格式
如果你确实需要让输入框的name属性是key["math"]这种格式(虽然不太符合Rails的参数规范,但也能实现),可以不用嵌套属性,直接手动写input标签:
<%= simple_form_for @kid do |f| %> <%= f.input :name, placeholder: 'Kid Name', label: '姓名' %> <% courses = { "math" => "数学", "english" => "英语", "chinese" => "语文", "science" => "科学", "history" => "历史" } %> <% courses.each do |key, name| %> <%= label_tag "key[#{key}]", name %> <%= text_field_tag "key[#{key}]", '', placeholder: 'Score' %> <% end %> <%= f.button :submit, '保存' %>
这种情况下,你需要在控制器的create方法里手动处理params[:key],逐个创建Lesson记录:
def create @kid = Kid.new(name: params[:kid][:name]) if @kid.save params[:key].each do |course_key, score| @kid.lessons.create(key: course_key, value: score) unless score.blank? end redirect_to kids_path, notice: "保存成功!" else render :new end end
不过更推荐第一种嵌套属性的方式,因为它更符合Rails的最佳实践,也更容易维护和处理验证逻辑。
内容的提问来源于stack exchange,提问作者Crazy Coders
相关产品推荐
相关产品推荐

