Rspec rails : check if object.value is false - ruby-on-rails

I'm testing a cron job in rails and I want to test if an attribute of object to be false by default, this the portion of code that do the job :
describe ".perform()" do
before :each do
SendReportCronJob.perform()
end
context "automatically_send_report" do
it "should be false by default" do
binding.pry()
expect( automatically_send_report.value ).to be "false"
end
end
context "time_limit" do
it "should not be nil" do
expect( time_limit_for_sending_report.value ).to_not be_nil
end
end
end
the problem is the automatically_send_report.value return a "false" value !
here the output of rails console when I do binding.pry() :
#<Setting:0x00000009990878> {
:id => "69617295-4209-4092-80cf-5934d1cf7d38",
:related_id => "cd830ace-933a-4230-ad54-bd94e63d5d7b",
:key => "automatically_send_report",
:value => "false",
:data_type => "boolean",
:is_archived => false,
:updated_by_id => nil,
:device_id => nil,
:created_at => Wed, 18 Apr 2018 18:34:35 +03 +03:00,
:updated_at => Wed, 18 Apr 2018 18:34:35 +03 +03:00
}
can I convert this value from string to boolean in the rspec file ?

You don't need to convert the string to boolean, you can compare strings as well, but in that case you need to use eq instead of be, as they are different objects with the same value:
expect(automatically_send_report.value).to eq "false"

Related

factory_bot build_stubbed strategy

The factory_bot documentation for build strategies says:
factory_bot supports several different build strategies: build, create, attributes_for and build_stubbed
And continues with some examples of usage. However, it doesn't clearly state what the result of each one is. I've been using create and build for a while now. attributes_for seems straightforward from the description and I see some uses for it. However, what is build_stubbed? The description says
Returns an object with all defined attributes stubbed out
What does "stubbed out" mean? How is this different from either create or build?
Let's consider the difference on the example of these factories:
FactoryBot.define do
factory :post do
user
title { 'Post title' }
body { 'Post body' }
end
end
FactoryBot.define do
factory :user do
first_name { 'John' }
last_name { 'Doe' }
end
end
build
With build method everything is easy. It returns a Post instance that's not saved
# initialization
post = FactoryBot.build(:post)
# call
p post
p post.user
# output
#<Post:0x00007fd10f824168> {
:id => nil,
:user_id => nil,
:title => "Post title",
:body => "Post body",
:created_at => nil,
:updated_at => nil
}
#<User:0x00007f8792ed9290> {
:id => nil,
:first_name => "Post title",
:last_name => "Post body",
:created_at => nil,
:updated_at => nil
}
Post.all # => []
User.all # => []
create
With create everything is also quite obvious. It saves and returns a Post instance. But it calls all validations and callbacks and also creates associated instance of User
# initialization
post = FactoryBot.create(:post)
# call
p post
p post.user
# output
#<Post:0x00007fd10f824168> {
:id => 1,
:user_id => 1,
:title => "Post title",
:body => "Post body",
:created_at => Sat, 18 Jun 2022 05:32:17.122906000 UTC +00:00,
:updated_at => Sat, 18 Jun 2022 05:32:17.122906000 UTC +00:00
}
#<User:0x00007f8792ed9290> {
:id => 1,
:first_name => "John",
:last_name => "Joe",
:created_at => Sat, 18 Jun 2022 05:32:17.122906000 UTC +00:00,
:updated_at => Sat, 18 Jun 2022 05:32:17.122906000 UTC +00:00
}
Post record and associated user record were created in the database:
Post.all # => [<Post:0x00007fd10f824168> {...}]
# User also created in the database
User.all # => [<User:0x00007f91af405b30> {...}]
build_stubbed
build_stubbed imitates creating. It slubs id, created_at, updated_at and user_id attributes. Also it skips all validations and callbacks.
Stubs means that FactoryBot just initialize object and assigns values to the id created_at and updated_at attributes so that it just looks like created. For id it assign integer number 1001 (1001 is just default number what FactoryBot uses to assign to id), for created_at and updated_at assigns current datetime. And for every other record created with build_stubbed is will increment number to be assigned to id by 1.
First FactoryBot initialize user record and assign 1001 to id attribute but not save it to the database than it initialize post record and assing 1002 to the id attribute and 1001 to user_id attribute to make association, but also doesn't save record to the database.
See example below.
#initialization
post = FactoryBot.build_stubbed(:post)
# call
p post
p post.user
# output
# It looks like persisted instance
#<Post:0x00007fd10f824168> {
:id => 1002,
:user_id => 1001,
:title => "Post title",
:body => "Post body",
:created_at => Sat, 18 Jun 2022 05:32:17.122906000 UTC +00:00,
:updated_at => Sat, 18 Jun 2022 05:32:17.122906000 UTC +00:00
}
#<User:0x00007f8792ed9290> {
:id => 1001,
:first_name => "John",
:last_name => "Joe",
:created_at => Sat, 18 Jun 2022 05:32:17.122906000 UTC +00:00,
:updated_at => Sat, 18 Jun 2022 05:32:17.122906000 UTC +00:00
}
Post and user records were not created in the database!!!
# it is not persisted in the database
Post.all # => []
# Association was also just stubbed(initialized) and there are no users in the database.
User.all # => []

Can someone point out to me why ActiveRecord::Enum is not working as expected in this simple example?

