I was trying something similar (using Rails 4.2.4) and arrived at this solution.
app/models/user.rb
The allow_destroy: true
will allow you to destroy the profile association through a user form (more here).
class User < ActiveRecord::Base
has_one :profile
accepts_nested_attributes_for :profile, allow_destroy: true
app/controllers/users_controller.rb
You'll need to build the user's associated profile instance (in the new
and edit
methods) for this to work correctly in the respective forms.
When editing a user it is possible that a profile association already exists. The edit
method will use the associated profile if it does exists (setting the form with its values) or create a new profile instance if not.
Notice also that the user_params
include profile_attributes: [:_destroy, :id]
which will be the values sent by the checkbox.
def new
@user = User.new
@user.build_profile
end
def create
@user = User.new(user_params)
if @user.save
redirect_to root_path
else
render :new
end
end
def edit
@user.profile || @user.build_profile
end
def update
if @user.update(user_params)
redirect_to @user
else
render :edit
end
end
private
def user_params
params.require(:user).permit(:name, profile_attributes: [:_destroy, :id])
end
app/views/users/new.html.rb and app/views/users/edit.html.rb
Use the fields_for
method in the form to submit data for the association (more on nested attributes, specifically one-to-one relationships, here).
Use the checkbox destroy
attribute to create/destroy the associated profile. The value of the checked
attribute within the curly braces sets the default state of the checkbox depending on whether or not the association exists (more under the 'More complicated relationships' header here). The '0'
and '1'
that follow invert the destroy
method (i.e. create the association if checkbox is checked and delete it if not) (more here).
<%= form_for @user do |user| %>
<%= user.fields_for :profile do |profile| %>
<div class='form-item'>
<%= profile.check_box :_destroy, { checked: profile.object.persisted? }, '0', '1' %>
<%= profile.label :_destroy, 'Profile', class: 'checkbox' %>
</div>
<% end %>
<%= user.submit 'Submit', class: 'button' %>
<% end %>
You can probably also delete the primary key id
from the profile model given it is unnecessary in this scenario and this link is very useful in that regard.