Hi,
I would like to use the acts_as_ordered plugin to step through a
collection. My problem is the :scope option. I have a one-to-many
relationship between countries and cities, and I would like to step
through the cities (on a country’s page):
class City < ActiveRecord::Base
belongs_to :country
acts_as_ordered, :order => ‘name’, :scope => ‘country_id’
Now what I would like to happen is that ‘acts_as_versioned’ would
consider the last city of a given country the last object, and NOT
return the first city of the next country for city.next, but the instead
the current city. But that is not what is happening.
What do I need to do differently?
Thanks!
Ingo
Adding :wrap => false to acts_as_ordered will stop the next and previous
methods from wrapping around, that may be what you’re after.
-Jonathan.
Thanks, Jonathan!
I tried :wrap => false and it still seems to not have the desired
effect. I guess what I am looking for is a way to tell acts_as_ordered
to step through not the entire collection of records, but only the ones
that have a belong_to relationship with a specific resource. In my
example, I would like to step through not all cities, but only the
cities of one country. Basically, I am on the page
‘/countries/us/cities’ and would like to provide prev/next navigation.
Right now I am using the following options:
acts_as_ordered :scope => ‘country_id’, :order => ‘name’, :wrap => false
But acts_as_ordered still gives me cities for other countries which in
my case generates an not-found-error since I am using
@country.cities.find(params[:id]) in the controller to find the city.
Ingo
Jonathan V. wrote:
Adding :wrap => false to acts_as_ordered will stop the next and previous
methods from wrapping around, that may be what you’re after.
-Jonathan.
Try scoping to the association and not the foreign key.
acts_as_ordered :scope => :country, :order => ‘name’
When you provide a string to :scope, it should be the piece of sql used
in
the where clause of the sql. If you use a symbol it will add _id and set
a
scope of ‘country_id = #{country_id}’.
I agree it’s not the best and probably isn’t documented either.
-Jonathan.
Please send me a failing test case so I can look at this further.
-Jonathan.
Jonathan V. wrote:
Please send me a failing test case so I can look at this further.
-Jonathan.
Hi Jonathan,
below is my failing test case. It basically asserts that if I use
acts_as_ordered to step through a collection of cities that belong to a
country (:scope => :country), then all the cities I am getting should in
fact belong to that country. Maybe I’m expecting a behavior that
acts_as_ordered was not designed for? Or maybe i misunderstand what
:scope does?
Ingo
def test_next
country = Country.find(1)
city = country.cities.first
assert_equal city.country, country
(country.cities.size-1).times do
city = city.next
assert_equal city.country, country
end
end
Thanks!
I tried this and it doesn’t seem to solve the problem either.
Ingo
Jonathan V. wrote:
Try scoping to the association and not the foreign key.
acts_as_ordered :scope => :country, :order => ‘name’
When you provide a string to :scope, it should be the piece of sql used
in
the where clause of the sql. If you use a symbol it will add _id and set
a
scope of ‘country_id = #{country_id}’.
I agree it’s not the best and probably isn’t documented either.
-Jonathan.
Of course the obvious solution would be to sort both by country_id and
name, and then test whether the ‘next’ or ‘previous’ city belongs to the
correct country. But it seems counterintuitive having to test that when
you do something like germany.cities.find_by_name(‘Berlin’).next, don’t
you think?
Ingo
Ingo W. wrote:
Jonathan V. wrote:
Please send me a failing test case so I can look at this further.
-Jonathan.
Hi Jonathan,
below is my failing test case. It basically asserts that if I use
acts_as_ordered to step through a collection of cities that belong to a
country (:scope => :country), then all the cities I am getting should in
fact belong to that country. Maybe I’m expecting a behavior that
acts_as_ordered was not designed for? Or maybe i misunderstand what
:scope does?
Ingo
def test_next
country = Country.find(1)
city = country.cities.first
assert_equal city.country, country
(country.cities.size-1).times do
city = city.next
assert_equal city.country, country
end
end
hmm,
in my app this test passes only if all cities belonging to one country
happen to be in sequence. To test for this, how about something like
this:
def test_next
country_1 = Country.create(:name => ‘country 1’
country_2 = Country.create(:name => ‘country 2’
country_1.cities.create(:name => ‘city 1’)
country_2.cities.create(:name => ‘city 2’)
country_1.cities.create(:name => ‘city 3’)
country_2.cities.create(:name => ‘city 4’)
city = country_1.cities.first
assert_equal city.country, country_1
(country_1.cities.size-1).times do
city = city.next
assert_equal city.country, country_1
end
end
BTW I ended up taking a different route since I only need a very simple
functionality. I put the following in environment.rb:
class Array
def member_after(member)
index = self.index(member) and self[index+1]
end
def member_before(member)
index = self.index(member) and self[index-1]
end
end
Now I can do things like this:
next_city = country.cities.member_after(city)
prev_city = country.cities.member_before(city)
Ingo
Jonathan V. wrote:
That test passes with the following models:
class Country < ActiveRecord::Base
has_many :cities
end
class City < ActiveRecord::Base
belongs_to :country
acts_as_ordered :scope => :country, :order => ‘name’
end
-Jonathan.
That test passes with the following models:
class Country < ActiveRecord::Base
has_many :cities
end
class City < ActiveRecord::Base
belongs_to :country
acts_as_ordered :scope => :country, :order => ‘name’
end
-Jonathan.