I am trying to test my default scope line in a model.
My test is as follows:
it 'orders by ascending name by default' do
expect(Coaster.scoped.to_sql).to eq Coaster.order(:name).to_sql
end
My error is:
expected: "SELECT \"coasters\".* FROM \"coasters\" ORDER BY name ASC, name"
got: "SELECT \"coasters\".* FROM \"coasters\" ORDER BY name ASC"
What does the , name
part at the end of the first line of the error mean and how can I resolve this?
UPDATE:
My test:
describe 'default scope' do
let!(:coaster_one) { FactoryGirl.create(:coaster, name: "Tower of Terror") }
let!(:coaster_two) { FactoryGirl.create(:coaster, name: "Apocalypse") }
it 'orders by ascending name' do
Coaster.all.should eq [:coaster_two, :coaster_one]
end
end
My errors:
expected: [:coaster_two, :coaster_one]
got: [#<Coaster id: 5, name: "Apocalypse", height: "60", speed: 60.0, length: "160", inversions: 4, material: nil, notes: nil, lat: nil, lng: nil, manufacturer_id: nil, park_id: 408, created_at: "2013-07-23 20:48:52", updated_at: "2013-07-23 20:48:52", slug: "apocalypse-at-alton-towers", style: nil, covering: nil, ride_style: nil, model: nil, layout: nil, order: nil, dates_ridden: nil, times_ridden: nil>, #<Coaster id: 4, name: "Tower of Terror", height: "60", speed: 60.0, length: "160", inversions: 4, material: nil, notes: nil, lat: nil, lng: nil, manufacturer_id: nil, park_id: 407, created_at: "2013-07-23 20:48:52", updated_at: "2013-07-23 20:48:52", slug: "tower-of-terror-at-alton-towers", style: nil, covering: nil, ride_style: nil, model: nil, layout: nil, order: nil, dates_ridden: nil, times_ridden: nil>]
(compared using ==)
UPDATE 2:
It looks as though Rails 4 deprecates the use of default_scope so in light of this, I have remove the default_scope from my model and replaced it with a standard scope.
The new scope is now:
scope :by_name_asc, lambda { order("name ASC") }
and my associated test is:
describe 'scopes' do
let!(:coaster_one) { FactoryGirl.create(:coaster, name: "Tower of Terror") }
let!(:coaster_two) { FactoryGirl.create(:coaster, name: "Apocalypse") }
it "orders coasters by ascending name" do
Coaster.by_name_asc.should eq [:coaster_two, :coaster_one]
end
end
When running this test I get:
1) Coaster scopes orders coasters by ascending name
Failure/Error: Coaster.by_name_asc.should eq [:coaster_two, :coaster_one]
expected: [:coaster_two, :coaster_one]
got: [#<Coaster id: 15, name: "Apocalypse", height: "60", speed: 60.0, length: "160", inversions: 4, material: nil, notes: nil, lat: nil, lng: nil, manufacturer_id: nil, park_id: 528, created_at: "2013-07-24 22:36:50", updated_at: "2013-07-24 22:36:50", slug: "apocalypse-at-alton-towers", style: nil, covering: nil, ride_style: nil, model: nil, layout: nil, order: nil, dates_ridden: nil, times_ridden: nil>, #<Coaster id: 14, name: "Tower of Terror", height: "60", speed: 60.0, length: "160", inversions: 4, material: nil, notes: nil, lat: nil, lng: nil, manufacturer_id: nil, park_id: 527, created_at: "2013-07-24 22:36:50", updated_at: "2013-07-24 22:36:50", slug: "tower-of-terror-at-alton-towers", style: nil, covering: nil, ride_style: nil, model: nil, layout: nil, order: nil, dates_ridden: nil, times_ridden: nil>]
(compared using ==)
Diff:
@@ -1,2 +1,2 @@
-[:coaster_two, :coaster_one]
+[#<Coaster id: 15, name: "Apocalypse", height: "60", speed: 60.0, length: "160", inversions: 4, material: nil, notes: nil, lat: nil, lng: nil, manufacturer_id: nil, park_id: 528, created_at: "2013-07-24 22:36:50", updated_at: "2013-07-24 22:36:50", slug: "apocalypse-at-alton-towers", style: nil, covering: nil, ride_style: nil, model: nil, layout: nil, order: nil, dates_ridden: nil, times_ridden: nil>, #<Coaster id: 14, name: "Tower of Terror", height: "60", speed: 60.0, length: "160", inversions: 4, material: nil, notes: nil, lat: nil, lng: nil, manufacturer_id: nil, park_id: 527, created_at: "2013-07-24 22:36:50", updated_at: "2013-07-24 22:36:50", slug: "tower-of-terror-at-alton-towers", style: nil, covering: nil, ride_style: nil, model: nil, layout: nil, order: nil, dates_ridden: nil, times_ridden: nil>]
# ./spec/models/coaster_spec.rb:10:in `block (3 levels) in <top (required)>'
Any ideas on what is going wrong?
A better way to test your default scope is to use real data with an expected output. Create dummy objects for your class, then query the class and compare the result to what you expect to be the correct order:
describe 'default scope' do
let!(:book_one) { Book.create(name: "The Count of Monte Cristo") }
let!(:book_two) { Book.create(name: "Animal Farm") }
it 'orders by ascending name' do
Book.all.should eq [book_two, book_one]
end
end
let!(:book_one)
creates an instance of Book
and assigns it to a local variable called book_one
. Its name
attribute is The Count of Monte Cristo. let!(:book_two)
does something similar.
If the default order is name ASC
, then querying the Book
model should return an ActiveRecord relation with book_two
as the first element ("Animal..."), and book_one
as the second element ("The C...").
We can test this expectation as follows:
Book.all.should eq [book_two, book_one]
This does not test your SQL, but it tests the direct output of your code, which is more useful. It is also database independent.
Your example is adding a second order term to the default, so you're getting name ASC, name
. Try stripping off the first order clause first with reorder('')
, e.g.:
expect(Coaster.scoped.to_sql).to eq Coaster.reorder('').order('name ASC').to_sql
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With