As an exercise, I am working on app for finding people to play RockBand with.
Users sign up as “Drummers”, “Guitarists” or “Singers”. Since the data is the same for all types, I decided to go with STI. These are my models:
class User < ActiveRecord::Base
attr_accessible(
:email,
:name,
:password,
:password_confirmation,
:type
)
has_secure_password
end
class Drummer < User
end
class GuitarPlayer < User
end
class Singer < User
end
My goal with this app is trying to apply design patterns, so I tried to create a UserFactory object.
It is called from the Users controller:
class UsersController < ApplicationController
def new
@user = User.new
end
def create
user = UserFactory.create_with_type(params[:user])
session[:current_user] = user
redirect_to dashboard_path
end
end
and it looks like this:
class UserFactory
def self.create_with_type(params)
type = params.fetch(:type)
type.constantize.create(params)
end
end
My question is should I use a class method like I did or should I be instantiating a new UserFactory from the controller?
Thank you, also I’m not really sure how to test this.
I have the following feature test (from which the Factory + STI structure originates):
feature 'A visitor can signup' do
scenario 'as a Drummer' do
sign_up_as 'Drummer'
user_should_see_greeting 'Welcome, example_drummer'
expect(page).to have_css '[data-user-type="Drummer"]'
end
# other user types ommited here for brevity
def sign_up_as(user_type)
visit sign_up_path
fill_in 'Name', with: user_type.capitalize
fill_in 'Email',
with: "#{user_type.gsub(' ', '_').downcase}@example.com"
fill_in 'PSN username',
with: "example_#{user_type.gsub(' ', '_').downcase}"
choose("user_type_#{user_type.gsub(' ', '').downcase}")
click_button 'Sign up'
end
def user_should_see_greeting(greeting)
expect(page).to have_css '.greeting', text: greeting
end
end
And the following unit test:
describe UserFactory, '.create_with_type' do
it 'creates a user of the type passed in' do
params = attributes_for(:user, type: "Singer")
user = UserFactory.create_with_type(params)
expect(user.type).to eq "Singer"
end
end
I’m not so sure about this unit test, any suggestions?