0

我試圖在我的rails(版本3.2.9)應用程序中使用REST API。從json POST返回的重複嵌套關聯

我將json數據包發送到標準導軌腳手架控制器,其中包括模型本身的詳細信息以及嵌套的子級。

父模型及其子模型已成功插入數據庫。但是,來自POST的響應使嵌套的子項翻倍。

爲什麼嵌套關聯在POST響應中翻倍了?過去幾天我一直在努力爭取這一點......這讓我感到非常緊張。

具體實例

JSON請求

POST http://localhost:3000/audio_events HTTP/1.1 
Host: localhost:3000 
Connection: keep-alive 
Content-Length: 432 
Accept: application/json, text/plain, */* 

{ 
    "audio_event": { 
     "start_time_seconds": 0.05, 
     "end_time_seconds": 15.23, 
     "low_frequency_hertz": 1000, 
     "high_frequency_hertz": 8753, 
     "audio_event_tags_attributes": [ 
      { 
       "tag_id": "-1" 
      }, 
      { 
       "tag_id": "-2" 
      } 
     ], 
     "audio_recording_id": "1bd0d668-1471-4396-adc3-09ccd8fe949a" 
    } 
} 

JSON響應

HTTP/1.1 201 Created 
Location: http://localhost:3000/audio_events/27 
Content-Type: application/json; charset=utf-8 
X-Ua-Compatible: IE=Edge 
Etag: "c79ccdf981a9fadad3a8b08c3a878e8e" 
Cache-Control: max-age=0, private, must-revalidate 
Content-Length: 924 
Server: WEBrick/1.3.1 (Ruby/1.9.3/2012-04-20) 
Date: Mon, 26 Nov 2012 00:27:47 GMT 
Connection: Keep-Alive 

{ 
    "created_at": "2012-11-26T00:27:32Z", 
    "creator_id": 1, 
    "deleted_at": null, 
    "deleter_id": null, 
    "end_time_seconds": "15.23", 
    "high_frequency_hertz": "8753.0", 
    "id": 27, 
    "is_reference": false, 
    "low_frequency_hertz": "1000.0", 
    "start_time_seconds": "0.05", 
    "updated_at": "2012-11-26T00:27:32Z", 
    "updater_id": 1, 
    "audio_event_tags": [ 
     { 
      "audio_event_id": 27, 
      "created_at": "2012-11-26T00:27:32Z", 
      "creator_id": 1, 
      "tag_id": -1, 
      "updated_at": "2012-11-26T00:27:32Z", 
      "updater_id": 1 
     }, 
     { 
      "audio_event_id": 27, 
      "created_at": "2012-11-26T00:27:32Z", 
      "creator_id": 1, 
      "tag_id": -2, 
      "updated_at": "2012-11-26T00:27:32Z", 
      "updater_id": 1 
     }, 
     // DUPLICATES ARE HERE 
     { 
      "audio_event_id": 27, 
      "created_at": "2012-11-26T00:27:32Z", 
      "creator_id": 1, 
      "tag_id": -1, 
      "updated_at": "2012-11-26T00:27:32Z", 
      "updater_id": 1 
     }, 
     { 
      "audio_event_id": 27, 
      "created_at": "2012-11-26T00:27:32Z", 
      "creator_id": 1, 
      "tag_id": -2, 
      "updated_at": "2012-11-26T00:27:32Z", 
      "updater_id": 1 
     } 
    ], 
    "audio_recording": { 
     "id": 1, 
     "uuid": "1bd0d668-1471-4396-adc3-09ccd8fe949a" 
    } 
} 

模型

多對多模型

class AudioEventTag < ActiveRecord::Base 
    belongs_to :audio_event 
    belongs_to :tag 
    accepts_nested_attributes_for :audio_event 

    attr_accessible :audio_event, :tag, :tag_id 

    stampable 
    belongs_to :user, :class_name => 'User', :foreign_key => :creator_id 

    validates_uniqueness_of :audio_event_id, :scope => :tag_id 
end 

標籤模型

class Tag < ActiveRecord::Base 
    has_many :audio_event_tags 
    has_many :audio_events, :through => :audio_event_tags 
    accepts_nested_attributes_for :audio_events, :audio_event_tags 

    attr_accessible :is_taxanomic, :text, :type_of_tag 

    stampable 
    belongs_to :user, :class_name => 'User', :foreign_key => :creator_id 
    acts_as_paranoid 
    validates_as_paranoid 
end 

音頻事件模型

class AudioEvent < ActiveRecord::Base 
    belongs_to :audio_recording 

    has_many :tags, :through => :audio_event_tags, :uniq => true 

    has_many :audio_event_tags 
    accepts_nested_attributes_for :audio_event_tags 

    attr_accessible :audio_recording_id, :end_time_seconds, :high_frequency_hertz, :is_reference, 
        :low_frequency_hertz, :start_time_seconds, 
        :tags_attributes, :audio_event_tags_attributes 

    stampable 
    belongs_to :user, :class_name => 'User', :foreign_key => :creator_id 
    acts_as_paranoid 
    validates_as_paranoid 

    # validation 
    validates :audio_recording, :presence => true 

    validates :start_time_seconds, :presence => true, :numericality => { :greater_than_or_equal_to => 0 } 
    validates :end_time_seconds, :numericality => { :greater_than_or_equal_to => 0 } 

    validates :low_frequency_hertz, :presence => true, :numericality => { :greater_than_or_equal_to => 0 } 
    validates :high_frequency_hertz, :numericality => { :greater_than_or_equal_to => 0 } 

    # json formatting 
    def as_json(options={}) 
    super(
     :include => 
      [ 
       :audio_event_tags, 
       :audio_recording => {:only => [:id, :uuid]} 
      ], 
     :except => :audio_recording_id 
    ) 
    end 
end 

更新

作爲控制器要求的意見,該代碼爲我的行動

# POST /audio_events 
# POST /audio_events.json 
def create 
    @audio_event = AudioEvent.new(params[:audio_event]) 
    #@audio_event.audio_event_tags.each{ |aet| aet.build() } 

    #@audio_event.audio_event_tags.count.times { @audio_event.audio_event_tags.build } 

    respond_to do |format| 
    if @audio_event.save 

     format.json { render json: @audio_event, status: :created, location: @audio_event } 
    else 
     format.json { render json: @audio_event.errors, status: :unprocessable_entity } 
    end 
    end 
end 

而且,我試圖刪除這個stampable d acts_as_paranoid宏無效。

更新2

如果我嘗試添加3個嵌套屬性,我得到6回。 4返回8,並且5返回10.

+0

我發佈了一個關於一個可以由''as_json'使用的答案的答案:http://stackoverflow.com/questions/3872236/rails-object-to-hash/8429140#8429140 也許這可以幫助找到你的問題是什麼。我會在今天晚些時候嘗試執行你的代碼,看看我能否找出發生了什麼。 – Raf

+0

那麼我做了你的模型的快速實施,我似乎無法得到重複。它按預期工作。也許問題不在於你的模型,而在於你調用模型序列化的方式。你能用這個代碼更新你的答案嗎? – Raf

+0

我只是想知道,你是否試圖看到當你註釋掉stampable和acts_as_paranoid宏時會發生什麼?也許他們會擋你的路。這兩個都擺弄積極的記錄內部... –

回答

0

重新發表評論。

看起來像json序列化問題。如果單獨獲得工作,您可以在控制器中的format.json之前嘗試@audio_event.audio_event_tags.reload

- 這當然很奇怪。 audio_event_tags的內存詳細信息在@ audio_event.save行中搞砸了。 AudioEvent是否有after_save回調?如果沒有回調,那麼我不知道如何發生。需要重現它。如果發生所有嵌套屬性,處理這個問題是一個嚴重的問題。

+0

這似乎是唯一的工作。有點煩人,我不得不額外查詢重新加載audio_event_tags ......我不明白爲什麼它需要這樣......至少我可以繼續前進。 FYI @so_mv,AudioEvent和AudioEventTag都有一個after_save callack set ...從調試開始,after_save prop有一個數組,其中有一個項目,屬於同一個類。我試圖清除這些數組無效。 –

+0

如果你想避免數據庫調用,你可以試試@ audio_event.audio_event_tags.uniq!{| aet | aet.tag_id}而不是.reload。請注意,uniq!僅適用於Ruby 1.9.3。 v1.8.7也有uniq,但不使用該塊進行比較。 –