Rails has_one build_association deletes record before save

rest, ruby-on-rails, ruby-on-rails-4

Solution

It depends on what you want to do

Thoughts

From what you've posted, it seems the `RESTful` structure is still valid for you. You're calling the `new` action on the `subscriptions` controller, which, by definition, means you're making a new subscription (not loading a current subscription)?

You have to remember that Rails is basically just a group of Ruby classes, with instance methods. This means that you don't need to keep entirely to the `RESTful` structure if it doesn't suit

I think your issue is how you're handling the request / action:

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

`@subscription` is building a new `ActiveRecord` object, but doesn't need to be that way. You presumably want to change the subscription (if they have one), or create an association if they don't

Logic

Perhaps you could include some logic in an instance method:

#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

This will give you a populated ActiveRecord, either with data from the subscription, or the new `ActiveRecord` object.

View

In the view, you can then use a select box like this:

#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 %>

They are my thoughts, but I think you want to do something else with your code. If you give me some comments on this answer, we can fix it accordingly!

Problem

So this has been asked previously, but with no satisfying answers. Consider two models, `User`, and `Subscription` associated as such: ``` class User < ActiveRecord::Base has_one :subscription, dependent: :destroy end class Subscription < ActiveRecord::Base belongs_to :user end ``` Inside of SubscriptionsController, I have a new action that looks like this ``` def new user = User.find(params[:user_id]) @subscription = user.build_subscription end ``` Given that a subscription already exists for a user record, I'm faced with the following problem: `user.build_subscription` is destructive, meaning that simply visiting the `new` action actually destroys the association, thereby losing the current subscription record. Now, I could simply check for the subscription's existence and redirect like this: ``` def new user = User.find(params[:user_id]) if user.subscription.present? redirect_to root_path else @subscription = user.build_subscription end end ``` But that doesn't seem all that elegant. Here's my question Shouldn't just building a tentative record for an association not be destructive? Doesn't that violate RESTful routing, since `new` is accessed with a GET request, which should not modify the record? Or perhaps I'm doing something wrong. Should I be building the record differently? Maybe via `Subscription.new(user_id: user.id)`? Doesn't seem to make much sense. Would much appreciate an explanation as to why this is implemented this way and how you'd go about dealing with this. Thanks!

Original source