0

I'm creating a Rails application where users can sign up by checking a box in a form where they are either a "person" or "organization". I'm struggling to find a way to implement this into Rails. Both of these user types would have the same authorization. I have no idea if I want to use a string or a boolean as a data type in my ActiveRecord database. Also, what would I need to put in my model (User.rb) and my controller in order to validate it and implement it respectively?

3 Answers 3

2

There are many ways to implement this; it depends on what your needs are. Ask yourself: "Do people and organizations share the same attributes?"

AR Enum

If they do, the only thing that differentiates the two is role (or whatever you want to call it), i.e., person or organization. For that scenario, Rails 4.1 provides AR enums. This is the simplest solution, it could go something like this:

class User < ActiveRecord::Base
  enum role: [ :person, :organization ] # @user.role => 'person', @user.person? => true
end

Polymorphic Association

On the other hand, if people and organizations share only some attributes, you might consider using a polymorphic association (If people and organizations share no attributes—not even role—they should be two different models). The base model should contain the attributes that both people and organizations share. The person/organization models should contain attributes specific to that model.

# common attributes
class User < ActiveRecord::Base
  belongs_to :profile, polymorphic: true

  def self.roles
    %w(person organization)
  end
end

# person-specific attributes
class PersonProfile < ActiveRecord::Base
  has_one :user, as: :profile, dependent: :destroy
end

# organization-specific attributes
class OrganizationProfile < ActiveRecord::Base
  has_one :user, as: :profile, dependent: :destroy
end

For user signup, you can create users#new and users#create actions. In your user signup form (perhaps app/views/users/new.html.erb), you could use a select_tag to let the user specify their role. Then, use that to determine what kind of profile to attach to your user model. For example (users#create):

def create
  @user = User.new(user_params)
  if role = params[:role]
    # return HTTP 400
    head :bad_request and return unless User.roles.include?(role)

    # Assign the User's profile
    @user.profile = "#{role.capitalize}Profile".constantize.new
  else
    # enter your own logic here
  end

  @user.save ? redirect_to(@user) : render(:new)
end

The handling of sessions (user signin/signout), in my opinion, should be handled in a separate SessionsController.

Sign up to request clarification or add additional context in comments.

4 Comments

Okay thanks @jmera! I think I might implement the polymorphic associations. One major question I have is when a user signs up though, how would I let them choose to be either a "person" or "organization" in the sign up form under the view?
Hey @jtarr523, see my edits. If I were you, I'd use two different controllers. One for People, another for Organizations. It gets messy when you use the same controller for what sounds to me like two fundamentally different models.
You've got the polymorphic relationship wrong. PersonProfile and OrganizationProfile always belong to a User, so those relationships are not polymorphic. Also, I don't think you can use has_one in the way you're intending here -- there's no way for AR to know which table to look in to find the associated record.
You're right @ToddAgulnick. See my edit. I haven't tested it out, but I'm pretty sure it's right now.
0

Add a new table to the database named user_types with fields role and id. And in users table you need to add user_type_id column. Then, in UserType model

class UserType < ActiveRecord::Base
  has_many :users
end

And in User model you need to add

class User < ActiveRecord::Base
  belongs_to :user_type
end

You can create UserType records in seeds, but make sure it runs everytime the database is reset, add this to seeds.rb

UserType.create!(role: "person")
UserType.create!(role: "organization")

Hope this makes sense!

Comments

0

If you have only two types of users (Person and Organization) as indicated in your question, you could just have a Person model, and add a bool field is_organization to it. For more details, See how devise, a popular authentication gem, handles this here (this approach is option 2 on the linked page, you can also check out option 1, which is to create an entire new model).

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.