Ruby on Rails根据勾选用户批量创建messages时报NoMethodError如何解决
问题根因
- 直接原因:
JSON.parse(u)得到的是Hash对象,不是User模型实例,不存在messages关联方法,所以触发报错 - 其他逻辑问题:
- 循环创建消息过程中直接执行
redirect_to/render,会在处理第一个用户后直接终止流程,剩下的选中用户不会创建消息 - 强参数编写错误,表单提交的
content参数在message键下,原有写法无法正确读取参数 - 复选框传递完整用户JSON属于冗余且不安全的实现,前端可以随意篡改用户数据
- 循环创建消息过程中直接执行
修复方案
1. 修改视图文件(new.html.erb)
把复选框部分改为仅传递用户ID,避免传递JSON的冗余操作:
<% @users.each do |u| %> <div> <p><%= check_box_tag "user_ids[]", u.id %> <%= u.name %></p> </div> <% end %>
2. 修正控制器逻辑
修正new动作
new动作初始化时不需要传入参数,避免GET请求无参数时报错:
def new @users = User.all @message = Message.new end
修正create动作和强参数
def create # 读取选中的用户ID,查询对应的User实例 selected_users = User.where(id: params[:user_ids]) # 读取消息内容参数 message_content = message_params[:content] # 用事务保证所有消息要么都创建成功,要么都回滚 Message.transaction do selected_users.each do |user| user.messages.create!(content: message_content) end end # 所有消息创建成功后跳转 redirect_to root_path rescue ActiveRecord::RecordInvalid => e # 任意一条消息创建失败则回滚,返回新建页面 @users = User.all @message = Message.new(content: message_content) @message.errors.add(:base, "消息创建失败:#{e.message}") render :new end private def message_params # 修正强参数,从message键下读取content params.require(:message).permit(:content) end
可选:如果坚持使用传递JSON的实现
如果一定要保留现有传JSON的写法,需要把解析后的Hash中的ID取出,查询得到User实例再创建消息:
params[:user_objs].each do |u| user_hash = JSON.parse(u) person = User.find(user_hash["id"]) # 后续创建逻辑和上面一致 end
注意:该实现不安全,不推荐生产环境使用
内容的提问来源于stack exchange,提问作者Sarvar Khalimov
相关产品推荐
相关产品推荐

