Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

activerecord where clause on relation belongs_to

I'm not strong in sql and relatively new to rails. The

Case
  attr_accessible client_id
  belongs_to Client

Client
  attr_accessibe name
  has_many Cases

I can query directly by client_id and get a record back as expected

Case.where(client_id: 1)

But I would like to query by client.name

Case.where(client.name => "Foo")

This give me an error that tells me that client is not a method of case.

Undefined method or local variable 

Ultimately, what I'm trying to do is very simple: get the first Case that belongs to client "Foo". The query I would expect to use is this.

Case.where(client.name => "Foo").first

What should it be?

like image 307
rakitin Avatar asked Sep 19 '13 17:09

rakitin


People also ask

What is difference between Has_one and Belongs_to?

They essentially do the same thing, the only difference is what side of the relationship you are on. If a User has a Profile , then in the User class you'd have has_one :profile and in the Profile class you'd have belongs_to :user .

What is an ActiveRecord relation object?

The Relation Class. Having queries return an ActiveRecord::Relation object allows us to chain queries together and this Relation class is at the heart of the new query syntax. Let's take a look at this class by searching through the ActiveRecord source code for a file called relation.

What is ActiveRecord naming convention?

Active Record uses naming conventions for the columns in database tables, depending on the purpose of these columns. Foreign keys - These fields should be named following the pattern singularized_table_name_id (e.g., item_id , order_id ).

What is ActiveRecord :: Base in Ruby?

in Ruby, :: accesses static class or module constants. ActiveRecord::Base indicates that the ActiveRecord class or module has a static inner class called Base that you're extending.


2 Answers

Case.joins(:client).where(clients: { name: 'foo' })

This query will joins the clients on the case table (eliminates the Cases without any client associated) and add the where clause "where clients.name = 'foo'"

In human language, this query does:

Get the Cases having at least one Client having the name strictly equal (case-sensitive) to 'foo'


Pay attention to the plural/singular:

  • in the joins/includes, use the same name as the relation is declared in the model

  • in the where clause, always use the pluralized version of the relation (actually the table's name)


Additionnal informations:

  • You can use an array of values in the where clause:

    Case.joins(:client).where(clients: { id: [1,2,5] })
    
  • Difference between .joins and .includes: Rails :include vs. :joins

like image 177
MrYoshiji Avatar answered Oct 13 '22 15:10

MrYoshiji


Depending on what you're doing it may be easier to go about it this way:

Client.where(:name => "foo").first.cases

This will return all the cases for the client.

like image 1
Helios de Guerra Avatar answered Oct 13 '22 17:10

Helios de Guerra