如何在保存模型时保存rails子模型连接表更改?

时间:2012-12-29 02:30:32

标签: ruby-on-rails ruby-on-rails-3.2 associations autosave jointable

我无法弄清楚如何在我的应用中获取自动保存的连接表记录。我正在构建一个让用户制作书籍的应用程序。他们创建页面并上传图像库,然后将图像连接到页面。每本书都有封面,上面有封面图片。

我的目标是能够设置书籍的cover_image_file_name,并在保存书籍时保存子模型更改。 (我缩小了示例,因此我们不处理实际附加的图像 - 这不是问题)。

class Book < ActiveRecord::Base
  has_many :pages, :dependent=>:destroy, :autosave=>true
  has_many :images, :dependent=>:destroy, :autosave=>true
  attr_accessible :title, :pages_attributes

  # we want to be able to set the cover page image filename for a book
  attr_accessor :cover_image_file_name

  before_validation do 
    # a book always has a cover page as page 0
    cover_page = pages.find_or_initialize_by_page_number(0)
    if @cover_image_file_name
      page_image = cover_page.page_images.find_or_initialize_by_image_type('cover')
      page_image.image = images.find_or_initialize_by_image_file_name(@cover_image_file_name)
    end
  end
end

class Image < ActiveRecord::Base
  belongs_to :book
  has_many :page_images,:dependent=>:destroy
  attr_accessible :image_file_name
end
class Page < ActiveRecord::Base
  belongs_to :book
  has_many :page_images, :dependent=>:destroy, :autosave=>true
  attr_accessible :page_number, :page_images_attributes
end
class PageImage < ActiveRecord::Base
  belongs_to :page
  belongs_to :image
  attr_accessible :image_type, :image
end

现在,当我执行以下代码来创建一本书并设置(或重置)其封面图像时,不会保存将新创建的图像连接到封面页面的page_image对象:

book = Book.new({ title: "Book Title" })
book.save!  # this correctly saves the book and its cover page

book.cover_image_file_name = 'my_cover_page.png'
book.save!  # the image gets created and saved, but not the page_image

我错过了什么?我认为它可能与https://github.com/rails/rails/pull/3610有关,但我使用的是rails 3.2.9。

1 个答案:

答案 0 :(得分:1)

当您尝试将图片分配给 page_image * * belongs_to:image *时,最后一个将不会被保存。因为此时没有保存图像(作为父对象)。

所以你必须保存它才能用book保存page_image。

class Book < ActiveRecord::Base
  has_many :pages, :dependent=>:destroy, :autosave=>true
  has_many :images, :dependent=>:destroy, :autosave=>true
  attr_accessible :title, :pages_attributes

  # we want to be able to set the cover page image filename for a book
  attr_accessor :cover_image_file_name

  before_validation do 
    # a book always has a cover page as page 0
    cover_page = pages.find_or_initialize_by_page_number(0)
    if @cover_image_file_name
      image = images.find_or_initialize_by_image_file_name(@cover_image_file_name).save
      page_image = cover_page.page_images.find_or_initialize_by_image_type('cover')
      page_image.image = image
    end
  end
end

关注的是你的代码运行* before_validation *并且在这个阶段保存任何东西都是错误的。书籍尚未保存,但您已保存其内容...

你必须重写你的回调。让它变得聪明。