2014-06-10 48 views
0

我想在我的應用程序中一個帖子有很多位置(通過locations_posts表)執行find_or_create函數(類似於here)。不幸的是,代碼似乎執行,找到正確的記錄,然後繼續創建一個新的記錄,導致記錄重複。任何想法爲什麼會發生這種情況?使用Find_or_Create創建重複的模型

Post.rb

class Post < ActiveRecord::Base 

    before_save :get_locations 

    # =============== 
    # = Before Save = 
    # =============== 




    def get_locations 
    self.locations = self.locations.collect do |location| 
     Location.find_or_create_by(name: location[:name]) 
    end 
    end 


    # ================= 
    # = Associations = 
    # =================  

    has_many :location_post 
    has_many :locations, :through => :location_post 

    accepts_nested_attributes_for :locations 

posts_controller.rb

class PostsController < ::Blogit::ApplicationController  

... 

def create 
    @post = current_blogger.blog_posts.new(valid_params) 
    if @post.save 
    redirect_to @post, notice: t(:blog_post_was_successfully_created, scope: 'blogit.posts') 
    else 
    render action: "new" 
    end 
end 

日誌

Parameters: {"utf8"=>"✓", "authenticity_token"=>"n4s...uAHATBRG1Nk=", "post"=>{"title"=>"Lorem ipsum dolor sit am 
et", "body"=>"Consectetur adipiscing elit. Duis in diam in massa aliquet venenatis. Donec eleifend sed magna rutrum sagittis.", "locations_attributes"=>{"1402420506265"=>{"name"=>"London", "_destroy"=>"false"}}}, "commit"=>"Submit"} 

    User Load (0.8ms) SELECT "users".* FROM "users" WHERE "users"."id" = 1 ORDER BY "users"."id" ASC LIMIT 1 
Unpermitted parameters: _destroy 
    (0.3ms) BEGIN 

    Location Load (0.6ms) SELECT "locations".* FROM "locations" WHERE "locations"."name" = 'London' LIMIT 1 

    SQL (0.5ms) INSERT INTO "blog_posts" ("blogger_id", "blogger_type", "body", "created_at", "title", "updated_at") VALUES ($1, $2, $3, $4, $ 
5, $6) RETURNING "id" [["blogger_id", 1], ["blogger_type", "User"], ["body", "Consectetur adipiscing elit. Duis in diam in massa aliquet ven 
enatis. Donec eleifend sed magna rutrum sagittis."], ["created_at", "2014-06-10 17:15:09.564257"], ["title", "Lorem ipsum dolor sit amet"], [ 
"updated_at", "2014-06-10 17:15:09.564257"]] 

    SQL (0.4ms) INSERT INTO "locations" ("created_at", "name", "updated_at") VALUES ($1, $2, $3) RETURNING "id" [["created_at", "2014-06-10 1 
7:15:09.566659"], ["name", "London"], ["updated_at", "2014-06-10 17:15:09.566659"]] 
    SQL (0.4ms) INSERT INTO "location_posts" ("created_at", "location_id", "post_id", "updated_at") VALUES ($1, $2, $3, $4) [["created_at", " 
2014-06-10 17:15:09.568250"], ["location_id", 376], ["post_id", 83], ["updated_at", "2014-06-10 17:15:09.568250"]] 
    SQL (0.3ms) INSERT INTO "location_posts" ("created_at", "location_id", "post_id", "updated_at") VALUES ($1, $2, $3, $4) [["created_at", " 
2014-06-10 17:15:09.571852"], ["location_id", 1], ["post_id", 83], ["updated_at", "2014-06-10 17:15:09.571852"]] 
    (0.7ms) COMMIT 
+0

請在get_locations方法中顯示self.locations內容。 – tebayoso

+0

嗨@JorgedelosSantos,抱歉不知道你的意思? –

+0

在執行get_location循環之前顯示自我對象的內容。 self.inspect並放置內容。 – tebayoso

回答

1

哦,男人,你的問題讓我走下了一個兔子洞。所以,讓我回顧一下,你的前提很簡單:在保存帖子之前,你要確保如果位置已經存在於數據庫中,則使用它們。這聽起來很簡單,它曾經工作。在軌道3.x東西

所以我重新創建你的榜樣,你看:我到處都是雙打。

不知怎的,總是想起原來的位置添加,然後我恍然大悟:立即增加了新的位置到location_posts爲好,當我再改locations,我其實增加地點location_posts

所以放心:該作品find_or_create_by完美:)

所以很多試驗和錯誤之後,我能夠解決這個問題如下:

before_save :reuse_existing_locations 

def reuse_existing_locations 
    new_locations = locations.map do |location | 
    if location.new_record? 
     new_loc = Location.find_by(name: location.name) 
     new_loc.present? ? new_loc : location.dup 
    else 
     location.dup 
    end 
    end 

    self.location_posts.reset 
    self.locations.replace(new_locations) 
end 

所以關鍵-採取贈品:

  • dup(副本)的所有元素,否則當我做了更換或重置,該列表將是空的
  • 重置location_posts所以它是空的,之前插入「新」位置
  • 使用replace用新的(否則它也只是補充)

我不得不更換的位置的當前陣列感覺這是一個軌道錯誤,但不確定。至少它比以前困難得多。

+0

完美!沒有問題,第一次工作。可以做一些研究,看它是否確實是一個錯誤。謝謝@nathanvda –

0

我的猜測是,你可以REM只要它看起來不工作,就可以使用before_save:

self.locations是一種調用關係的關係,它收集活動記錄數組中的所有現有項目。如果這些物品不在表格中,只要它不會找到任何未保留的物品,他就不會創建新的物品。

嵌套參數是負責執行查找或爲位置創建的參數。只要您定義從控制器傳遞給後期模型的主鍵即可。

這是嵌套的工作流程:

  • 控制器創建與PARAMS的新模式,並與嵌套PARAMS 相關模型的新實例,並開始交易。
  • 如果 第一個模型被保存,則關係被保存在現有的id上,或者創建一個新的。
  • 如果第一個模型或第二個模型失敗,則事務回滾並且不保存任何內容。

如果嵌套參數不是自己創建位置(或者更新(如果存在)),這意味着您沒有傳遞正確的參數,或者您沒有發送主鍵。

+0

嗨@喬治我不知道我明白。我通過location_posts聲明瞭has_many:locations(參見上文)。 Update_only作爲嵌套屬性參數也無效。任何其他想法? –

+0

accepted_nested_attributes_for:locations,:update_only => true – tebayoso

+0

嗨豪爾赫,是的,我試過這個,但一直沒有變化。重複仍在創建中。 –