2014-01-06 72 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展示在我看来,如果我订阅复数。然后它不会保存。 但现在,一切正常。