Testing for FactoryGirl Results - ruby-on-rails

I'm trying to test to see if the items the array exist after I create the factory.
spec/models/thing_spec.rb
require 'rails_helper'
RSpec.describe Thing, :type => :model do
let(:thing) { Array.new(3) {FactoryGirl.create(:thing) } }
it "should sort the items in order" do
expect(thing).to include(ordering:1, ordering:2, ordering:3)
end
end
spec/factories/things.rb
FactoryGirl.define do
factory :thing, :class => 'Thing' do
name "item_name"
sequence(:ordering)
end
end
Below are the results that I received.
results
1) Things should be sorted in order
Failure/Error: expect(thing).to include(ordering:1, ordering:2, ordering:3)
expected [#<Thing id: 1, name: "item_name", create_date: "2014-11-07 04:18:17", modified_date: "2014-11-14 04:18:17", ordering: 1>, #<Thing id: 2, name: "item_name", create_date: "2014-11-07 04:18:17", modified_date: "2014-11-14 04:18:17", ordering: 2>, #<Thing id: 3, name: "item_name", create_date: "2014-11-07 04:18:17", modified_date: "2014-11-14 04:18:17", ordering: 3>] to include {:ordering => 2}
Diff:
## -1,2 +1,19 ##
-[{:ordering=>2}]
+[#<Thing:0x007fb96217cc30
+ id: 1,
+ name: "item_name",
+ create_date: Fri, 07 Nov 2014 04:18:17 UTC +00:00,
+ modified_date: Fri, 14 Nov 2014 04:18:17 UTC +00:00,
+ ordering: 1>,
+ #<Thing:0x007fb9621cfca0
+ id: 2,
+ name: "item_name",
+ create_date: Fri, 07 Nov 2014 04:18:17 UTC +00:00,
+ modified_date: Fri, 14 Nov 2014 04:18:17 UTC +00:00,
+ ordering: 2>,
+ #<Thing:0x007fb96221eda0
+ id: 3,
+ name: "item_name",
+ create_date: Fri, 07 Nov 2014 04:18:17 UTC +00:00,
+ modified_date: Fri, 14 Nov 2014 04:18:17 UTC +00:00,
+ ordering: 3>]

You can't do it this way. You'll have to check each record individually like this
it "should sort the items in order" do
expect(thing[0].ordering).to eq(1)
expect(thing[1].ordering).to eq(2)
expect(thing[2].ordering).to eq(3)
end
Or do something like this:
it "should sort the items in order" do
expect(thing.map(&:ordering)).to eq([1, 2, 3])
end
You can only use include to check if the array includes an element as a whole, like this:
expect(thing).to include(thing[0])

Related

Uniqueness validation not functioning as expected

I have a Call model with the following validations:
class Call < ActiveRecord::Base
validates_uniqueness_of :external_id, scope: :source
end
I generate new calls through a webhook that calls the following service:
class AircallWebhookService
include HubspotExtension
def initialize(params)
#event = params["event"]
#params = params["data"]
#call = nil
#aircall_number = nil
#employee_email = nil
end
def process
#call = Call.find_by(source: :aircall, external_id: #params["id"])
if #call.present?
p "Found existing call!"
else
p "Could not locate existing call."
#call = Call.new(source: :aircall, external_id: #params["id"])
end
#call.source = 1
#call.external_id = #params["id"]
#call.url = #params["direct_link"]
#call.direction = #params["direction"]
#call.status = #params["status"]
#call.missed_call_reason = #params["missed_call_reason"]
#call.started_at = Time.at(#params["started_at"]) if #params["started_at"].present?
#call.answered_at = Time.at(#params["answered_at"]) if #params["answered_at"].present?
#call.ended_at = Time.at(#params["ended_at"]) if #params["ended_at"].present?
#call.duration = #params["duration"]
#call.raw_digits = #params["raw_digits"]
#call.aircall_user_id = #params.dig("user", "id")
#call.contact_id = #params.dig("contact", "id")
#aircall_number = #params.dig("number", "digits").try{|n| n.gsub(/\s|-|\(|\)|\+/, "")}
#call.aircall_user_id = #params.dig("user", "id")
#employee_email = #params.dig("user", "email")
if !#params["tags"].empty?
mapTagToReferrer
end
#call.comments = mapComments
if #call.save
linkTagToCall
linkCallToEmployee
updateHubspotEngagement
end
end
...
end
For some reason, despite the uniqueness validation, I continue to see calls with the same external_id and source. For example these are 2 records in my DB:
[
[0] #<Call:0x000055d780f639b8> {
:id => 8149,
:location_id => nil,
:referrer => nil,
:consultation => nil,
:created_at => Tue, 07 Sep 2021 15:42:01 EDT -04:00,
:updated_at => Tue, 07 Sep 2021 15:42:01 EDT -04:00,
:worldwide => nil,
:external_id => 582402916,
:source => "aircall",
:direction => "inbound",
:started_at => Tue, 07 Sep 2021 15:41:03 EDT -04:00,
:answered_at => Tue, 07 Sep 2021 15:41:10 EDT -04:00,
:ended_at => Tue, 07 Sep 2021 15:41:57 EDT -04:00,
:duration => 54,
:status => "done",
:missed_call_reason => nil,
:aircall_user_id => 567754,
:contact_id => nil,
:comments => nil,
:lead_status => nil,
:call_type => "unknown"
},
[1] #<Call:0x000055d780f636e8> {
:id => 8150,
:location_id => nil,
:referrer => nil,
:consultation => nil,
:created_at => Tue, 07 Sep 2021 15:42:01 EDT -04:00,
:updated_at => Tue, 07 Sep 2021 15:42:01 EDT -04:00,
:worldwide => nil,
:external_id => 582402916,
:source => "aircall",
:direction => "inbound",
:started_at => Tue, 07 Sep 2021 15:41:03 EDT -04:00,
:answered_at => Tue, 07 Sep 2021 15:41:10 EDT -04:00,
:ended_at => Tue, 07 Sep 2021 15:41:57 EDT -04:00,
:duration => 54,
:status => "done",
:missed_call_reason => nil,
:aircall_user_id => 567754,
:contact_id => nil,
:comments => nil,
:lead_status => nil,
:call_type => "unknown"
}
]
They are identical and even the created_at is identical down to the millisecond. How is this possible?
Here's the controller in case it's necessary:
class API::WebhooksController < ApplicationController
def aircall_webhook
ac = AircallWebhookService.new(params)
ac.process
head :ok
end
end
validates_uniqueness_of doesn't actually guarantee that duplicate values cannot be inserted. It merely catches most of the cases where users input duplicated data and provides user feedback. Its very much prone to race conditions, and is foiled by stuff as simple as double clicking grannies.
If uniqueness is actually important you need to enforce it on the database layer with a unique index.
add_index :calls, [:external_id, :source], unique: true

