I have a table called Jurisdiction and created that task to update the kind column:
namespace :populate_jurisdiction do
desc "Populate column kind of jurisdiction model"
task kind: :environment do
Jurisdiction.all.each { |jurisdiction|
case (jurisdiction.kind.nil? || jurisdiction.kind.blank?)
when jurisdiction.name.parameterize == "federal"
jurisdiction.kind = 1
when jurisdiction.name.parameterize == "estadual"
jurisdiction.kind = 2
when jurisdiction.name.parameterize == "municipal"
jurisdiction.kind = 3
when jurisdiction.name.parameterize == "privado"
jurisdiction.kind = 4
end
jurisdiction.save!
}
end
end
Then I created that test
require "spec_helper"
Rails.application.load_tasks
describe "populate_jurisdiction:kind" do
context "when update kind column of jurisdiction" do
let(:federal) { create(:jurisdiction, name: "Federal", kind: nil) }
let(:state) { create(:jurisdiction, name: "Estadual", kind: nil) }
let(:municipal) { create(:jurisdiction, name: "Municipal", kind: '') }
let(:particular) { create(:jurisdiction, name: "Privado", kind: '') }
it "when kind column is updated" do
Rake::Task["populate_jurisdiction:kind"].invoke
expect(federal.kind).to eq(1)
expect(state.kind).to eq(2)
expect(municipal.kind).to eq(3)
expect(particular.kind).to eq(4)
end
end
end
When I run the task in rails console it works, but when I run the test, I got this error
Failures:
1) populate_jurisdiction:kind when update kind column of jurisdiction when kind column is updated
Failure/Error: expect(federal.kind).to eq(1)
expected: 1
got: nil
(compared using ==)
What I'm doing wrong? How can I fix this test?
CodePudding user response:
When you invoke the rake task, there are no jurisdictions, that's why you're getting nil
. For example, federal jurisdiction is only created after the rake task when you call federal.kind
.
require "spec_helper"
Rails.application.load_tasks
describe "populate_jurisdiction:kind" do
context "when update kind column of jurisdiction" do
let(:federal) { create(:jurisdiction, name: "Federal", kind: nil) }
let(:state) { create(:jurisdiction, name: "Estadual", kind: nil) }
let(:municipal) { create(:jurisdiction, name: "Municipal", kind: '') }
let(:particular) { create(:jurisdiction, name: "Privado", kind: '') }
it "when kind column is updated" do
# NOTE: jurisdictions are not created until `let` blocks are called.
federal
state
municipal
particular
Rake::Task["populate_jurisdiction:kind"].invoke
# NOTE: `let` return values are memoized, second call will just
# retrieve the value. You have to reload the models as well
# to get the updated values from the database.
expect(federal.reload.kind).to eq(1)
expect(state.reload.kind).to eq(2)
expect(municipal.reload.kind).to eq(3)
expect(particular.reload.kind).to eq(4)
end
end
end
https://relishapp.com/rspec/rspec-core/v/3-11/docs/helper-methods/let-and-let
CodePudding user response:
You're invoking the rake task before any of the Jurisdiction's are created. When you say this:
let(:federal) { create(:jurisdiction, name: "Federal", kind: nil) }
that will create federal
when you first access it in a test and then remember that for the duration of the test. So there is no federal
until after your rake task runs. If you used let!
instead of let
and reloaded the jurisdictions after the task runs, you'd get better results.
BTW, your rake task doesn't work they way you think it does. There are two forms of case
:
case expr
when value1
...
when value2
...
end
and
case
when expr1
...
when expr2
...
end
You're using the first form when you mean to be using the second and your code is working by accident. I suspect that all your kind
s are nil
when you run this, otherwise you'd end up doing:
case false
...
end
and you'd go into the first branch where the jurisdiction.name.parameterize
test failed.
Your task should look more like:
Jurisdiction.all.reject { |j| j.kind.blank? }.each do |jurisdiction|
case jurisdiction.name.parameterize
when 'federal'
jurisdiction.kind = 1
when 'estadual'
jurisdiction.kind = 2
when 'municipal'
jurisdiction.kind = 3
when 'privado'
jurisdiction.kind = 4
end
jurisdiction.save!
end
or:
Jurisdiction.all.reject { |j| j.kind.blank? }.each do |jurisdiction|
jurisdiction.kind = case jurisdiction.name.parameterize
when 'federal' then 1
when 'estadual' then 2
when 'municipal' then 3
when 'privado' then 4
end
jurisdiction.save!
end
If kind
is an integer then kind.blank?
will only true when kind.nil?
so that can be pushed into the database:
Jurisdiction.where(kind: nil).each do |jurisdiction|
jurisdiction.kind = case jurisdiction.name.parameterize
when 'federal' then 1
when 'estadual' then 2
when 'municipal' then 3
when 'privado' then 4
end
jurisdiction.save!
end
and it looks like #parameterize
in this case is only going to be converting the name
to lower case so push all the logic into the database:
# This is an SQL CASE expression, not a Ruby one
Jurisdiction.where(kind: nil).update_all(%q(
kind = case lower(name)
when 'federal' then 1
when 'estadual' then 2
when 'municipal' then 3
when 'privado' then 4
end
))