Ruby on Rails 3: has_one association testing - ruby-on-rails-3

I may have my associations messed up. I have the following models: User and UserProfiles.
My models:
class User < ActiveRecord::Base
has_one :user_profile, :dependent => :destroy
attr_accessible :email
end
class UserProfile < ActiveRecord::Base
belongs_to :user
end
I have a column named "user_id" in my user_profiles table.
My factory is setup like so:
Factory.define :user do |user|
user.email "test#test.com"
end
Factory.sequence :email do |n|
"person-#{n}#example.com"
end
Factory.define :user_profile do |user_profile|
user_profile.address_line_1 "123 Test St"
user_profile.city "Atlanta"
user_profile.state "GA"
user_profile.zip_code "30309"
user_profile.association :user
end
My user_spec test is setup like so:
describe "profile" do
before(:each) do
#user = User.create(#attr)
#profile = Factory(:user_profile, :user => #user, :created_at => 1.day.ago)
end
it "should have a user profile attribute" do
#user.should respond_to(:user_profile)
end
it "should have the right user profile" do
#user.user_profile.should == #profile
end
it "should destroy associated profile" do
#user.destroy
[#profile].each do |user_profile|
lambda do
UserProfile.find(user_profile)
end.should raise_error(ActiveRecord::RecordNotFound)
end
end
end
My user_profile_spec is setup like so:
describe UserProfile do
before(:each) do
#user = Factory(:user)
#attr = { :state => "GA" }
end
it "should create a new instance with valid attributes" do
#user.user_profiles.create!(#attr)
end
describe "user associations" do
before(:each) do
#user_profile = #user.user_profiles.create(#attr)
end
it "should have a user attribute" do
#user_profile.should respond_to(:user)
end
it "should have the right associated user" do
#user_profile.user_id.should == #user.id
#user_profile.user.should == #user
end
end
end
When I run the tests I get "undefined method `user_profiles' for #". How is my test flawed or is my relationship flawed?
Thanks!

You have a has_one association called user_profile (singular). You do not have an association called user_profiles (plural).

Related

FactoryGirl belongs_to with Seeded association

I have a UserType object that ideally is seeded in the DB and remains static:
{id: 1, name: 'Individual'}, {id: 2, name: 'Group'}, {id: 3, name: 'Admin'}
class UserType < ActiveRecord::Base
attr_accessible :name
has_many :users
end
class User < ActiveRecord::Base
attr_accessible :email, :first_name
belongs_to :user_type
end
In testing, I simply want to create an admin user that has its user_type_id field set to 3 when created, and for the UserType.all to have those three items. I've tried a number of things, but here's where I'm at:
FactoryGirl.define do
factory :user_type do
id 1
name "Individual"
trait :group do
after(:create) do |user_type|
id 2
name "Group Leader"
end
end
trait :admin do
after(:create) do |user_type|
id 3
name "Administrative"
end
end
end
end
FactoryGirl.define do
factory :user do
first_name 'TestUser'
email { Faker::Internet.email }
user_type
trait :admin do
after(:create) do |user|
admin_user_type = UserType.where(id: 3).first
admin_user_type = create(:user_type, :admin) unless admin_user_type
user_type admin_user_type
end
end
end
And my test in spec/features/sessions/admin_sign_in_spec.rb:
feature "Admin signing in" do
background do
#institution = create(:institution_with_institutiondomains)
#admin = create(:user, :admin, email: "admin##{#institution.subdomain}.com")
end
scenario "with correct credentials", focus: true do
binding.pry
#admin.inspect
page.visit get_host_using_subdomain(#institution.subdomain)
within("#login-box") { fill_in t('email'), with: #admin.email }
click_button t('session.admin.sign_in') #the action in signing in here checks that user.user_type_id == 3
expect(page).to have_content "You're signed in!"
end
end
In many cases, especially in tests where I have multiple users getting created, I'll receive a MySQL duplicate error on the first id: 1 Individual. I appreciate any guidance.
For what it's worth, anyone finding this may not like my answer, but it is the only thing that works for me. UserTypes are static in my test database, so I removed the traits in the :user_type factory. Instead, I simply set the user_type_id directly and call save on it. Without the save, the change does not persist to my #admin variable. The test data is cleaned between tests using DatabaseCleaner, leaving my user_types table alone.
FactoryGirl.define do
factory :user do
first_name 'TestUser'
email { Faker::Internet.email }
user_type
trait :admin do
after(:create) do |user|
# admin_user_type = UserType.where(id: 3).first
# admin_user_type = create(:user_type, :admin) unless admin_user_type
# user_type admin_user_type
user.user_type_id = 3
user.save #without this, the change won't persist
end
end
end
end

Rspec controller error: No route matches {:controller=>"bookings", :action=>"/dashboard/index"}

I'm getting an error when I try to test mi controller, I'm new with rspec test and maybe there are something that I dont undertand.
$rspec spec/controllers/booking_controller_spec.rb
I get the following error:
No route matches {:controller=>"bookings", :action=>"/dashboard/index"}
and I don't understand why? so if can any help me, I really appreciate some help.
File Structure:
app/models/booking.rb
app/models/user.rb
app/models/role.rb
app/models/ability.rb
app/controllers/bookings_controller.rb
app/views/bookings/index.html.erb
app/views/dashboard/index.html.erb
app/spec/controllers/bookings_controller_spec.rb
My fail Spec:
describe BookingsController do
context 'as guest' do
before(:each) do
#user = User.new(:email => 'mail_admin#test.com',
:username => 'admin',
:password => 'password_admin',
:password_confirmation => 'password_admin')
#user.save
#when i save, with gem CanCan i assign a default role to #user
#with the default role the user only can see the views/dashboard/index.html.erb
end
it 'should not render index template from bookings' do
get :index
response.should_not render_template(:index)
end
it 'should render index template from dashboard' do
get '/dashboard/index'
response.should render_template('index')
end
end
end
Controller:
class BookingsController < ApplicationController
load_and_authorize_resource
def index
...
end
def show
...
end
end
My model:
class Booking < Activerecord::Base
paginates_per 20
def
...
end
def
...
end
end
User:
Class User < ActiveRecord::Base
after_save :set_default_role
rolify
.
.
.
.
def set_default_role
self.add_role :default
end
end
Role:
class Role < ActiveRecord::Base
ROLES = {"admin" => "Admin", "default" => "Default"}
.
.
.
.
scopify
end
Ability:
class Ability
include CanCan::Ability
def initialize(user)
user ||= User.new
if user.has_role? :admin
can :manage, :all
elsif user.has_role? :data_consistency
can :read, Booking
end
end
end

Got error : can't be blank, Rails test

I would like to do testing my rails application, especially on controller, here are the code
customer_controller_test.rb
require 'test_helper'
class CustomersControllerTest < ActionController::TestCase
include Devise::TestHelpers
setup do
#user = FactoryGirl.create(:user)
#role = FactoryGirl.create(:role)
#puts #role.name
#permission = FactoryGirl.create(:permission)
#puts #permission.name
#role_permission = FactoryGirl.create(:role_permission)
#puts #role_permission.role_id
#puts #role_permission.permission_id
sign_in #user
#customer = FactoryGirl.create(:customer)
end
test "should get index" do
get :index
assert_response :success
assert_template 'index'
assert_not_nil assigns(:customers)
end
test "should show article" do
get :show, :id => #customer.to_param
assert_response :success
assert_template 'show'
assert_not_nil assigns(:customer)
assert assigns(:customer).valid?
end
test "should get new" do
#login_as(#user)
get :new
assert_response :success
end
end
factories.rb <-- setup tha fixtures with factorygirl
FactoryGirl.define do
sequence :email do |n| "admin#admin.admin#{n}" end
sequence :role_name do |n| n end
sequence :role_id do |n| n end
sequence :permission_id do |n| n end
factory :user do |u|
u.name "Admin"
u.role_id {1}
u.email do FactoryGirl.generate(:email) end
u.password "123456"
u.after(:create) do |user|
user.creator_id {1}
user.save
end
end
factory :customer do
name "Test customer-name"
code "Test customer-code"
address "Test customer-address"
phone "Test customer phone"
end
factory :permission do
name "Customer"
end
factory :role do
name do FactoryGirl.generate(:role_name) end
end
end
And I got error
Any idea? Thx before
Try creating the role in FactoryGirl before assigning it to the user. It looks like you've got a validation error when saving your User record, because it's trying to validate that you've got an actual role assigned. You don't, because you're attempting to create your role after your user.
Just try switching the two lines in your FactoryGirl "setup" like this:
#role = FactoryGirl.create(:role)
#user = FactoryGirl.create(:user)
Or, check out this link for a more thorough examination of how to use FactoryGirl to test associations:
http://blog.joshsoftware.com/2011/05/13/testing-associations-with-factory-girl/

Rails 3.2 - accepts_nested_attributes_for and join models

I have the following models: user, role, user_role (user_role is a join model)
I am trying to edit a user's roles using checkboxes on the user#edit page. Here's my attempt, I feel like I'm missing something significant, or taking the wrong approach.
user.rb
has_many :user_roles, dependent: :destroy
has_many :roles, through: :user_roles
attr_accessible :user_roles_attributes
accepts_nested_attributes_for :user_roles, reject_if: lambda { |a| a[:role_id] == 0 }, allow_destroy: true
def has_role?(role_sym)
roles.any? { |r| r.name.underscore.to_sym == role_sym.downcase }
end
def setup_roles!
Role.all.each { |role|
user_roles.build(user_id: id, role_id: role.id) unless has_role?(role.name.to_sym)
}
end
user_role.rb
belongs_to :user
belongs_to :role
delegate :name, to: :role
role.rb
has_many :user_roles
has_many :users, through: :user_role
users_controller.rb
def edit
#user = User.find(params[:id])
#user.setup_roles!
end
def update
#user = User.find(params[:id])
if #user.update_attributes(params[:user])
flash[:notice] = 'User was successfully updated.'
redirect_to edit_user_path(#user)
else
render :edit
end
end
users/edit.html.haml
= form_for #user do |f|
= f.fields_for(:user_roles) do |role_form|
= role_form.check_box :role_id, {}, role_form.object.role_id, 0
= role_form.hidden_field :user_id
= role_form.label :name, role_form.object.name
= f.submit 'Update'
Here is my solution. I received a lot of help from This Post at RubySource. The way the checkbox is setup, it will destroy a UserRole if "unchecked", and only create it when it is "checked" (why the '0', '1' is on that line.)
users_controller.rb
def edit
#user = User.find(params[:id])
#user.setup_roles!
end
user.rb
def has_role?(role_sym)
roles.any? { |r| r.name.underscore.to_sym == role_sym.downcase }
end
def setup_roles!
Role.all.each { |role|
user_roles.build(role: role) unless has_role?(role.name.to_sym)
}
end
users/edit.html.haml
= form_for #user do |f|
= f.fields_for :user_roles do |builder|
= builder.check_box :_destroy, { checked: builder.object.persisted? }, '0', '1'
= builder.label :_destroy, builder.object.role.name
= builder.hidden_field :role_id
= f.submit 'Update'

How to build Active Record with multiple associations?

I defined these 3 models in Rails3.
class User < ActiveRecord::Base
has_many :questions
has_many :answers
class Question < ActiveRecord::Base
belongs_to :user
has_many :answers
class Answer < ActiveRecord::Base
belongs_to :user
belongs_to :question
I wrote RSpec like this:
describe "user associations" do
before :each do
#answer = #user.answers.build question: #question
end
it "should have the right associated user" do
#answer.user.should_not be_nil
end
it "should have the right associated question" do
#question.should_not be_nil
#answer.question.should_not be_nil #FAIL!!
end
But I always get the following error:
Failures:
1) Answer user associations should have the right associated question
Failure/Error: #answer.question.should_not be_nil
expected: not nil
got: nil
I guess this line is wrong:
#answer = #user.answers.build question: #question
But how should I build answer object?
Update: Thanks everyone, I found I should have to write like this:
require 'spec_helper'
describe Answer do
before :each do
#user = Factory :user
asker = Factory :user, :user_name => 'someone'
#question = Factory :question, :user => asker
end
describe "user associations" do
before :each do
#answer = Factory :answer, :user => #user, :question => #question
end
it "should have the right associated user" do
#answer.user.should_not be_nil
end
it "should have the right associated question" do
#answer.question.should_not be_nil
end
end
end
Here is spec/factories.rb:
Factory.define :user do |user|
user.user_name "junichiito"
end
Factory.define :question do |question|
question.title "my question"
question.content "How old are you?"
question.association :user
end
Factory.define :answer do |answer|
answer.content "I am thirteen."
answer.association :user
answer.association :question
end
Once I explicitly save the #user instance, the spec doesn't fail anymore. Here's my version:
require 'spec_helper'
describe Answer do
before :each do
#user = User.new
#user.save!
#question = #user.questions.build
#question.save!
#answer = #user.answers.build question: #question
#question.answers << #answer
end
it "should have the right associated user" do
#answer.user.should_not be_nil
end
it "should have the right associated question" do
#question.should_not be_nil
#answer.question.should_not be_nil # SUCCESS!
end
end