I am implementing some code refactoring and for my purposes, I've determined that ActiveRecord::Enum would be a perfect fit. For those who have not used or heard of ActiveRecord::Enum here is the documentation link
ActiveRecord::Enum.
Here is code taken from the docs that I am having a problem with.
class Conversation < ActiveRecord::Base
enum status: [ :active, :archived ]
end
# conversation.update! status: 0
conversation.active!
conversation.active? # => true
conversation.status # => "active"
# conversation.update! status: 1
conversation.archived!
conversation.archived? # => true
conversation.status # => "archived"
# conversation.status = 1
conversation.status = "archived"
conversation.status = nil
conversation.status.nil? # => true
conversation.status # => nil
Here is my example code which tries to mimic this behavior:
class ReverificationTracer < ActiveRecord::Base
enum status: [ :verified, :unverified ]
end
rev = ReverificationTracker.create
rev.verified! ==> true
rev.unverified? ==> false
rev.status ==> nil
rev.unverified! ==> true
rev.unverified? ==> false
rev.status ==> nil
When I inspect the rev variable, I do see that the status has shifted to '0'
rev
id: 1,
account_id: nil,
status: "0",
created_at: Wed, 24 Feb 2016 16:24:55 UTC +00:00,
updated_at: Wed, 24 Feb 2016 16:25:21 UTC +00:00>
When it is archived I see the status increment to 1.
Why is this not working as I would expect from the documentation?
The issue is caused by your status column being string column, not the integer. Change it to integer and everything will work as expected.

How to validate :created_at in model (RAILS 3)

irb(main):044:0> i1.created_at
=> Thu, 24 Apr 2014 02:41:15 UTC +00:00
irb(main):045:0> i2.created_at
=> Thu, 24 Apr 2014 02:41:15 UTC +00:00
irb(main):046:0> i1.created_at == i2.created_at
=> false
irb(main):047:0> i1.created_at.to_time.to_i == i2.created_at.to_time.to_i
=> true
Seems not to work validates_uniqueness_of :created_at
because
irb(main):046:0> i1.created_at == i2.created_at
=> false
How to validate created_at? Don't want to save with the same date.
+++ UPDATE +++
irb(main):048:0> i1.created_at.class
=> ActiveSupport::TimeWithZone
irb(main):049:0> i2.created_at.class
=> ActiveSupport::TimeWithZone
Since they might have different precision milliseconds.
Refer to the post: Testing ActiveSupport::TimeWithZone objects for equality
Chances are the millisecond values would be unequal.
puts i1.created_at.usec
puts i2.created_at.usec
I think, if you are getting concurrent requests, there are chances that you may have multiple entries in the table which are created at same time and will have same time stamps.
As you said, if you don't want to save with the same date, you can put a lock while saving the entries, removing the possibility of creating two entries at same time. In that case validates_uniqueness_of :created_at should also work.
Just in case
class Item < ActiveRecord::Base
attr_accessible :asin, :domain, :formatted_price, :user_id, :created_at
validate :double_dates
private
def double_dates
if Item.where(:user_id => self.user_id, :asin => self.asin, :domain => self.domain).where("DATE(created_at) = ?", Date.today).length >= 1
errors.add(:created_at, "no double dates")
end
end
end

Wrong boolean result comparing Date objects

I'm trying to write test that compare some dates. So far i have 2 tests, one of them works as intended, but the other one fails because doesnt/not correctly compare dates.
Here is my code:
def self.has_expired?(card, start_month, start_year, annually)
card_date = Date.new(card.year, card.month, -1)
billing_date = Date.new(start_year, start_month, -1)
if !annually
p '--------'
p card_date
p billing_date
card_date > billing_date
else
#return false
end
end
creditcard object
creditcard = ActiveMerchant::Billing::CreditCard.new(
:number => 1234567890123456
:month => 01,
:year => 13,
:first_name => 'John',
:last_name => 'Doe',
:verification_value => 132,
:brand => 'visa'
)
Here is output of p's
First block works as intended.
"--------"
Tue, 31 Jan 0013
Thu, 28 Feb 2013
false
Second block fails, expecting true, but got false
."--------"
Tue, 31 Jan 0013
Fri, 30 Nov 2012
false
Here is my rspec code
describe CreditCard do
context 'card_expired' do
it 'should return false with args passed to method (02month, 13 year, annually==false)' do
CreditCard.has_expired?(creditcard, 02, 2013, false).should == false
end
it 'should return true with args passed to method (11month, 12 year, annually==false)' do
CreditCard.has_expired?(creditcard, 11, 2012, false).should == true
end
end
end
in irb it works as charm, returning correct value(true/false)
I think the problem is in your logic. A card is expired when the expiration date is before the billing date, thus when
card_date < billing_date # expired
and not when
card_date > billing_date # valid
Also try puting in the full 2013 and see if that helps if it keeps breaking
:year => 2013,
You're also missing a comma after this line (probably a copy/paste error) :number => 1234567890123456

mongoid update_attributes changed?

I want to update_attributes and than check if information is changed
You can simply pass this code to rails console in existing rails + mongoid project
class TestModel
include Mongoid::Document
include Mongoid::Timestamps
field :name, type: String
end
test = TestModel.new({:name => "name 1"})
test.save()
=> true
test
=> created_at: 2012-11-14 13:48:26 UTC, updated_at: 2012-11-14 13:48:26 UTC
test.changed?
=> false
test.name_changed?
=> false
test.update_attributes({:name => "name 2"})
=> true
test.changed?
=> false
test.name_changed?
=> false
test
=> created_at: 2012-11-14 13:48:26 UTC, updated_at: 2012-11-14 13:49:23 UTC
Am I doing something wrong or this is a bug?
Its perfectly logic.
Dirty methods are meant to be used to check if an object has changed before it's saved. By definition a persisted object has no pending changes.
You should do:
test.assign_attributes(attributes)
test.changed? #=> true
test.save
See method definition.

Resources