使用has_many和through为嵌套模型创建条目

时间:2016-09-14 07:56:00

标签: ruby-on-rails

我有三个简单关联的模型。

class User < ActiveRecord::Base
   has_many :blogs
end

class Blog < ActiveRecord::Base
   # Blog has 'title' column
   belongs_to :user
   has_many :entries
end

class Entry < ActiveRecord::Base 
   # Entry has 'article' column 
   belongs_to :blog
end

我正在创建一个JSON API来创建新的Entry。一个特殊要求是创建Blog(如果不存在)。 JSON输入应该像

 { "entry" : 
           { "article" : "my first blog entry", 
             "blog" : 
                    { "title": "My new blog" }
           }
 }

如果博客存在,请将条目添加到博客中。我正在实施&#39;条目#create&#39;方法和我想要做的是像

 def create
     @user = Users.find(params[:user_id]) # :user_id is given in URL
     # I want to do something like
     # @user.entries.create(params[:entry])
     #     or
     # @user.create(params[:entry])
     # but this doesn't work.
 end

我想问的是,我是否必须首先手动解析JSON并创建博客对象,然后创建条目对象。如果可能的话,我想让模型接受这样的输入并正常工作。

另一种可能的解决方案是更改API并在博客控制器中创建它并接受JSON,如

  { "blog" : 
           { "title" : "My new blog", 
             "article_attributes" :
                    { "article": "my first blog entry" }
           }
  }

但由于某些原因,我不能像这样制作API。 (JSON的第一个节点必须是&#34;条目&#34;不是&#34;博客&#34;)

我到目前为止尝试的是添加&#34; accepts_nested_attributes_for&#34;在Entry模型中。

class Entry < ActiveRecord::Base 
   # Entry has 'article' column 
   belongs_to :blog
   accepts_nested_attributes_for :blog
end

然后发布JSON,如

 { "entry" : 
           { "article" : "my first blog entry", 
             "blog_attributes" : 
                    { "title": "My new blog" }
           }
 }

然后在控制器中

 @user.entries.create(params[:entry])

似乎Rails试图创建&#34;博客&#34;使用此代码的条目但由于&#34; blog_attributes&#34;而失败不包含&#39; user_id&#39;。我可以将user_id添加到我的控制器中的参数中,但由于我正在编写@user.entries.create,它应该告诉我现在正在处理哪个用户,这看起来很尴尬。

有没有什么好方法可以让它全部按照我想要的方式工作? (或者我做错了什么?)

1 个答案:

答案 0 :(得分:0)

好的,从您的参赛模式中删除accepts_nested_attributes_for :blog

在您的博客模型中添加了accepts_nested_attributes_for :entries, reject_if: :all_blank, allow_destroy: true

在您的JSON中执行此操作:

{ "blog" : 
           { "title" : "My new blog", 
             "entry" : 
                    { "article": "my first blog entry" }
           }
 }

在您的blogs_controller.rb中执行以下操作:

def blog_params
  params.require(:blog).permit(:id, :title, entries_attributes: [:id, :article, :_destroy])
end

并在您的blogs_controller.rb新操作中:

def new 
 @blog = Blog.new
 @blog.entries.build
end 

//在您的blogs_controller中创建操作:

def create
  @user = Users.find(params[:user_id]) # :user_id is given in URL
  @user.blog.create(blog_params)
end