Rails为accepts_nested_attributes发布JSON

时间:2014-06-01 09:07:40

标签: ruby-on-rails json

我正在使用Rails和Angular,并试图通过前端的JSON PUT请求获得一个简单的关联来更新。

协会:Article has_many :categories, through: :article_categories

文章模型:

class Article < ActiveRecord::Base
    validates :title, presence: true, uniqueness: true
    validates :body, presence: true
    has_many :article_categories
    has_many :categories, through: :article_categories

    accepts_nested_attributes_for :categories
end

我在更新titlebody时没有遇到任何问题,但我无法更新文章的类别。

以下是相关的控制器部件

        def update
            @article = Article.find(params[:id])
            if @article.update(article_params)
                render json: @article, status: 200
            end
        end

        private
          def article_params
            params.require(:article).permit(:title, :body,
             categories_attributes: [:name, :id])
          end

我的传入JSON看起来像这样,间隔开以使其更具可读性:

Started PUT "/api/v1/articles/6" for 127.0.0.1 at 2014-06-01 17:53:04 +0900
Processing by Api::V1::ArticlesController#update as HTML
  Parameters: {"title"=>"new title", "body"=>"blablabla", "id"=>"6", "categories"=>
[{"name"=>"Ruby", "id"=>1}, {"name"=>"Javascript", "id"=>2}, {"name"=>"HTML", "id"=>3},
{"name"=>"CSS", "id"=>4}],

"categories_attributes"=>[{"name"=>"Ruby", "id"=>1},
{"name"=>"Javascript", "id"=>2}, {"name"=>"HTML", "id"=>3}, {"name"=>"CSS", "id"=>4}],

"article"=>{"id"=>"6", "title"=>"new title", "body"=>"blablabla"}}

我得到的唯一反馈是article id不是列入白名单的参数。不是R categories_attributes什么是Rails在采用嵌套属性时所寻找的?为什么不抱怨categories参数没有被列入白名单?

2 个答案:

答案 0 :(得分:1)

我们had this problem before - 您基本上绕过join model,这会阻止您的应用程序正常运行。

嵌套关联

基本上,您需要在传递article_categories数据之前将关联数据传递到categories模型

#app/models/article.rb
Class Article < ActiveRecord::Base
    ...
    accepts_nested_attributes_for :article_categories
end

#app/models/article_category.rb
Class ArticleCategory < ActiveRecord::Base
    belongs_to :category
    belongs_to :article
    accepts_nested_attributes_for :category
end

#app/controllers/articles_controller.rb
def new
   @article = Article.new
   @article.article_categories.build.build_category
end

def create
   @article = Article.new(article_params)
   @article.save
end

private

def article_params
     params.require(:article).permit(:article, :attributes, article_categories_attributes: [categories_attributes: [:category, :options]] )
end

#app/view/articles/new.html.erb
<%= form_for @article do |f| %>
    <%= f.fiels_for :article_categories do |ac| %>
        <%= ac.fields_For :categories do |c| %>
            <%= c.text_field :your_field &>
        <% end %>
    <% end %>
<% end %>

答案 1 :(得分:0)

这里有几个问题:

我的json格式不正确。这些类别没有嵌套在article中,这就是为什么rails没有抛出验证错误的原因。我改变了角度前端来发布这个:

{"article"=>{"title"=>"sdfsd", "body"=>"sdf", "category_ids"=>[1, 2, 3]}}

我的angular $ scope包含类别ID和名称,因此我必须编写一个函数来解析ID并将它们转储到数组中。烦。

接下来,由于ArticleCategory上的验证,使用此JSON格式创建文章失败。我将inverse_of添加到我的模型https://github.com/rails/rails/issues/5178,然后在创建包含类别的新文章并绕过连接模型时验证将会通过。如果我理解正确,这是Richard Peck回答的另一种解决方案。

最终模型看起来像这样:

class Article < ActiveRecord::Base
  validates :title, presence: true, uniqueness: true
  validates :body, presence: true
  has_many :article_categories, inverse_of: :article
  has_many :categories, through: :article_categories
end

class Category < ActiveRecord::Base
  validates :name, presence: true, uniqueness: true
  has_many :article_categories, inverse_of: :category
  has_many :articles, through: :article_categories
end


class ArticleCategory < ActiveRecord::Base
  belongs_to :article, inverse_of: :article_categories
  belongs_to :category, inverse_of: :article_categories
  validates :category, :article, presence: true
end