Rails, why joins returns array with non-uniq values?

I use example with Rails 3, but I believe that this is true for Rails 2.3 as well.

Suppose, I have model City that has many Locations. I try to find Cities that have locations.

I use following code:

City.joins(:locations)

But output array is:

=> [#<City id: 5, name: "moscow", created_at: "2010-07-02 15:09:16", updated_at: "2010-07-02 15:09:16">, #<City id: 5, name: "moscow", created_at: "2010-07-02 15:09:16", updated_at: "2010-07-02 15:09:16">, #<City id: 5, name: "moscow", created_at: "2010-07-02 15:09:16", updated_at: "2010-07-02 15:09:16">, #<City id: 5, name: "moscow", created_at: "2010-07-02 15:09:16", updated_at: "2010-07-02 15:09:16">]

Array length is 4 (number of locations of Moscow).

In what case it can be useful? For what aims are 4 copies of one object in output-array?

I can use City.joins(:locations).uniq, but I lost agile of arel.

I have two questions:

  1. Why joins returns non unique array?
  2. What is prefer to use instead of joins for this purpose?

Answers


Join essentially says to combine two tables and treat it like one table, sending back whatever would be found. That means it will find you every combination of city and location (Rails is helping out by matching things up based on the belongs_to/has_many relationship in your models).

Doing City.joins(:locations) would be for finding all the locations in a city. Doing it the other way (Location.joins(:city)) would be for finding what city a location is in.

Now, to just find the list of cities that have some locations, you might try City.select(:city).joins(:locations).group('cities.id') The select() clause tells it to just bring back the City, and the group() clause tells it to not bring back duplicate copies.


Need Your Help

jquery mobile listview search filter start typing detect

jquery-mobile cordova

I want to detect when a user start type intp jquery mobile list view filter input.

How do I get mouse positions in my view model

c# wpf mvvm

From MVVM Design pattern, the viewmodel should not know the view. But in my case, I need the view and the model, I mean :