【问题标题】:Create nested records on put/post with accepts_nested_attributes_for使用 accept_nested_attributes_for 在 put/post 上创建嵌套记录
【发布时间】:2011-07-21 17:49:53
【问题描述】:

我有两个模型,

风景:

class Landscape < ActiveRecord::Base
  has_many :images, :as => :imageable
  accepts_nested_attributes_for :images, :allow_destroy => true  
  attr_accessible :id, :name, :city, :state, :zip, :gps, :images, :images_attributes, :address1

  def autosave_associated_records_for_images 
    logger.info "in autosave"
    images.each do |image|
      if new_image = Image.find(image.id) then
        new_image.save!
      else
        self.images.build(image)
      end
    end
  end
end

图片:

class Image < ActiveRecord::Base
  belongs_to :imageable, :polymorphic => true
end

我正在从 iPhone 发送帖子并提出请求,以使用 json 更新/创建横向记录。这是一个示例 POST 请求,用于创建新的风景记录和新的关联图像记录

{
  "landscape":{
    "id":0,
    "name":"New Landscape",
    "city":"The City",
    "state":"LA",
    "zip":"71457",
    "images_attributes":[
      {
        "id":0,
        "image_data":"image data image data image data",
        "is_thumbnail":1
      }
     ],
    "address1":"1800 Fancy Road"
  }

}

当服务器接收到这个时,它会吐出

ActiveRecord::RecordNotFound (Couldn't find Image with ID=0 for Landscape with ID=0):

所以这似乎是某种循环引用问题,但目前尚不清楚如何解决它。同样有趣的是 autosave_associated_records_for_images 似乎从未被调用(也几乎没有该函数的文档,我不得不查看 rails 源代码)。

我几乎阅读了有关 accept_nested_attributes_for 的所有 SO 帖子,但都没有运气。

更新

我现在创建了记录,但我无法让 rails 将图像数据传回 Image 模型。让我举例说明:

Started POST "/landscapes" for 127.0.0.1 at 2011-07-22 19:43:23 -0500
  Processing by LandscapesController#create as JSON
  Parameters: {"landscape"=>{"name"=>"asdf", "id"=>0, "address1"=>"asdf", "city"=>"asdf", "images_attributes"=>[{"id"=>0, "image_data"=>"Im a bunch of image data image data image data", "is_thumbnail"=>1}]}}
  SQL (0.1ms)  BEGIN
  SQL (1.6ms)  describe `landscapes`
  AREL (0.2ms)  INSERT INTO `landscapes` (`address1`, `city`, `gps`, `name`, `state`, `zip`, `updated_at`, `created_at`) VALUES (NULL, NULL, NULL, NULL, NULL, NULL, '2011-07-23 00:43:23', '2011-07-23 00:43:23')
  SQL (1.0ms)  describe `images`
  AREL (0.1ms)  INSERT INTO `images` (`image_caption`, `image_data`, `is_thumbnail`, `created_at`, `updated_at`, `imageable_id`, `imageable_type`) VALUES (NULL, NULL, NULL, '2011-07-23 00:43:23', '2011-07-23 00:43:23', 46, 'Landscape')
  SQL (0.2ms)  COMMIT
Completed 201 Created in 37ms (Views: 2.2ms | ActiveRecord: 14.5ms)

当我定义 autosave_asociated_records_for_images 时会发生这种情况。但是,如果我这样定义它:

def autosave_associated_records_for_images
  logger.info "in autosave"
  logger.info images.to_s
end

我看到以下输出:

Started POST "/landscapes" for 127.0.0.1 at 2011-07-22 19:50:57 -0500
  Processing by LandscapesController#create as JSON
  Parameters: {"landscape"=>{"name"=>"asdf", "id"=>0, "address1"=>"asdf", "city"=>"asdf", "images_attributes"=>[{"id"=>0, "image_data"=>"Im a bunch of image data image data image data", "is_thumbnail"=>1}]}}
  SQL (0.1ms)  BEGIN
  SQL (1.6ms)  describe `landscapes`
  AREL (0.2ms)  INSERT INTO `landscapes` (`address1`, `city`, `gps`, `name`, `state`, `zip`, `updated_at`, `created_at`) VALUES (NULL, NULL, NULL, NULL, NULL, NULL, '2011-07-23 00:50:57', '2011-07-23 00:50:57')
in autosave
[#<Image id: nil, image_caption: nil, image_data: nil, is_thumbnail: nil, created_at: nil, updated_at: nil, imageable_id: nil, imageable_type: "Landscape">]
  SQL (0.2ms)  COMMIT
Completed 201 Created in 32ms (Views: 2.2ms | ActiveRecord: 2.1ms)

这很奇怪!它正确地创建了关系,但实际上并没有用我发送的数据填充数据库。有什么想法吗?

【问题讨论】:

  • 在参数中使用 POST 发送 id 的原因是什么?
  • 你能复制粘贴你的控制器代码吗?
  • 这个要点有我的风景和图像控制器:gist.github.com/1099067
  • @mikhailov,我在服务器发送的 json 的反向序列化(所以我从 json 映射到 Core Data,然后返回到相同的 json 属性,将图像更改为 images_attributes 什么轨道预计)。如果这会产生影响,我可以删除 id,但我已经将其他模型(非嵌套)发布到同一台服务器,id 为零,并且它成功创建了新记录。
  • @Eval,从控制器和 development.log 复制粘贴代码。会有很大帮助

标签: ruby-on-rails json nested-attributes autosave


【解决方案1】:

我从来没有在这里找到任何解决方案。我所做的是通过循环参数在控制器中手动执行此操作。

【讨论】:

  • 有类似的问题,但 ActiveRecord 应该足够聪明,可以解决这个问题,我想。
  • 我也有类似的问题。我认为有一些 Rails 错误。
【解决方案2】:

我猜错误来自:

Image.find(image.id)

确实,当什么都没找到时,这会引发异常。

只需将_it替换为:

Image.find_by_id(image.id)

如果没有找到,它会吐出nil

【讨论】:

  • 我尝试了这个,但它没有成功。如果您查看我发布的代码,您会发现我尝试从 autosave_associated_records_for_images 方法中进行日志记录。没有记录任何内容,因此似乎没有调用该函数。
  • 好的,但是autosave_associated_records_for_images 被称为after_createafter_update,你为什么不创建自己的before_save 呢?
  • 我在 before_save 中尝试过。它没有用,并且再次没有将任何内容写入日志。您在哪里看到 autosave_associated_records_for_images 被称为 after_create?我找不到太多关于它的文档。
  • 我在 Rails 代码中直接看到了:github.com/rails/rails/blob/master/activerecord/lib/…
【解决方案3】:

autosave_associated_records_for_images 方法包含太多对该类的责任。解决方案是将这个方法逻辑移到 Image 类中。每个 ActiveRecord 类实例都有默认的回调,例如 before_validation、before_create。我建议你先使用它们

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2018-12-23
    • 2011-07-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多