Reputation: 7938
Here's my functioning code to register a type of user called mentor via a Rails 4 JSON API.
Now I'm wondering, is there a better way to go about this? A more cleaner/simpler approach where Rails can automagically create the user/mentor association.
Currently I'm setting it manually in the create
method which doesn't seem right. So I just want to make sure there is no better way out there of going about this.
models/user.rb
class User < ActiveRecord::Base
# Include default devise modules. Others available are:
# :confirmable, :lockable, :timeoutable and :omniauthable
devise :database_authenticatable, :registerable,
:recoverable, :rememberable, :trackable, :validatable
belongs_to :role, :polymorphic => true
end
models/mentor.rb
class Mentor < ActiveRecord::Base
has_one :user, as: :role
accepts_nested_attributes_for :user
end
controllers/api/V1/mentors_controller.rb
class Api::V1::MentorsController < ApplicationController
respond_to :json
def create
@user = User.new(user_params)
@mentor = Mentor.new(mentor_params)
@user.role = @mentor
@user.save!
@mentor.user_id = @user.id
@mentor.save!
respond_with :api, @mentor
end
private
def mentor_params
params.require(:mentor).permit(:first_name, :last_name)
end
def user_params
params.require(:user).permit(:email, :password)
end
end
UPDATE - 10/01/2013
I make some more inroads with this. Here's what I have now:
controllers/api/V1/mentors_controller.rb
class Api::V1::MentorsController < ApplicationController
respond_to :json
def create
@mentor = Mentor.new(mentor_params)
@mentor.user.save!
@mentor.user_id = @mentor.user.id
@mentor.save!
respond_with :api, @mentor
end
private
def mentor_params
params.require(:mentor).permit(:first_name, :last_name, user_attributes: [:email, :password])
end
end
But I still have to set the user_id manually. Only doing Mentor.create(mentor_params)
fails to set the user_id. Any way to get around that?
Upvotes: 0
Views: 692
Reputation: 11
To answer the question on your update, try adding the id to your params whitelist:
def mentor_params
params.require(:mentor).permit(:first_name, :last_name,user_attributes: [:id, :email, :password])
end
Upvotes: 1
Reputation: 5563
This is off the top of my head but the basic idea goes something like this.
Create a form with a nested resource
form_for @mentor do |f|
f.input :mentor_val
f.fields_for :user do |m|
m.input :user_val
It should post a params object with a format something like this:
mentor: {
mentor_val: 'blah'
user_attributes: {
user_val: 'foo'
}
}
Now since you have included accepts_nested_attributes_for
in your Mentor model, Rails automatically added a user_attributes=
method to Mentor
which will build the user model, including setting the relationship. This means that to create both models, all you need to do in the controller is call
@mentor.create(params)
Upvotes: 1