我建了一个表 user_courses,已经存在一些记录,现在我想一次性更新多条记录中的一个属性,如下面的给每个学生打分,可以出来一个表格,用输入值来更新 grade 这个属性。 <%= form_tag do %> <% @user_courses.each do |user_course| %>
<%= user_course.course_name %> <%= user_course.user_name %> <% if user_course.grade %> <%= user_course.grade %> <% else %> <%= text_area_tag 'user_course', nil, :class => "input-medium search-query" %> <% end %> <% end %> <%=submit_tag "submit" , :class => "btn" %> <% end %> 备注:我可以试着用 data[] 数组来存储每次的 text 值,在控制器里面在依次读取出来赋值,但是我觉得这样可能会出错,例如排序之后。有没有更好的方法能够解决这个问题而又不出错。你应该把 user_course.id 和对应的成绩当作 hash 的 key 和 value 用 post 方法传回 controller,然后用 hash key value 对应的特性来赋值,例如,在你的 controller 里
user_courses = UserCourse.find(hash.keys)
user_courses.each do |user_course|
user_course.grade = hash[user_course.id]
user_course.save
end
这样可以避免用顺序来赋值容易出现的错误,但是其他错误还是得靠测试和 validation 找出来
我用 hash 只是举个例子,你传回到 controller 里面的 params hash 如果没有特别修改应该是 name 和 value 一一对应的,我的意思是让你用 id 做 name 来取 value
<input type='text' name=<%= user_course.id%> value=<%= user_course.grade %> />
把这个加在你 form 中的@user_courses遍历里,这样你 controller 里面会接到相关的 params
#6 楼 @karmue mue 我是这样写的 <% @user_courses.each do |user_course| %>
<%= user_course.course_name %> <%= user_course.user_name %> <% if user_course.grade %> <%= user_course.grade %> <% else %> > <% end %> <% end %> 浏览器把 user_course.id 当成了一个字符串变量,能不能把这句代码写完整啊,我还是不太明白。怎样取出的数字赋值给 key。我是用的 params[] hash,错误提示 Couldn't find all UserCourses with IDs (utf8, authenticity_token, user_course.id, commit, controller, action) (found 0 results, but was looking for 6). 另外,还有个问题,我的复制上贴吧的代码为什么这么不好看,有什么地方可以设置吗?#5 楼 @karmue 我按照你的思路做了 这是 create 的函数
def create
data = Array.new
params.keys().each do |key|
if key.is_a?(Integer)
else
data[] = key
end
end
user_courses = UserCourse.find(data)
user_courses.each do |user_course|
user_course.grade = params[user_course.id]
user_course.save
end
redirect_to :action => "index", :controller => "select"
end
而 html 页面中,提取代码为 textarea id="comment" name="<%= user_course.id %>" value=<%= user_course.grade %>>"✓", "authenticity_token"=>"/9RSuxSpGdWxu2/PnCsxoK8CxtzUaXQWnIA/D5CsDbY=", "1"=>"85", "11"=>"58", "commit"=>"submit"}
@sylan401 或许可以考虑做一个 FormObject, 譬如 UserCoursesBatch, 由他负责表单的生成,验证和保存(甚至做事务处理),这样 Controller 会非常干净,至于 form_tag 的写法,可以看作 nested form 处理。
可以考虑这个函数 http://apidock.com/rails/ActiveRecord/Relation/update_all 只生成一条 SQL 语句
#13 楼 @greenmoon55 我试了一下,用 update_all 不能将 id 去出来,只能一个一个的来取 id,如下面所示:
UserCourse.all.each do |user_course|
if !user_course.grade
user_course.update_attribute(:grade, params[user_course.id])
end
end
但是这样有一个问题,params[user_course.id] 不能够取出值并赋给 grade,不知道是怎么回事?
@sylan401 我完全不是这个意思。我的建议是创建一个类专门负责这个表单的处理。主要理由是提供了表单验证和校正输入的可能,我觉得像成绩录入这类的操作,难免会遇到录入错误的问题,系统应该在做保存前对输入内容做验证。
class UserCoursesForm
extend ActiveModel::Naming
include ActiveModel::Conversion
include ActiveModel::Validations
// user_courses为array或hash
attr_accessor :user_courses
// 自定义验证规则
validate :custom_validate
// rails验证规则
validates
// 构建规则
def initialize(option)
@user_courses = ...
end
def persisted?
false
end
def submit(params)
// mass assignment
@user_courses = ...
if valid?
// 保存逻辑,例如
@user_courses.each do |user_course|
user_course.save!
end
true
else
false
end
end
def custom_validate
...
end
end
然后就可以通过 form_for 或 simple_form_for 做对象表单构建。 在 controller 中也可以做常规写法
// or update
def create
@user_courses_form = UserCoursesForm.new(...)
if @user_courses_form.submit(params[:user_courses_form])
// 其他处理
...
redirect_to ...
else
// or edit
render "new"
end
end