2014-01-06 73 views
5

所以這已經被問過,但沒有令人滿意的答案。Rails has_one build_association在保存之前刪除記錄

考慮兩個型號,UserSubscription因此相關:

class User < ActiveRecord::Base 
     has_one :subscription, dependent: :destroy 
end 

class Subscription < ActiveRecord::Base 
     belongs_to :user 
end 

內SubscriptionsController的,我有一個新的動作,看起來像這樣

def new 
    user = User.find(params[:user_id]) 
    @subscription = user.build_subscription 
end 

由於訂閱已經存在用戶記錄,我面臨以下問題:

user.build_subscription破壞性,這意味着只需訪問new行動實際上破壞了締合,從而失去目前的預訂記錄。現在

,我可以簡單地檢查訂閱的存在和重定向這樣的:

def new 
    user = User.find(params[:user_id]) 
    if user.subscription.present? 
     redirect_to root_path 
    else 
     @subscription = user.build_subscription 
    end 
end 

但是,這似乎並沒有那麼優雅。

這裏是我的問題

不應該只是建立一個暫定紀錄協會不是破壞性? 這是不是違反了RESTful路由,因爲new是用GET請求訪問的,哪個不應該修改記錄?

或者我做錯了什麼。我應該建立不同的記錄嗎?也許通過Subscription.new(user_id: user.id)?似乎沒有多大意義。

非常感謝解釋爲什麼這是以這種方式實現的,以及如何處理這個問題。

謝謝!

回答

2

這取決於你想要做


思考

從你貼什麼什麼,似乎RESTful結構仍然是有效的爲您服務。您正在調用subscriptions控制器上的new操作,根據定義,這意味着您正在進行新訂閱(不加載當前訂閱)?

你必須記住,Rails基本上只是一組具有實例方法的Ruby類。這意味着,你不必完全保持到了RESTful結構,如果它不適合

我覺得你的問題是,你是如何處理的請求/動作:

def new 
    user = User.find(params[:user_id]) 
    @subscription = user.build_subscription 
end 

@subscription正在建設一個新的ActiveRecord對象,但並不需要那樣。你可能想改變訂閱(如果他們有一個),或創建一個協會,如果他們不這樣做


邏輯

也許你可以包括在實例方法的一些邏輯:

#app/models/user.rb 
Class User < ActiveRecord::Base 

    def build 
     if subscription 
      subscription 
     else 
      build_subscription 
     end 
    end 

end 

#app/controllers/subscriptions_controller.rb 
def new 
    user = User.find(params[:user_id]) 
    @subscription = user.build 
end 

這將爲您提供填充的ActiveRecord,可以使用訂閱中的數據,也可以使用新的ActiveRecord對象。


查看

在視圖中,然後你可以使用一個選擇框是這樣的:

#app/views/subscriptions/new.html.erb 
<%= form_for @subscription do |f| %> 
    <%= "User #{params[:user_id]}'s subscription: %> 
    <%= f.collection_select :subscription_id, Subscription.all,:id , :name %> 
<% end %> 

他們是我的想法,但我想你想做些別的事情與你的代碼。如果你給我這個答案的一些意見,我們可以相應地解決它!

1

我也一直認爲,user.build_foobar只會被寫入數據庫,如果此後調用user.save。一個問題:在調用user.build_subscription之後,舊的訂閱仍在數據庫中嗎?

什麼是輸出user.persisted?user.subscription.persisted?,調用後user.build_subscription

您的方法來檢查訂閱是否存在,恕我直言,絕對好的和有效的。

0

我今天遇到這個,並同意在調用構建時從db中刪除某些東西是一個非常意想不到的結果(導致我們有不良數據)。正如你所建議的那樣,只要簡單地進行Subscription.new(user:user)就可以解決問題。我個人認爲這是不可讀的,然後user.build_subscription。

0

截至2018理查德·佩克的解決方案爲我工作:

#app/models/user.rb 
Class User < ActiveRecord::Base 

    def build_a_subscription 
     if subscription 
      subscription 
     else 
      build_subscription 
     end 
    end 
    end 

我的問題是,用戶控制器沒有一個新的方法,因爲用戶的API或種子文件來了。 所以我的樣子:

#app/controllers/subscriptions_controller.rb 
def update 
    @user = User.find(params[:id]) 
    @user.build_a_subscription 
    if @user.update_attributes(user_params) 
    redirect_to edit_user_path(@user), notice: 'User was successfully updated.' 
    else 
    render :edit 
    end 
end 

我終於能有訂閱的正確奇異的版本在我fields_for,所以:subscription詩句:subscriptions

#app/views 
<%= f.fields_for :subscription do |sub| %> 
    <%= render 'subscription', f: sub %> 
<% end %> 

之前,我只能拿到fields_for展示在我看來,如果我訂閱複數。然後它不會保存。 但現在,一切正常。