LoginSignup
1
1

More than 5 years have passed since last update.

複数の子レコードを作成、更新する

Posted at

1対1の時

MemberモデルはAbatarモデルに1対1の関連を持っている

app/assets/models/member.rb
class Member < ActiveRecord::Base
  has_one :avatar
  accepts_nested_attributes_for :avatar, allow_destroy: true
end
app/assets/controllers/members_controller.rb
def create
  params = { member: { name: 'Jack', avatar_attributes: { icon: 'smiling' } } }
  member = Member.create(params[:member])
  member.avatar.id # => 2
  member.avatar.icon # => 'smiling'
end

def update
  params = { member: { avatar_attributes: { id: '2', icon: 'sad' } } }
  member.update params[:member]
  member.avatar.icon # => 'sad'
end

def destroy
  member.avatar_attributes = { id: '2', _destroy: '1' }
  member.avatar.marked_for_destruction? # => true
  member.save
  member.reload.avatar # => nil
end

1対多の時

MemberモデルはPostモデルに1対多の関連を持っている

app/assets/models/member.rb
class Member < ActiveRecord::Base
  has_many :posts
  accepts_nested_attributes_for :posts, allow_destroy: true
end
app/assets/controllers/members_controller.rb
def create
  params = { member: {
  name: 'joe', posts_attributes: [
    { title: 'Kari, the awesome Ruby documentation browser!' },
    { title: 'The egalitarian assumption of the modern citizen' },
    { title: '', _destroy: '1' } # this will be ignored
  ]
}}

member = Member.create(params[:member])
member.posts.length # => 2
member.posts.first.title # => 'Kari, the awesome Ruby documentation browser!'
member.posts.second.title # => 'The egalitarian assumption of the modern citizen'
end

def update
  member.attributes = {
  name: 'Joe',
  posts_attributes: [
    { id: 1, title: '[UPDATED] An, as of yet, undisclosed awesome Ruby documentation browser!' },
    { id: 2, title: '[UPDATED] other post' }
  ]
}

member.posts.first.title # => '[UPDATED] An, as of yet, undisclosed awesome Ruby documentation browser!'
member.posts.second.title # => '[UPDATED] other post'
end

def destroy
  params = { member: {
  posts_attributes: [{ id: '2', _destroy: '1' }]
}}

member.attributes = params[:member]
member.posts.detect { |p| p.id == 2 }.marked_for_destruction? # => true
member.posts.length # => 2
member.save
member.reload.posts.length # => 1
end

reject_if

パラメータが指定した条件に合致した場合、子要素を作成しない.
procとmethodのシンボルで指定可能

proc

app/assets/models/member.rb
class Member < ActiveRecord::Base
  has_many :posts
  accepts_nested_attributes_for :posts, reject_if: proc { |attributes| attributes['title'].blank? }
end

method

app/assets/models/member.rb
class Member < ActiveRecord::Base
  has_many :posts
  accepts_nested_attributes_for :posts, reject_if: :reject_posts

  def reject_posts(attributed)
    attributed['title'].blank?
  end
end

参考

複数の子レコードを作成・更新する. accepts_nested_attributes_for
http://qiita.com/hmuronaka/items/818c421dc632e3efb7a6#3-1

1
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
1