0

This works:

@user = User.find(current_user.id)
@users_cities = @user.cities

This does NOT work:

@other_users = User.where("id != ?", 1)
@users_cities = @other_users.cities

However, I can run the second example from the console and it works fine.

Here's the error:

NoMethodError in CitiesController#index
undefined method `cities' for #<ActiveRecord::Relation:0x007f8f670f2870>
app/controllers/cities_controller.rb:23:in `index'

Line 23 is this one:

@users_cities = @other_users.cities

Models are just has_and_belongs_to_many :cities and has_and_belongs_to_many :user. I thought that has_and_belongs_to_many :user was meant to be has_and_belongs_to_many :users but I get the same error (even after restarting the server).

ale
  • 11,636
  • 27
  • 92
  • 149
  • The issue is you're trying to call `cities` on an `ActiveRecord::Relation` (which is what is returned by `where`). The `cities` relation is only on an instance of `User`. Perhaps you're really trying to ask: "how do I return all cities related to some group of users"? – sigre Jul 15 '13 at 20:28

3 Answers3

4

Add .first to ActiveRecord::Relation object

@other_users = User.where("id != ?", 1).first
@users_cities = @other_users.cities

User.find_by_id(1) is a instance of User Model.

User.where(:id => 1) is not of User Model but ActiveRecord::Relation

Koichiro Wada
  • 381
  • 1
  • 7
1

In the former case it works fine because, @user points to a userobject. Assuming that your user model has the following attributes(id, name, created_at, updated_at).

@user= User.find(current_user.id)
@user.class
 => User(id: integer, name: string, created_at: datetime, updated_at: datetime, etc)
@user
  => #<User id: 1, name: "Amar",created_at: "2013-07-10 10:07:37", updated_at: "2013-07-10 10:07:37"> 

So now your instance variable @user points to a userobject and so the following works.

@users_cities = @user.cities 

But in case of where, it is a relation and the instance variable holds an array having a single record.

@user= User.where(:id => current_user.id)
@user.class
  => ActiveRecord::Relation
@user
  => [#<User id: 1, name: "Amar", created_at: "2013-07-10 10:07:37", updated_at: "2013-07-10 10:07:37">] 

Here, @user is not pointing to a userobject and hence you cant get the cities assoicted with that user. You can try the following.

@user= User.where(:id => current_user.id).first #first gets the first object from the array.
@user.class
 => User(id: integer, name: string, created_at: datetime, updated_at: datetime, etc)
@user
 => #<User id: 1, name: "Amar",created_at: "2013-07-10 10:07:37", updated_at: "2013-07-10 10:07:37"> 

In this case the following should work because your instance variable @user have made to point to a single userobject by using first.

@users_cities = @user.cities 

Again in your case, your are getting an array from User model

@other_users = User.where("id != ?", 1)

It will collect an array of elements. So you have to iterate over the array to find its cities.

@other_users.each do |user|
 # do manipulation with user.cities
end

In this case if you use first then it will point only to the first object in the array. So iterate through it to cover all the other users.

Amarnath Krishnan
  • 1,253
  • 1
  • 9
  • 12
0

@other_users return array of users not a single user object.you need to iterate through all objects to get cities

Use map

@users_cities = @other_users.map(&:cities) => [[city1, city 2], [city3, city4]]

if you want to have a flat array then user flattern

@users_cities = @other_users.map(&:cities).flatten

the other option is to select cities from City model not via association. something like

@users_cities = City.where("user_id != 1")

Naren Sisodiya
  • 7,158
  • 2
  • 24
  • 35