Rails group_by id and group created

I have a model call GcMission
it contains gamecharacter_id, mission_id and of course created_at.
Now I need to group_by gamecharacter_id, and then group the created_at to see how many mission_id per day.
I assum the result will be like
{
69 => {
'2017-08-18' => 1
},
75 => {
'2017-08-18' => 2
},
78 => {
'2017-08-18' => 1,
'2017-08-19' => 1,
}
}
But I am stuck at that.
Here is what I've written.
GcMission.select('gamecharacter_id, mission_id, created_at').where(mission_id: assign_mission_ids).where('finish_counter >= 1').group_by{|a| a.gamecharacter_id}
And the result is like
{
69 => [
[0] #<GcMission:0x007ff6c6a53650> {
:gamecharacter_id => 69,
:mission_id => 3,
:created_at => Tue, 18 Apr 2017 03:20:36 UTC +00:00
}
],
75 => [
[0] #<GcMission:0x007ff6c6a52d18> {
:gamecharacter_id => 75,
:mission_id => 3,
:created_at => Tue, 18 Apr 2017 06:38:27 UTC +00:00
},
[1] #<GcMission:0x007ff6c6a52408> {
:gamecharacter_id => 75,
:mission_id => 4,
:created_at => Tue, 18 Apr 2017 07:55:40 UTC +00:00
}
],
78 => [
[0] #<GcMission:0x007ff6c6a51be8> {
:gamecharacter_id => 78,
:mission_id => 3,
:created_at => Tue, 18 Apr 2017 17:29:24 UTC +00:00
},
[1] #<GcMission:0x007ff6c6a51580> {
:gamecharacter_id => 78,
:mission_id => 4,
:created_at => Wed, 19 Apr 2017 03:20:31 UTC +00:00
}
]
}
Try Following
gc_missions = GcMission.select("gamecharacter_id, DATE(created_at) AS date,
COUNT(mission_id) AS mission_count")
.group('gamecharacter_id, date')
If you want count of unique mission_id per gamecharacter_id per day use
COUNT(DISTINCT(mission_id))
You may like to verify using following code
gc_missions.each {|gc| puts "#{gc.gamecharacter_id}, #{gc.date}, #{gc.mission_count}"}

When doing an ActiveRecord query, how do I prioritize a record that has an attribute marked as true first then created_at desc after?

I have a bunch of Answers on a Question.
What I want to do is order the answers on each question in two steps:
If there is an accepted answer, return that one first, THEN...
Return the rest of the answers, created_at: :desc
If #1 doesn't exist, just default to 2.
This is what I tried, but it didn't work:
[21] pry(main)> q.answers.order(:accepted, created_at: :desc)
[23] pry(main)> q.answers.order(accepted: true, created_at: :asc).inspect
ArgumentError: Direction "true" is invalid. Valid directions are: [:asc, :desc, :ASC, :DESC, "asc", "desc", "ASC", "DESC"]
from /gems/activerecord-5.0.0.rc1/lib/active_record/relation/query_methods.rb:1164:in `block (2 levels) in validate_order_args'
[24] pry(main)> q.answers.order(accepted: "true", created_at: :asc).inspect
ArgumentError: Direction "true" is invalid. Valid directions are: [:asc, :desc, :ASC, :DESC, "asc", "desc", "ASC", "DESC"]
from gems/activerecord-5.0.0.rc1/lib/active_record/relation/query_methods.rb:1164:in `block (2 levels) in validate_order_args'
How do I achieve this?
Edit 1
This is an example of an answer with an accepted: true:
[26] pry(main)> q.answers.first
=> #<Answer:0x007f997d7a5a80
id: 69,
body:
"public static Process CreateProcessAsUser(string filename, string args)\r\n {\r\n var hToken = WindowsIdentity.GetCurrent().Token;\r\n var hDupedToken = IntPtr.Zero;\r\n\r\n var pi = new PROCESS_INFORMATION();\r\n var sa = new SECURITY_ATTRIBUTES();\r\n sa.Length = Marshal.SizeOf(sa);\r\n\r\n try\r\n {\r\n if (!DuplicateTokenEx(\r\n hToken,\r\n GENERIC_ALL_ACCESS,\r\n ref sa,\r\n (int)SECURITY_IMPERSONATION_LEVEL.SecurityIdentification,\r\n (int)TOKEN_TYPE.TokenPrimary,\r\n ref hDupedToken\r\n ))\r\n throw new Win32Exception(Marshal.GetLastWin32Error());\r\n\r\n var si = new STARTUPINFO();\r\n si.cb = Marshal.SizeOf(si);\r\n ",
user_id: 1547,
question_id: 47,
created_at: Wed, 15 Jun 2016 05:20:11 UTC +00:00,
updated_at: Mon, 20 Jun 2016 22:34:08 UTC +00:00,
accepted: true,
language: nil,
comments_count: nil>
You'll need to pass a string to the order method:
q.answers.order("accepted = true DESC").order(:created_at)

How to update boolean value in rails

I'm trying to update the occupied field of runn to true during the creation of a stay.
def create
if params[:id].present?
#patient = Patient.find(params[:id])
#stay = #patient.stays.build(stay_params)
#stay.is_current = true
Runn.find_by_id(#stay.runn_id).update_attribute(:occupied, true)
else
#stay = Stays.new(stay_params)
end
if #stay.save
redirect_to #patient
end
end
This is the create method in my stays_controller.rb
class Stay < ActiveRecord::Base
belongs_to :patient
has_one :runn
has_many :feeding_events
has_many :ud_events
has_many :misc_stay_events
after_create :update
private
def update
self.check_in_dt = Time.new
self.is_current = true
end
end
This is stay.rb
class Runn < ActiveRecord::Base
belongs_to :ward
belongs_to :stay
end
This is runn.rb
When I use the console to display all, they all show that occupied is false, which makes sense because that's how I set it in seeds. However, I'm wondering how to update occupied? When I do:
[1] pry(main)> Runn.find_by_id(1)
Runn Load (0.5ms) SELECT "runns".* FROM "runns" WHERE "runns"."id" = $1 LIMIT 1 [["id", 1]]
=> #<Runn:0x007f478460d6c8
id: 1,
ident: "Run 0.0",
size: "Medium,",
amenities: nil,
created_at: Thu, 03 Dec 2015 05:50:01 UTC +00:00,
updated_at: Thu, 03 Dec 2015 05:50:01 UTC +00:00,
ward_id: 1,
occupied: false>
[2] pry(main)> Runn.find_by_id(1).occupied = true
Runn Load (0.6ms) SELECT "runns".* FROM "runns" WHERE "runns"."id" = $1 LIMIT 1 [["id", 1]]
=> true
[3] pry(main)> Runn.find_by_id(1)
Runn Load (0.5ms) SELECT "runns".* FROM "runns" WHERE "runns"."id" = $1 LIMIT 1 [["id", 1]]
=> #<Runn:0x007f478467a6b0
id: 1,
ident: "Run 0.0",
size: "Medium,",
amenities: nil,
created_at: Thu, 03 Dec 2015 05:50:01 UTC +00:00,
updated_at: Thu, 03 Dec 2015 05:50:01 UTC +00:00,
ward_id: 1,
occupied: false>
[4] pry(main)>
The occupied has not been update. However, with update_attribute:
[4] pry(main)> Runn.find_by_id(1).update_attribute(:occupied, true)
Runn Load (0.4ms) SELECT "runns".* FROM "runns" WHERE "runns"."id" = $1 LIMIT 1 [["id", 1]]
(0.2ms) BEGIN
SQL (0.4ms) UPDATE "runns" SET "occupied" = $1, "updated_at" = $2 WHERE "runns"."id" = $3 [["occupied", "t"], ["updated_at", "2015-12-03 05:52:33.949456"], ["id", 1]]
(11.0ms) COMMIT
=> true
[5] pry(main)> Runn.find_by_id(1)
Runn Load (0.5ms) SELECT "runns".* FROM "runns" WHERE "runns"."id" = $1 LIMIT 1 [["id", 1]]
=> #<Runn:0x007f479d0fd098
id: 1,
ident: "Run 0.0",
size: "Medium,",
amenities: nil,
created_at: Thu, 03 Dec 2015 05:50:01 UTC +00:00,
updated_at: Thu, 03 Dec 2015 05:52:33 UTC +00:00,
ward_id: 1,
occupied: true>
[6] pry(main)> Runn.all
Runn Load (0.6ms) SELECT "runns".* FROM "runns"
=> [#<Runn:0x007f479d0aafa0
id: 2,
ident: "Run 0.1",
size: "Small,",
amenities: nil,
created_at: Thu, 03 Dec 2015 05:50:01 UTC +00:00,
updated_at: Thu, 03 Dec 2015 05:50:01 UTC +00:00,
ward_id: 1,
occupied: false>,
#<Runn:0x007f479d0aae60
id: 3,
ident: "Run 1.0",
size: "Small,",
amenities: nil,
created_at: Thu, 03 Dec 2015 05:50:01 UTC +00:00,
updated_at: Thu, 03 Dec 2015 05:50:01 UTC +00:00,
ward_id: 2,
occupied: false>,
#<Runn:0x007f479d0aad20
id: 4,
ident: "Run 1.1",
size: "Medium,",
amenities: nil,
It has been successfully updated, but it has been removed from Runn.all. Any advice?
EDIT:
[1] pry(main)> Runn.all
Runn Load (0.8ms) SELECT "runns".* FROM "runns"
=> [#<Runn:0x007f4784e9b3a8
id: 1,
ident: "Run 0.0",
size: "Medium,",
amenities: nil,
created_at: Thu, 03 Dec 2015 05:59:02 UTC +00:00,
updated_at: Thu, 03 Dec 2015 05:59:02 UTC +00:00,
ward_id: 1,
occupied: false>,
#<Runn:0x007f4784e98a40
id: 2,
ident: "Run 0.1",
size: "Small,",
amenities: nil,
created_at: Thu, 03 Dec 2015 05:59:02 UTC +00:00,
updated_at: Thu, 03 Dec 2015 05:59:02 UTC +00:00,
ward_id: 1,
occupied: false>,
#<Runn:0x007f4784e98900
id: 3,
ident: "Run 1.0",
size: "Small,",
amenities: nil,
original Runn.all.
Please try this to update:
runn = Runn.find_by_id(1)
if !runn.nil?
runn.occupied = true
runn.save
end

Save_and_open_page is blank in cucumber / capybara but not in rspec request spec

I am baffled as to why my save_and_open_page works in my request spec, but not in this cucumber feature / web steps. It does work in other features / web steps files.
I'd love a pointer to where to begin looking for the root cause of this problem.
https://gist.github.com/2210420
ok, I think it may have something to do with this encoding error when I'm using pry?
From: /Users/ivan/dev/c4c/features/step_definitions/licenses_steps.rb # line 20:
15: name: arg1,
16: status: ExpressLicenseTechnology::PUBLISHED_STATUS)
17: end
18:
19: When /^I am on the license page for "([^"]*)"$/ do |arg1|
=> 20: binding.pry
21: visit(license_path(License.find_by_name(arg1)
22: ))
23: end
24:
25: Then /^I should see a form for licensee info$/ do
[1] pry(#<Cucumber::Rails::World>)> arg1
=> "test no fee license"
[2] pry(#<Cucumber::Rails::World>)> License.find_by_name(arg1)
=> #<License id: 3, name: "test no fee license", description: "license one description", status: "published", allow_edu: nil, allow_other: nil, allow_org: nil, allow_us_gov: nil, require_contact_info: nil, show_contact_info_form: nil, way: "clickthrough", express_license_technology_id: 1, created_at: "2012-03-27 16:39:41", updated_at: "2012-03-27 16:39:41", licensefile_file_name: "test-license.pdf", licensefile_content_type: "application/pdf", licensefile_file_size: 516650, licensefile_updated_at: "2012-03-27 16:39:41", fee: #<BigDecimal:7ffcb1310820,'0.154E3',9(18)>, allocation_rule_number: "66", fulfillment_email: nil>
[3] pry(#<Cucumber::Rails::World>)> ap License.find_by_name(arg1)
#<License:0x007ffcabf00b68> {
:id => 3,
:name => "test no fee license",
:description => "license one description",
:status => "published",
:allow_edu => nil,
:allow_other => nil,
:allow_org => nil,
:allow_us_gov => nil,
:require_contact_info => nil,
:show_contact_info_form => nil,
:way => "clickthrough",
:express_license_technology_id => 1,
:created_at => Tue, 27 Mar 2012 16:39:41 UTC +00:00,
:updated_at => Tue, 27 Mar 2012 16:39:41 UTC +00:00,
:licensefile_file_name => "test-license.pdf",
:licensefile_content_type => "application/pdf",
:licensefile_file_size => 516650,
:licensefile_updated_at => Tue, 27 Mar 2012 16:39:41 UTC +00:00,
:fee => 154.0,
:allocation_rule_number => "66",
:fulfillment_email => nil
}
=> #<License id: 3, name: "test no fee license", description: "license one description", status: "published", allow_edu: nil, allow_other: nil, allow_org: nil, allow_us_gov: nil, require_contact_info: nil, show_contact_info_form: nil, way: "clickthrough", express_license_technology_id: 1, created_at: "2012-03-27 16:39:41", updated_at: "2012-03-27 16:39:41", licensefile_file_name: "test-license.pdf", licensefile_content_type: "application/pdf", licensefile_file_size: 516650, licensefile_updated_at: "2012-03-27 16:39:41", fee: #<BigDecimal:7ffcabf01428,'0.154E3',9(18)>, allocation_rule_number: "66", fulfillment_email: nil>
[4] pry(#<Cucumber::Rails::World>)> license_path(License.find_by_name(arg1))
=> "/licenses/3"
[5] pry(#<Cucumber::Rails::World>)> visit(license_path(License.find_by_name(arg1)))
=> nil
[6] pry(#<Cucumber::Rails::World>)> save_and_open_page
encoding error : output conversion failed due to conv error, bytes 0xA3 0xC3 0x8F 0xC3
I/O error : encoder error
=> #<Thread:0x007ffcb1280f40 sleep>
[7] pry(#<Cucumber::Rails::World>)>
encoding error : output conversion failed due to conv error, bytes 0xA3 0xC3 0x8F 0xC3
I/O error : encoder error
Fixed by removing the pdf file from the license fixture.

Resources