ruby-on-rails – Rails无法通过ActiveResource保存嵌套资源

我使用ActiveResource保存一个嵌套资源的模型时遇到问题:我可以加载和保存一个没有问题的非嵌套资源,我可以加载一个资源加其嵌套资源,但保存资源失败.使用REE 1.8.7 / Rails 2.3.9和 Ruby 1.9.2-p0 / Rails 3.0.2发生此问题.以下示例来自Rails 3 / AR 3.

我的示例应用程序有两个模型:

资产
>界面

资产有很多接口,接口属于资产.

的routes.rb

Rails3Testapp::Application.routes.draw do
 resources :interfaces
 resources :assets
end

相关AssetController操作

def index
    @assets = Asset.all

    respond_to do |format|
      format.html # index.html.erb
      format.xml  { render :xml => @assets,:include => [ :interfaces ] }
    end
  end

  def show
    @asset = Asset.find(params[:id])

    respond_to do |format|
      format.html # show.html.erb
      format.xml  { render :xml => @asset,:include => [ :interfaces ] }
    end
  end

  def update
    @asset = Asset.find(params[:id])

    respond_to do |format|
      if @asset.update_attributes(params[:asset])
        format.html { redirect_to(@asset,:notice => 'Asset was successfully updated.') }
        format.xml  { head :ok }
      else
        format.html { render :action => "edit" }
        format.xml  { render :xml => @asset.errors,:status => :unprocessable_entity }
      end
    end
  end

楷模

class Asset < ActiveRecord::Base
  has_many :interfaces

  accepts_nested_attributes_for :interfaces
end

class Interface < ActiveRecord::Base
  belongs_to :asset
end

复制步骤

>> require 'active_resource'
=> true
>> class Asset < ActiveResource::Base
>>   self.site = 'http://localhost:3000/'
>> end
>> test_asset = Asset.first
=> #<Asset:0x00000100a86690 @attributes={"created_at"=>2010-12-07 16:24:59 UTC,"description"=>"Testing testing","id"=>1,"name"=>"Test Asset #1","updated_at"=>2010-12-07 16:24:59 UTC,"interfaces"=>[#<Asset::Interface:0x00000100a7dc98 @attributes={"asset_id"=>1,"created_at"=>2010-12-07 18:01:15 UTC,"name"=>"eth0","updated_at"=>2010-12-07 18:01:15 UTC},@prefix_options={}>,#<Asset::Interface:0x00000100a7a8e0 @attributes={"asset_id"=>1,"created_at"=>2010-12-07 18:04:49 UTC,"id"=>2,"name"=>"eth1","updated_at"=>2010-12-07 18:04:49 UTC},@prefix_options={}>]},@prefix_options={}>
>> test_asset.save
ActiveResource::ServerError: Failed.  Response code = 500.  Response message = Internal Server Error .
    from /Users/threetee/.rvm/gems/ruby-1.9.2-p0@rails3/gems/activeresource-3.0.3/lib/active_resource/connection.rb:147:in `handle_response'
    from /Users/threetee/.rvm/gems/ruby-1.9.2-p0@rails3/gems/activeresource-3.0.3/lib/active_resource/connection.rb:114:in `request'
    from /Users/threetee/.rvm/gems/ruby-1.9.2-p0@rails3/gems/activeresource-3.0.3/lib/active_resource/connection.rb:91:in `block in put'
    from /Users/threetee/.rvm/gems/ruby-1.9.2-p0@rails3/gems/activeresource-3.0.3/lib/active_resource/connection.rb:217:in `with_auth'
    from /Users/threetee/.rvm/gems/ruby-1.9.2-p0@rails3/gems/activeresource-3.0.3/lib/active_resource/connection.rb:91:in `put'
    from /Users/threetee/.rvm/gems/ruby-1.9.2-p0@rails3/gems/activeresource-3.0.3/lib/active_resource/base.rb:1307:in `update'
    from /Users/threetee/.rvm/gems/ruby-1.9.2-p0@rails3/gems/activeresource-3.0.3/lib/active_resource/observing.rb:11:in `update_with_notifications'
    from /Users/threetee/.rvm/gems/ruby-1.9.2-p0@rails3/gems/activeresource-3.0.3/lib/active_resource/base.rb:1117:in `save'
    from /Users/threetee/.rvm/gems/ruby-1.9.2-p0@rails3/gems/activeresource-3.0.3/lib/active_resource/validations.rb:87:in `save_with_validation'
    from /Users/threetee/.rvm/gems/ruby-1.9.2-p0@rails3/gems/activeresource-3.0.3/lib/active_resource/observing.rb:11:in `save_with_notifications'
    from (irb):33
    from /Users/threetee/.rvm/rubies/ruby-1.9.2-p0/bin/irb:17:in `<main>'

日志

Started PUT "/assets/1.xml" for 127.0.0.1 at 2010-12-07 11:58:40 -0800
  Processing by AssetsController#update as XML
  Parameters: {"asset"=>{"created_at"=>2010-12-07 16:24:59 UTC,"interfaces"=>[{"asset_id"=>1,{"asset_id"=>1,"updated_at"=>2010-12-07 18:04:49 UTC}]},"id"=>"1"}
  sql (0.8ms)   SELECT name
 FROM sqlite_master
 WHERE type = 'table' AND NOT name = 'sqlite_sequence'

  Asset Load (0.2ms)  SELECT "assets".* FROM "assets" WHERE ("assets"."id" = 1) LIMIT 1
WARNING: Can't mass-assign protected attributes: id
Completed   in 161ms

ActiveRecord::AssociationTypeMismatch (Interface(#2154409400) expected,got ActiveSupport::HashWithIndifferentAccess(#2154546040)):
  app/controllers/assets_controller.rb:62:in `block in update'
  app/controllers/assets_controller.rb:61:in `update'

有人有这个想法吗?我被困了提前感谢任何帮助!

解决方法

ActiveResource没有开箱即用的关联支持.有趣的想法来劫持这个嵌套的*东西.这似乎对我有用:
class Asset < ActiveRecord::Base
  has_many :interfaces
  accepts_nested_attributes_for :interfaces
  alias interfaces_attributes interfaces

  def to_xml(options = {})
    super(options.merge({:methods => :interfaces_attributes}))
  end
end

如果您愿意,将to_xml选项移动到控制器中.可能还要确保Interface具有正确的attr_protected的.

相关文章

以下代码导致我的问题: class Foo def initialize(n=0) @n = n end attr_accessor :n d...
这是我的spec文件,当为上下文添加测试“而不是可单独更新用户余额”时,我得到以下错误. require 's...
我有一个拦截器:DevelopmentMailInterceptor和一个启动拦截器的inititializer setup_mail.rb. 但我想将...
例如,如果我有YAML文件 en: questions: new: 'New Question' other: recent: ...
我听说在RSpec中避免它,let,let !,指定,之前和主题是最佳做法. 关于让,让!之前,如果不使用这些,我该如...
我在Rails中使用MongoDB和mongo_mapper gem,项目足够大.有什么办法可以将数据从Mongoid迁移到 Postgres...