I am new to rails. Newer to FactoryGirl.
I have a model like this.
class Manifest < ActiveRecord::Base
serialize :scopes, Array
:app_description
:app_name
:app_id
:app_verson
:dev_id
:callback
:manifest_ver
:signed_jwt
:scopes
validates :app_name, presence: true
validates :callback, presence: true
I have a factory like this.
factory(:manifest) do
callback "some callback"
app_name "cool birds"
end
The spec regarding above model is like this.
describe Manifest do
describe "validation" do
describe "of object from fractory" do
it "must be ok" do
FactoryGirl.build(:manifest).should be_valid
end
end
end
end
So I expected this test to pass. But it fails giving this output.
1) Manifest validation of object from fractory must be ok
Failure/Error: FactoryGirl.build(:manifest).should be_valid
expected #<Manifest id: nil, dev_id: nil, app_id: nil, app_description: nil, app_name: "cool birds", app_version: nil, manifest_ver: nil, callback: nil, signed_jwt: nil, scopes: [], created_at: nil, updated_at: nil> to be valid, but got errors: Callback can't be blank
It says Callback can't be blank.
It seems FactoryGirl ignores the value for attribute "callback".
when the spec changed to FactoryGirl.build(:manifest, callback: "some callback").should be_valid it works! The test passes.
FactoryGirl works for any other attribute in my model but "callback". Why? What wrong have I or this attribute named "callback" has done? What should I do to find out the problem.
Related
I want to test #create in Decidingscontroller , and Deciding model has undertaking_id column in association with Undertaking model , and has asking_id column in association with Asking model.
So, My factories/decidings.rb is below.
factory :deciding do
after(:build) do |deciding|
deciding.asking ||=build(:asking, deciding: deciding)
deciding.undertaking ||=build(:undertaking, deciding: deciding)
end
end
and My spec/controllers/decidings_controller_spec.rb is below.
RSpec.describe DecidingsController, type: :controller do
describe '#create' do
before do
#deciding=build(:deciding)
end
context 'correct_user login' do
before do
login_user(#deciding.asking.user)
end
it 'creates with deciding +1' do
expect{post :create , undertaking_id: #deciding.undertaking_id , asking_id: #deciding.asking_id}.to change(Deciding , :count).by(1)
end
end
end
end
but #deciding in this case is below.
#<Deciding id: nil, asking_id: nil, undertaking_id: nil, created_at: nil, updated_at: nil>
so I can't create test because undertaking_id and asking_id is nil.
Why is undertaking_id and asking_id nil? Please help me...
Anyway , My factories/asking.rb is below.
FactoryGirl.define do
factory :asking do
association :user
sequence(:content){|i| "お願いします#{i}"}
end
end
The ids are nil because the records are not persisted. When you use build method, it does not save a record in the database. If a record is not saved, it cannot have ID. Use create method instead.
Try this:
factory :deciding do
after(:build) do |deciding|
deciding.asking ||= create(:asking)
deciding.undertaking ||= create(:undertaking)
end
end
I'm having issues trying to access my associated model in a one-to-many relationship during testing. I don't understand why the below doesn't return the association.
The reason I care about this problem is because I wanted to use Factory Girl to call my guardian through my_factory_girl_user.guardians.first which wasn't working. I tried to simplify by using just ActiveRecord and it still isn't behaving how I would expect.
I'm a true Rails beginner so any advice on this problem or how to better debug it would be much appreciated!
Question: Why doesn't #target_user.guardians return anything?
User Model
class User < ActiveRecord::Base
has_many :guardians, dependent: :destroy
...
end
Guardian Model
class Guardian < ActiveRecord::Base
belongs_to :user
...
end
Controller Spec
describe 'PUT #update' do
context 'when logged in and authorized' do
let(:new_attributes){
{level: 31}
}
it 'sets current guardian' do
#target_user = User.create!(profile_name: 'MyGuardian', system: 'Xbox One', region: 'North America', password: "password", password_confirmation: "password")
#target_guardian = Guardian.create!(level: 31, guardian_class: 'Titan', activity: 'Vault of Glass', user_id: #target_user.id)
puts "User: #{#target_user.inspect}"
puts "Guardian: #{#target_guardian.inspect}"
puts "user.guardians: #{#target_user.guardians}"
put :update, {id: #target_guardian.id, guardian: new_attributes}, {user_id: #target_user.id}
expect(assigns(:guardian)).to eq(#target_guardian)
end
end
Output
User: #<User id: 3147, email: nil, password_digest: "$2a$04$QPk3kCsKLp0IX.YmMPAPdO2gCe79mwVybHkFpcEsVkG...", created_at: "2014-12-16 02:55:57", updated_at: "2014-12-16 02:55:57", is_admin: nil, profile_name: "MyGuardian", system: "Xbox One", region: "North America">
Guaridan: #<Guardian id: 3284, created_at: "2014-12-16 02:55:57", updated_at: "2014-12-16 02:55:57", user_id: 3147, fireteam_id: nil, level: 31, guardian_class: "Titan", activity: "Vault of Glass", comment: nil>
user.guardians:
Answer:
Thanks Typpex for the help! My issue was that I was not refreshing the User after creating the Guardian, the solution I used was adding the below line after creating my Guardian. For more information read the answer below.
#target_user.reload
It is because you never actually added the guardian to the user's guardian list such as:
#target_user.guardians << #target_guardian
Only after that you will be able to see guardians in #target_user.guardians.
When testing with rspec you need to call the action in your controller that is actualling adding the guardian to the guardians collection in user and then test if the guardian was correctly added with something like
#target_user.guardians.size.should_be 1
I'm trying to make some simple model test:
/app/models/album.rb:
class Album < ActiveRecord::Base
has_many :slides, dependent: :restrict_with_exception
validates :name, presence: true
end
/spec/model/album_spec.rb:
require 'spec_helper'
describe Album do
before do
#album = Album.new(name: 'Example Album')
end
describe "when album name is already taken" do
before do
another_album = #album.dup
another_album.save
end
it { should_not be_valid }
end
end
I was expecting it to fail first (as I have no validates :uniqueness and index on the name field) but it passed. So I changed:
it { should_not be_valid }
to
it { should be_valid }
To see what's going on and this is what I got:
1) Album when album name is already taken should be valid
Failure/Error: it { should be_valid }
expected #<Album id: nil, name: nil, created_at: nil, updated_at: nil> to be valid, but got errors: Name can't be blank
# ./spec/models/album_spec.rb:14:in `block (3 levels) in <top (required)>'
I would like to ask you what I did wrong.
One more thing is if I can/should use expect rather than should syntax here ? I read somewhere that should is a bit deprecated and not expect is recomended but I don't know how to use it for model testing (I have it on my Controller/View test in form of expect(page) or expect(current_path). What argument can I use for model ?
I have never seen the it syntax that you are using. First thing, I would checkout the quick start documentation available here: https://github.com/rspec/rspec-rails#model-specs and then make sure that you are familiar with this set of docs as well: http://rspec.info/
From the example on github:
require "spec_helper"
describe User do
it "orders by last name" do
lindeman = User.create!(first_name: "Andy", last_name: "Lindeman")
chelimsky = User.create!(first_name: "David", last_name: "Chelimsky")
expect(User.ordered_by_last_name).to eq([chelimsky, lindeman])
end
end
You would want to change your second describe to an it and then use one or more expect to determine if the test passes. it takes a string that appears in the test output. So generally you want to make it something expressive. Additionally there is no need to use before blocks here. You can do everything in the it block:
require 'spec_helper'
describe Album do
it "fails validation when album name is already taken" do
album = Album.new(name: 'Example Album')
another_album = album.dup
expect {another_album.save!}.to raise_error(ActiveRecord::RecordInvalid,'Validation failed: This question is no longer active.')
end
end
Setup an explicit subject before your example:
subject {#album}
it { should_not be_valid }
Currently, as per the failure error#<Album id: nil, name: nil, created_at: nil, updated_at: nil> an implicit blank instance of Album is created as no explicit subject is found before the example.
previous rails 4 I had in a model
class User < ActiveRecord::Base
attr_accessible :name, :email, :password, :password_confirmation
...
end
But now strong_parameters replaced the protected_attributes so I comment it and use permit.
Now I discovered that I can access attribute without permitting it.
In rails c I manage to do this:
2.0.0p247 :002 > User.new(admin: "1")
=> #<User id: nil, name: nil, email: nil, created_at: nil, updated_at: nil, password_digest: nil, remember_token: nil, admin: true>
2.0.0p247 :016 > user = User.new(name: 'Nir', email: 'nir#example.com', password: 'foobar', password_confirmation: 'foobar', admin: "1")
=> #<User id: nil, name: "Nir", email: "nir#example.com", created_at: nil, updated_at: nil, password_digest: "$2a$10$xVnY8ydd5SoaLVipK5j4Del40FrOmu4bKypGjBEwvms7...", remember_token: nil, admin: true>
When obviously I should not be able to set and change the admin attribute. Only user.toggle(:admin) should be able to.
So what am I not understanding or should do right.
And how to make this test pass:
describe "accessible attributes" do
it "should not have allow access to admin" do
expect do
User.new(admin: "1")
end.to raise_error(ActiveModel::MassAssignmentSecurity::Error)
end
end
To prevent a user from setting the admin property, you should not add it as a parameter of the permit method.
params.require(:user).permit(:name, :whatever_else_you_allow)
Keywords in this are: params (it deals with parameters) and permit (you tell rails which properties to allow for).
Strong Parameters will make Action Controller parameters forbidden to be used in Active Model mass assignment until they have been whitelisted. In your test however, you set the property directly on the model. Nothing prevents you from doing that.
I am migrating an app from rails3.2.13 to rails4.0.0-rc1. I am having the following code:
class Foo < ActiveRecord::Base
has_many :bars
before_create :build_bars
private
def build_bars
self.bars.build({name: 'Bar 1'})
self.bars.build({name: 'Bar 2'})
end
end
The code above worked in rails3, but creates empty records in rails4. Some try & error in the console revealed that, indeed, attributes are not assigned.
f = Foo.new
f.bars.build({name: 'Bar'})
=> #<Bar id: nil, name: nil>
What's the proper way to build associations and have them being saved together with its parent record?
i think that #Mischa is right. i've been migrating my app over to rails4 and it works:
user.authorizations.build provider: "bla"
=> #<Authorization id: nil, provider: "bla", uid: nil, user_id: 1, created_at: nil, updated_at: nil>
you can have a look at the changes i did: https://github.com/phoet/on_ruby/pull/83/files#L23L59
most probably it's removing:
# Mass assignment settings
config.active_record.whitelist_attributes = true