accepted_nested_attributes_for with hidden_​​field

时间:2014-02-16 04:47:38

标签: ruby-on-rails ruby-on-rails-4

一直在搜索stackoverflow以获得这个答案。我有一个表单来创建一个新主题。还应该使用该主题创建第一篇文章。一切都很好,除了user_id没有保存到帖子。

发布模型

class Post < ActiveRecord::Base
  belongs_to :topic
  belongs_to :user
end

主题模型

class Topic < ActiveRecord::Base
  belongs_to :forum
  belongs_to :user  
  has_many :posts 
  accepts_nested_attributes_for :posts
end

后置控制器

class PostsController < ApplicationController

  def new
    @post = Post.new
  end

  def create
    @post = Post.new(post_params)
    if @post.save
      redirect_to topic_path(@post.topic_id)
    else
      render 'new'
    end
  end

  private

  def post_params
    params.require(:post).permit(:content, :topic_id, :topic_name, :user_id)
  end

主题控制器

class TopicsController < ApplicationController

  def new
    @topic = Topic.new
    @topic.posts.build
  end

  def create
    @topic = Topic.new(topic_params)
    if @topic.save
      redirect_to @topic
    else
      render 'new'
    end
  end

  private

  def topic_params
    params.require(:topic).permit(
      :topic_name, 
      :forum_id, 
      :user_id,  
      posts_attributes: [:id, :content, :topic_id, :topic_name, :user_id ] )
  end
end

新/主题查看

<%= form_for(@topic) do |f| %> 
   <%= f.hidden_field :forum_id, :value => params[:forum_id] %>
   <%= f.hidden_field :user_id, :value => current_user.id %>
   <%= f.label :topic_name %>
   <%= f.text_field :topic_name %>
   <%= f.fields_for :posts do |p| %>
     <%= p.label :content %>
     <%= p.text_area :content %>
   <% end %>

   <%= f.submit "Post Topic", class: "btn btn-large btn-success" %>
<% end %>

我不完全确定为什么没有将user_id传递给帖子。希望比我聪明的人可以帮助我学习做什么:)

更新

我将主题控制器中的强制参数更改为此。

def topic_params
  params.require(:topic).permit(
  :topic_name, 
  :forum_id, 
posts_attributes: [:content, :topic_id, :id, '_destroy' ] ).merge(:user_id => current_user.id, posts_attributes: [:user_id => current_user.id]) 
    end

现在user_id正在运行,但没有保存任何posts_attributes:content。我对这个有很多乐趣..

2 个答案:

答案 0 :(得分:0)

简短回答,user_id不属于posts_attributes,因为content的唯一属性,这意味着允许其他属性,例如topic_idtopic_name是没用的。

现在我们清除了它,你不应该使用表单输入来表示任何模型的创建者的值,因为任何人都很容易篡改表单并将值设置为其他任何内容,就像其他用户的id一样。或者,您应该在控制器中设置user_id值,例如,在TopicsController中。这是代码:

def create
  _params = topic_params.deep_merge(user: current_user, posts_attributes: {user: current_user})
  @topic = Topic.new(_params)
  if @topic.save
    redirect_to @topic
  else
    render 'new'
  end
end

并从表单中删除user_id隐藏字段。

更新:您上次的代码更新包含错误;它应该是.merge(:user_id => current_user.id, posts_attributes: {:user_id => current_user.id})。您在:user_id => current_user.id周围使用方括号而不是卷曲方括号。

答案 1 :(得分:0)

注意在浏览器中生成的表单属性,post的所有嵌套属性都有topic[post_attributes]之类的前缀,请尝试将表单更改为:

<%= form_for(@topic) do |f| %> 
   <%= f.hidden_field :forum_id, :value => params[:forum_id] %>
   <%= f.label :topic_name %>
   <%= f.text_field :topic_name %>
   <%= f.fields_for :posts do |p| %>
     <%= p.hidden_field :user_id, :value => current_user.id %>
     <%= p.label :content %>
     <%= p.text_area :content %>
   <% end %>

   <%= f.submit "Post Topic", class: "btn btn-large btn-success" %>
<% end %>