How to updated nested attribute value in factory girl - ruby-on-rails-3

we have one factory in which we are developing nested relation
FactoryGirl.define do
factory : user do
name "Arvind"
association :campaign
factory :user_with_photos do
after(:build) do |user|
user.photos.build name: 'user 1',
user.photos.build name: 'user 2', position: 2
end
end
factory :user_with_mandatory_photos do
after(:build) do |user|
user.photos.build name: 'user 3', mandatory: true
user.photos.build name: 'user 4', mandatory: true
end
end
factory :user_with_mandatory_photos do
after(:build) do |user|
user.photos.build name: 'user 5', mandatory: false
user.photos.build name: 'user 6', mandatory: false
end
end
end
end
we are creating attribute like
users = FactoryGirl.create(:user_without_mandatory_fields, campaign: #campaign)
users = FactoryGirl.create(:user_with_mandatory_fields, campaign: #campaign)
we are looking to reduce this and use only
factory : user do
name "Arvind"
association :campaign
factory :user_with_photos do
after(:build) do |user|
user.photos.build name: 'user 1',
user.photos.build name: 'user 2', position: 2
end
end
end
But we are not getting how to create user photo with the mandatory field in this scenario. Can anyone please suggest?
Looking something like users = FactoryGirl.create(:user_with_photos,[update user photo attribute make mandatory true ] campaign: #campaign)

Fixed this problem with creating the new object of photos
photos = FactoryGirl.create_list(:photo, 12, mandatory: true)
users = FactoryGirl.create(:use, :photos, campaign: #campaign)

Related

Ruby on Rails 4: has_secure_password is not asking for a password confirmation when creating new user

I am currently writing an app using RoR4 and am having trouble with authentication. Even though I've added has_secure_password to the User model, I still seem to be able to create a new user without having to provide a password confirmation.
2.1.2 :012 > me = User.create(:institution_id => 1, :email => "me#myschool.edu", :password => "mypassword")
(0.1ms) BEGIN
User Exists (0.3ms) SELECT 1 AS one FROM `users` WHERE `users`.`email` = BINARY 'me#myschool.edu' LIMIT 1
SQL (0.2ms) INSERT INTO `users` (`created_at`, `email`, `institution_id`, `password_digest`, `updated_at`) VALUES ('2014-07-14 20:02:34', 'me#myschool.edu', 1, '$2a$10$sD2N.2nxhYO7egzzWxfF5.cdIZ4ds41.sU93Ja3E9Q0qAOaABdZb6', '2014-07-14 20:02:34')
(8.2ms) COMMIT
=> #<User id: 5, institution_id: 1, first_name: nil, last_name: nil, email: "me#myschool.edu", blurb: nil, facebook_link: nil, facebook_token: nil, password_digest: "$2a$10$sD2N.2nxhYO7egzzWxfF5.cdIZ4ds41.sU93Ja3E9Q0...", api_key: nil, active: false, created_at: "2014-07-14 20:02:34", updated_at: "2014-07-14 20:02:34", authentication_token: nil>
Why is this happening? Shouldn't has_secure_password always require a password confirmation as well??
Thanks for the help
Make sure you followed these things:
add gem 'bcrypt' to gem file.
Next:
have a password_digest attribute
Next:
class User < ActiveRecord::Base
has_secure_password
end
Then you can test it:
user = User.new(name: 'david', password: '', password_confirmation: 'nomatch')
user.save # => false, password required
user.password = 'mUc3m00RsqyRe'
user.save # => false, confirmation doesn't match
user.password_confirmation = 'mUc3m00RsqyRe'
user.save # => true
user.authenticate('notright') # => false
user.authenticate('mUc3m00RsqyRe') # => user
User.find_by(name: 'david').try(:authenticate, 'notright') # => false
User.find_by(name: 'david').try(:authenticate, 'mUc3m00RsqyRe') # => user

Issue in acceptance test while redirecting to another page

I am writing an acceptance test to check on clicking a button it gets redirected to another page(carts page), but I am getting an error while trying to do the same.
my code is:-
gift_cards_controller.rb
class GiftCardsController < ApplicationController
before_filter :get_order_and_shipment, only: [:create]
def create
super do |format|
if resource.errors.messages.any?
format.html { render :new }
else
format.html { redirect_to carts_path }
end
end
end
end
acceptance spec :-
gift_card_spec.rb
require 'spec_helper'
include Warden::Test::Helpers
Warden.test_mode!
describe 'Gift Card', type: :feature do
before(:all) do
Address.delete_all
end
it 'redirects to cart page' do
user = create(:user)
login_as(user, scope: :user)
address = create(:address, name: 'ABC',
street: 'PQR',
postal_code: '12345',
state_or_region: 'XYZ',
phone_number: '123-456-7890',
city: 'LMN',
user: user)
add_str = 'ABC, PQR, LMN, XYZ, 12345'
visit new_gift_card_path
page.should_not have_content('Please add address before creating a gift card')
page.should have_button('create gift card')
fill_in 'gift_card_name', with: 'Gift Card'
fill_in 'gift_card_value', with: 1000.99
fill_in 'gift_card_message', with: "This is A Gift Card"
option = first('#gift_card_address_list option').text
expect(option).to eq(add_str)
click_button 'create gift card'
expect(page.current_url).to eq(carts_url)
page.should have_content('ORDER SUMMARY')
end
end
error:-
Gift Card
redirects to cart page (FAILED - 1)
Failures:
1) Gift Card redirects to cart page
Failure/Error: expect(page.current_url).to eq(carts_url)
expected: "http://www.example.com/cart"
got: "http://www.example.com/gift_cards/new?gift_card[code]=75C4FC&gift_card[name]=Gift+Card&gift_card[value]=1000.99&gift_card[message]=This+is+A+Gift+Card&commit=create+gift+card"
[Edit]
On execution of click_button 'create gift card' line in the rspec, the control does not enter the create method in the controller. Because of which I am unable to check resourse.errors.messages.any?
view/gift_cards/new.html.haml
#giftcard
.giftCard
%h1
Create A Gift Card
= simple_form_for :gift_card, url: gift_cards_path, method: :post do |f|
%form
%fieldset
.form-inputs
= f.input :code,input_html: {value: GiftCard.generate_code}, required: true
= f.input :name, label: 'Gift Card Name/Caption', required: false
= f.input :value, label: 'Amount'
= f.input :address_list, collection: current_user.addresses,
label_method: :get_address_string, include_blank: false
= f.input :message, as: :text, required: false
= f.button :submit, 'create gift card',
class: 'gift_card_submit', disable_with: "creating your gift card..."
routes.rb
resources :gift_cards
gift_cards_path GET /gift_cards(.:format) gift_cards#index
POST /gift_cards(.:format) gift_cards#create
new_gift_card_path GET /gift_cards/new(.:format) gift_cards#new
edit_gift_card_path GET /gift_cards/:id/edit(.:format) gift_cards#edit
gift_card_path GET /gift_cards/:id(.:format) gift_cards#show
PUT /gift_cards/:id(.:format) gift_cards#update
DELETE /gift_cards/:id(.:format) gift_cards#destroy
Seems your form is incorrect.
= simple_form_for :gift_card, url: gift_cards_path, method: :post do |f|
%form
%fieldset
.form-inputs
remove the %form element
Use REST convention simple_form_for #gift_card do |f|
Based on the controller code you shared, it appears that either it's failing your before_filter or resource.errors.messages.any? was truthy and you rendered the new view rather than redirecting to carts_path. Without any other code, there's not much else to tell.

How can I debug seeds.rb file?

I am trying to insert some default users in my project using seed.rb file. I have executed the following line in the console:
rake db:seed
and no errors were thrown, but the records were not created either. When I paste the code in the rails console, again no errors are shown. I am guessing that I am doing something wrong in the seed.rb file.
This is how my models are related:
security_user.rb
has_one :security_users_detail, dependent: :destroy
has_many :security_users_manage_securities
has_many :security_users_roles, through: :security_users_manage_securities
security_users_detail.rb
belongs_to :security_user
security_users_role.rb
has_many :security_users_manage_securities
has_many :security_users, through: :security_users_manage_securities
And this is the code that I have in my seed.rb file:
users = {
Admin: {
Information: {
email: 'test#gmail.com',
password: 'test',
password_confirmation: 'test'
},
Details: {
address: 'Not defined.',
city: 'Not defined.',
country: 'Not defined.',
egn: '0000000000',
faculty_number: '',
first_name: 'Admin',
gender: 'male',
gsm: '0000000000',
last_name: 'Not defined.',
skype: 'Not defined.'
},
Roles: %w(Administrator)
}
}
users.each do |user, data|
security_user = SecurityUser.new(data[:Information])
data[:Roles].each { |role|
security_user.security_users_manage_securities.build(security_users_role: SecurityUsersRole.find_by_role(role))
}
SecurityUser.where(email: security_user.email).first_or_create!(security_user.attributes)
security_users_detail = SecurityUsersDetail.new(data[:Details])
security_users_detail.security_user_id = security_user.id
SecurityUsersDetail.where(security_user_id: security_users_detail.security_user_id).first_or_create
end
seed.rb is a rake task, so you can use puts to output messages to the console. For instance,
puts "User name: #{user.name}"
The issue was caused by the following line:
security_user = SecurityUser.new(data[:Information])
because even thought the hash passed in the new method holds only email and password fields, the result object was created with the rest of the model attributes but set to nil. For, example, I have id=>nil.
Then in I was doing the following
SecurityUser.where(email: security_user.email).first_or_create!(security_user.attributes)
in order to created the user only if exists. Anyway, since the id parameter is not in the attr_accessible clause in the model, I was not able to make mass assign.
To delete the nil values of the hash I've done the following:
SecurityUser.where(email: security_user.email)
.first_or_create!(security_user.attributes
.delete_if { |key, value| value.nil? })

While testing Devise with rspec, it acts like I am not logged in

I'm using Rails 3.2.13, devise 2.2.4, and rspec 2.13.2. I have a multi-tenant app in which the default scope only shows current_user's items. Everything seems to work in development, but my tests are having issues.
Problem: When I create a meal in my test, it shows user_id => nil. In my development environment everything works, though. Also, when I go into debug mode, when I check the #controller.current_user, it shows user_id 1 is logged in. Since in my development environment the user_id is being assigned automatically when I create an object, I can't figure out why it's not doing it during tests. Any ideas?
Here's my abbreviated meals_controller_spec file:
describe MealsController do
include Devise::TestHelpers
describe "When logged in as user," do
before(:each) do
#request.env["devise.mapping"] = Devise.mappings[:user]
#email = "someone#test.com"
#password = "password"
#user = User.create(email: #email, password: #password)
sign_in #user
end
describe "DELETE destroy" do
it "destroys the requested meal" do
meal = Meal.create!("name" => "", "servings" => "2", "meal_type" => "dinner")
expect { delete 'destroy', {:id => meal.id} }.to change(Meal, :count).by(-1)
end
end
end
end
Here's part of my model:
class Meal < ActiveRecord::Base
belongs_to :user
default_scope { where(user_id: User.current_id) }
Here's part of my controller:
class MealsController < ApplicationController
before_filter :authenticate_user!
def destroy
#meal = Meal.find(params[:id])
#meal.destroy
redirect_to meals_url, :notice => "Successfully deleted #{#meal.name}."
end
end
And I think my application controller could be relevant:
class ApplicationController < ActionController::Base
protect_from_forgery
around_filter :scope_current_tenant
private
def scope_current_tenant
User.current_id = current_user.id
yield
rescue Exception
yield
ensure
User.current_id = nil
end
end
Here's some output when I debug in the middle of that test:
(rdb:1) #controller.current_user.id
1
(rdb:1) Meal.create!(name: "meal", meal_type: "dinner", servings: 2)
#<Meal id: 2, name: "meal", meal_type: "dinner", servings: 2, user_id: nil, created_at: "2013-06-17 06:07:34", updated_at: "2013-06-17 06:07:34">
(rdb:1) Meal.create!(name: "meal", meal_type: "dinner", servings: 2, user_id: 1)
#<Meal id: 3, name: "meal", meal_type: "dinner", servings: 2, user_id: 1, created_at: "2013-06-17 06:12:18", updated_at: "2013-06-17 06:12:18">
(rdb:1) Meal.find(3).destroy
*** NoMethodError Exception: undefined method `destroy' for nil:NilClass
So I guess I'm wondering why the user in my test appears to be nil, even though I am using the Devise test helpers and signing in, and in my dev environment everything works.
Edit:
Here are some more debugger results:
(rdb:1) Meal.find(4)
*** ActiveRecord::RecordNotFound Exception: Couldn't find Meal with id=4 [WHERE "meals"."user_id" IS NULL]
(rdb:1) Meal.find(4).destroy
*** ActiveRecord::RecordNotFound Exception: Couldn't find Meal with id=4 [WHERE "meals"."user_id" IS NULL]
(rdb:1) Meal.where(:user_id => 1).find(3)
#<Meal id: 3, name: "meal", meal_type: "dinner", servings: 2, user_id: 1, created_at: "2013-06-17 06:12:18", updated_at: "2013-06-17 06:12:18">
It appears that the "current user" is in fact user_id => nil, per the sql snippets. So why would that be if I used the Devise test helper sign_in function?

How to update nested data in Rails

I have some users who take quizzes. I track the result they chose. I need to figure out how to allow them to change their quiz submission. If I just associate the answer, they'll have answered the question twice. Building up the data is complex, does ActiveRecord provide a way to deal with this?
This whole example will run in a standalone file.
Here is my schema:
require 'active_record'
ActiveRecord::Base.establish_connection adapter: 'sqlite3', database: ':memory:'
ActiveRecord::Schema.define do
self.verbose = false
create_table :users do |t|
t.string :name
end
create_table :questions do |t|
t.string :name
end
create_table :question_results do |t|
t.string :name
t.integer :question_id
end
create_table :question_results_users do |t|
t.integer :user_id
t.integer :question_result_id
end
end
here are my models:
class User < ActiveRecord::Base
has_and_belongs_to_many :question_results
has_many :questions, through: :question_results
end
class Question < ActiveRecord::Base
has_many :question_results
end
class QuestionResult < ActiveRecord::Base
belongs_to :question
has_and_belongs_to_many :users
end
Lets make three questions and some answers:
Question.create! name: "What's your favourite movie?" do |question|
question.question_results.build name: 'Gattaca'
question.question_results.build name: 'Super Troopers'
end
Question.create! name: 'Who do you want to be president?' do |question|
question.question_results.build name: 'Barack Obama'
question.question_results.build name: 'Mitt Romney'
question.question_results.build name: 'Mickey Mouse'
end
Question.create! name: "What's your favourite colour?" do |question|
question.question_results.build name: 'black'
question.question_results.build name: 'green'
end
Lets make a user:
jim = User.create! name: 'Jim'
jim.question_results << QuestionResult.find_by_name('Gattaca')
jim.question_results << QuestionResult.find_by_name('Barack Obama')
jim.question_results << QuestionResult.find_by_name('black')
jim.question_results # => [#<QuestionResult id: 1, name: "Gattaca", question_id: 1>, #<QuestionResult id: 3, name: "Barack Obama", question_id: 2>, #<QuestionResult id: 6, name: "black", question_id: 3>]
jim.question_results.map(&:question) # => [#<Question id: 1, name: "What's your favourite movie?">, #<Question id: 2, name: "Who do you want to be president?">, #<Question id: 3, name: "What's your favourite colour?">]
Now Jim changes his mind, he decides he likes Super Troopers and doesn't want to vote, but he still likes black. How do I update this without having him answer the question multiple times?
# pretend we're in a controller here (also note that I can change the format of the data, if there is something more convenient)
posted_from_form = {
questions: {
Question.all[0].id => 'Super Troopers',
Question.all[1].id => '',
Question.all[2].id => 'black',
}
}
First lets change the format of our data so that the results are in id form instead of name form:
posted_from_form = {
questions: {
Question.all[0].id => QuestionResult.find_by_name('Super Troopers').id.to_s,
Question.all[1].id => '',
Question.all[2].id => QuestionResult.find_by_name('black').id,
}
}
Then you can set the ids directly, and ActiveRecord will handle all of the complexity:
jim.question_result_ids = posted_from_form[:questions].values # => ["2", "", 6]
jim.question_results # => [#<QuestionResult id: 6, name: "black", question_id: 3>, #<QuestionResult id: 2, name: "Super Troopers", question_id: 1>]