Linking two records after creation in Rails
I am working on communication between two models:
class Person < ActiveRecord::Base
belongs_to :user
end
class User < ActiveRecord::Base
has_one :person
end
There are many records in the system person
that do not necessarily match user
, but when user
you create you need to either create a new record person
or link it to an existing one.
What would be the best way to link these two models when the record person
already exists? Do I need to manually assign the field, user_id
or is there a Rails way of doing this?
source to share
Where @user is the newly created user and @person is an existing person.
@user.person = @person @user.save
As an alternative:
User.new :person => @person, ... #other attributes
or in params form:
User.new(params[:user].merge({person => @person}))
As for go forms:
<% form_for @user do |f| %>
...
<% fields_for :person do |p| %>
<%= p.collection_select, :id, Person.all, :id, :name, :include_blank => "Use fields to create a person"%>
<%= p.label_for :name%>
<%= p.text_field :name %>
...
<% end %>
<% end %>
And in the custom controller:
def create
@user = User.create(params[:user])
@person = nil
if params[:person][:id]
@person = Person.find(params[:person][:id])
else
@person = Person.create(params[:person])
end
@user.person = @person
...
end
source to share
First you need to make a nested form:
<% form_for @user do |user| %>
<%= user.text_field :name %>
<% user.fields_for user.person do |person| %>
<%= person.text_field :name %>
<% end %>
<%= submit_tag %>
<% end %>
In your user model:
class User < ActiveRecord::Base
accepts_nested_attributes_for :person
end
If you want the person to be deleted when the user:
class User < ActiveRecord::Base
accepts_nested_attributes_for :person, :allow_destroy => true
end
And in your controller, do nothing:
class UserController < ApplicationController
def new
@user = User.new
#find the person you need
@user.person = Person.find(:first)
end
def create
@user = User.new(params[:user])
@user.save ? redirect_to(user_path(@user)) : render(:action => :new)
end
end
source to share