2016-01-24 58 views
2

我有一個一對多的相冊和信息之間的關係:Rails的添加元素,一個一對多的關聯

class Post < ActiveRecord::Base 
    belongs_to :album 

class Album < ActiveRecord::Base 
    has_many :posts, dependent: :destroy 
    accepts_nested_attributes_for :posts 

AlbumsController,我想爲後加入到這種關係建立的方法(到Album.posts):

def add_post 
    @album = Album.find(params[:album_id]) 
    params['album']['post_ids'].each do |post_id| 
     @album.posts << Post.find(post_id) 
    end 
end 

它爲什麼不起作用?這樣做的正確方法是什麼?我也嘗試將@album.id分配到帖子的album_id列,但它也沒有做任何事情。

形式如下:

<%= form_for :album, url: album_add_post_path(@album), method: :patch do |f| %> 
     <% @posts.each do |post| %> 
      <%= check_box_tag :post_ids, post.id, @album.posts.include?(post), :name => 'album[post_ids][]' %> 
     <% end %> 
     <%= f.submit class:"btn btn-success"%> 
    <% end %> 
+1

你可以粘貼'form'您使用。 – DevMarwen

回答

1

如果您正在使用嵌套的屬性,像你這樣,你不necesarily必須遍歷相關的訊息來製作。 (這是嵌套屬性的用途)

但是,您必須確保您在參數中允許使用這些post_id這是最常見的錯誤之一(我已經做了幾次自己)

所以,在你的控制器:

def add_post 
    @album = Album.find(params[:album_id]) 
    @album.update(album_params) 
end 

album_params方法如下:

def album_params 
    params.require(:album).permit(..., ..., ..., posts_attributes: [:id, ..., ...]) 
end 

這裏需要注意的重要事項:

  1. 的posts_attributes進來作爲屬性的所有相關聯的屬性(posts_attributes: []
  2. id應當允許對相關聯的屬性,或者新的關聯將總是在每次有一個編輯/更新創建的陣列
  3. 需要被允許的父對象(相冊)的所有屬性在許可證塊(params.require(:album).permit(..., ...,)需要
  4. 子對象(後)的所有屬性被允許列在嵌套屬性框直接列出。 (posts_attributes: [:id, ..., ...]

NOTE: The front-end view form has to be set right as well. An example can be found on this rails cast , And you can check the documentation for more information on this.

我剛纔看到與前端視您的更新。您可以利用已經使用的嵌套屬性,並且通過擴展專輯的帖子解釋瞭如下:

<%= f.fields_for :posts do |p| %> 
    <%= p.collection_select :post_id, Post.order(:name),:id,:name, include_blank: true %> 
<% end %> 
+0

他沒有使用嵌套屬性 –

+0

@RichPeck,但我認爲他是。這是正確的問題。 'Album_need_attributes_for:posts'裏面的專輯模型 –

+0

如果他想*爲專輯創建新帖子,那麼他就不得不使用它;如果他想更改某張專輯中的哪些帖子,則他不需要。 –

0

您的代碼的直接修復是...

#config/routes.rb 
resources :albums do 
    match :posts, via: [:get, :patch], on: :member #-> url.com/albums/:id/posts 
end 

#app/controllers/albums_controller.rb 
class AlbumsController < ApplicationController 
    def posts 
     @album = Album.find params[:id] 
     @posts = Post.all if request.get? 
     if request.patch? 
     @album.update album_params 
     @album.save 
     end 
    end 

    private 

    def album_params 
     params.require(:album).permit(post_ids: []) 
    end 
end 

這可以伴隨着collection_select

#app/views/albums/posts.html.erb 
<%= form_for @album do |f| %> 
    <%= f.collection_select :post_ids, @posts, :id, :name %> 
    <%= f.submit %> 
<% end %> 

然而,這將工作(我相信),你倒是希望。

當使用belongs_to/has_many時,只能有匹配的關係「對」。這意味着添加到singular_collection_ids方法將覆蓋Post記錄中的任何現有的belongs_to參考。

總之,如果你想改變(不添加)你的關聯的對象,它會工作。如果你想現有postsalbum,你必須使用下面的代碼。


你最好使用has_and_belongs_to_many

#config/routes.rb 
resources :album do 
    resources :posts #-> url.com/albums/:album_id/posts/new 
end 

#app/models/album.rb 
class Album < ActiveRecord::Base 
    has_and_belongs_to_many :posts 
end 

#app/models/post.rb 
class Post < ActiveRecord::Base 
    has_and_belongs_to_many :albums 
end 

#app/controllers/albums_controller.rb 
class AlbumsController < ApplicationController 
    def edit 
     @album = Album.find params[:id] 
     @posts = Post.all 
    end 

    def update 
     @album = Album.find params[:id] 
     @album.update album_params 
    end 

    private 

    def album_params 
     params.require(:album).permit(post_ids: []) 
    end 
end 

#app/views/albums/edit.html.erb 
<%= form_for @album do |f| %> 
    <%= f.collection_select :post_ids, @posts, :id, :name %> 
    <%= f.submit %> 
<% end %> 
+0

當我嘗試做直接修復時(我不介意覆蓋belongs_to引用,如果帖子已經屬於另一個專輯),我出現此錯誤:已完成422 17ms內無法處理的實體(ActiveRecord:1.3ms) ActiveRecord :: RecordNotSaved(由於無法保存一個或多個新記錄而無法替換帖子): app/controllers/albums_controller .rb:51:在'posts' – user238312

+0

您使用了哪些代碼? –

+0

好吧,我甚至無法在rails控制檯中更改album.posts或post.album_id,如果它已經設置(如果它尚未設置,這是可能的)。有沒有辦法如何做到這一點? (我不想讓帖子屬於多個專輯,這就是爲什麼我嘗試了第一個版本的代碼,我想覆蓋現有的關聯)。 – user238312