0
votes

I'm new to Rails and building a jobboard marketplace.I'm stuck with a user signup profile form. I'm using devise(4.2) with Rails 5. I've created profile before user_create and then just redirect to profile view and now update users with registration form fields like first_name & last_name.

My signup is a 2-way process and not nested profile. step 1 - devise sign-up form with just an extra field to check role of user as user(jobseeker)or company. Step 2 - Based on this role, create separate profile forms for users and company. If profile is not committed to DB, then user also should not be saved and again user sign_up must happen.

At present, I'm trying with just one generic user form which has fields first_name and last_name. I used before_create :build_profile in user model but it just passes the Profile.create without creating it on DB. Should I overwrite 'create'or 'new' in profiles_controller or registrations_controller(devise).

The error in views/profiles/show.html.erb is: First argument in form cannot contain nil or be empty. Also on the terminal I see this for profiles: "user_id"=>"2", "id"=>"profile_id"}...does this signify something between user and profile tables in DB that is hampering the create or the routes correctly set?

routes.rb

Rails.application.routes.draw do
   root "jobs#index"
  devise_for :users, :controllers => {registrations: "registrations"}
  resources :users do

    resources :profiles, only: [:show, :update]
  end
end

Registrations_controller

class RegistrationsController < Devise::RegistrationsController
    protected
    def after_sign_up_path_for(user)
      if resource.class == User && current_user.role == 'user'
        user_profile_path
      else # to check for company user resource.class == User && current_user.role == 'company'
        puts "redirecting to company profile-will do later"
      end
    end
  end

profiles_controller.rb

      class ProfilesController < ApplicationController

      def show
      end

      def update
        @profile = Profile.find_by_user_id(profile_params)
        current_user.update(@profile)
      end

      def destroy
        @profile.destroy
        respond_with(@profile)
      end

      private

      def profile_params
        params.require(:user).permit(profile_attributes: [])
      end

      def set_profile
        @profile = Profile.find(params[:id])
      end
    end

profile.rb

class Profile < ApplicationRecord
  belongs_to :user
end

user.rb

   class User < ApplicationRecord
      before_create :build_profile
      devise :database_authenticatable, :registerable, :recoverable, :rememberable, :trackable, :validatable
     enum role: [:user, :company, :admin]
      has_one :profile

      def build_profile
        Profile.create
        true
      end
1

1 Answers

0
votes

I suggest you use an approach based on inheritance.

You can add a type in users table and Rails will manage it for you.

example_timestamp_add_type_to_users.rb

class AddTypeToUsers < ActiveRecord::Migration[5.0]
  def change
    add_column :users, :type, :string, null: false
  end
end

Using this you can add as user types as you want:

models/job_seeker.rb

class JobSeeker < User
  has_one :job_seeker_profile, dependent: :destroy
  after_create :profile

  private

  def profile
    create_job_seeker_profile
  end
end

models/company_owner.rb

class CompanyOwner < User
  has_one :company_owner_profile, dependent: :destroy
  after_create :profile

  private

  def profile
    create_company_owner_profile
  end
end

models/admin.rb

class Admin < User
end

This approach will allows you to use the authentication methods based on user type:

for job seekers:

  1. current_job_seeker
  2. authenticate_job_seeker!

for company owners:

  1. current_company_owner
  2. authenticate_company_owner!

for admins:

  1. current_admin
  2. authenticate_admin!

You can also build a different registration and/or sign-in forms for each user type:

config/routes.rb

Rails.application.routes.draw do
  devise_for :admins
  devise_for :job_seekers
  devise_for :company_owners
end