0

I have a player model inheriting from a user model to share authentication logic (devise) with a 3rd model (coach that also inherits from user).

class User < ActiveRecord::Base
end
class Player < User
end
class Coach < User
end

I'm trying to add a field to the player table when players register so I created a migration

rails g migration AddClubCoachEmailToPlayer club_coach_email:string

then ran the migration

rake db:migrate

for the file

class AddClubCoachEmailToPlayer < ActiveRecord::Migration
  def change
    add_column :players, :club_coach_email, :string
  end
end

Schema as expected

  create_table "players", force: true do |t|
    t.datetime "created_at"
    t.datetime "updated_at"
    t.string   "club_coach_email"
  end

Now, I need to add the field to /views/players/registrations/new

<%= form_for(resource, :as => resource_name, :url => registration_path(resource_name)) do |f| %>
  <%= devise_error_messages! %>
  #...

  <div><%= f.label :position %><br />
    <%= f.radio_button(:position, "Striker") %> Striker
    <%= f.radio_button(:position, "Midfielder") %> Midefielder
    <%= f.radio_button(:position, "Defender") %> Defender
  </div>
  <div><%= f.label :club_coach_email %><br />
  <%= f.email_field :club_coach_email %></div>

  <div><%= f.label :profile_name %><br />
  <%= f.text_field :profile_name %></div>

 #...

and I sanitize params through this technique from devise wiki; in lib/player_sanitizer.rb I add the new field.

class PlayerParameterSanitizer < Devise::ParameterSanitizer
  private
  def sign_up
    default_params.permit(:first_name, :last_name, :profile_name, :password, :password_confirmation, :email, :grad_year, :position, :club_team, :formation, :club_coach_email)
  end
  def account_update
    default_params.permit(:first_name, :last_name, :profile_name, :password, :password_confirmation, :email, :grad_year, :position, :club_team, :formation)
  end
end

This is what my application controller looks like

class ApplicationController < ActionController::Base
  def after_sign_in_path_for(user)
    dashboard_path
  end

  protected
  def devise_parameter_sanitizer
    if resource_class == Player
      PlayerParameterSanitizer.new(Player, :player, params)
    elsif resource_class == Coach
      CoachParameterSanitizer.new(Coach, :coach, params)
    else
      super
    end    
  end 
end

However, I must be missing some step because when I navigate to /players/sign_up I'm getting a NoMethodError in Players::Registrations#new

undefined method `club_coach_email' for #<Player:0x00000109296be8>

Obvioulsy, here is where the trace is pointing

<%= f.radio_button(:position, "Defender") %> Defender
 </div>
 <div><%= f.label :club_coach_email %><br />
 <%= f.email_field :club_coach_email %></div>

 <div><%= f.label :profile_name %><br />
 <%= f.text_field :profile_name %></div>

What do I seem to not understand here?

computer_smile
  • 2,117
  • 2
  • 24
  • 42

1 Answers1

0

As for me you're doing it too complex. From the information you gave there is no different functionality between this three different users types, therefore it will be easier to make all of them not through inheritance but with the devise roles.

In this way you'll have One user model with three different roles (User, Player, Coach).

Or there is other way - using different models in "devise way": rails g devise User + rails g devise Player + rails g devise Coach

After this you'll get three almost separate models each with all devise functionality and methods (for example: player_signed_in?, current_coach, authenticate_player! etc.).

RedZagogulin
  • 441
  • 3
  • 11