13

ActiveResourceを使用してネストされたリソースを含むモデルを保存する際に問題が発生しました。ネストされていないリソースを問題なくロードおよび保存でき、リソースとそのネストされたリソースを正常にロードできますが、リソースの保存は失敗します。この問題は、REE 1.8.7 /Rails2.3.9およびRuby1.9.2-p0/Rails3.0.2で発生します。以下の例は、Rails 3 /AR3からのものです。

サンプルアプリには2つのモデルがあります。

  • 資産
  • インターフェース

アセットには多くのインターフェイスがあり、インターフェイスはアセットに属します。

ルート.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, "id"=>1, "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, "description"=>"Testing testing", "id"=>1, "name"=>"Test Asset #1", "updated_at"=>2010-12-07 16:24:59 UTC, "interfaces"=>[{"asset_id"=>1, "created_at"=>2010-12-07 18:01:15 UTC, "id"=>1, "name"=>"eth0", "updated_at"=>2010-12-07 18:01:15 UTC}, {"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}]}, "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'

誰かがこれについて何かアイデアがありますか?私は困惑しています。助けてくれてありがとう!

4

3 に答える 3

7

ActiveResourceには、すぐに使用できる関連付けのサポートはありません。このためにnested_*のものをハイジャックする興味深いアイデア。これは私にとってはうまくいくようです:

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オプションをコントローラーに移動します。また、インターフェイスに正しいattr_protectedが設定されていることを確認することもできます。

于 2010-12-08T03:56:21.180 に答える
6

これは、パラメータを使用して保存する場合に:assetsも機能します。

class Asset < ActiveRecord::Base
  has_many :interfaces
  accepts_nested_attributes_for :interfaces
  attr_accessible :interfaces, :interfaces_attributes
  alias_method :interfaces=, :interfaces_attributes=
end
于 2012-01-26T18:23:00.817 に答える
1

間違ったパラメータを渡しています。ネストされた属性は次のようになります。

:asset => {
  :interface_attributes => { '1' => { :name => "eth0" } }
}

タイムスタンプとIDはActiveRecordによって処理されます。属性を区切る識別子は、一意である限り重要ではないようです。ブラウザで属性を生成するときは、通常、タイムスタンプを使用します。

于 2010-12-08T02:58:14.590 に答える