Guilherme Oderdenge
Guilherme Oderdenge

Reputation: 5001

Counting entries on association table and inject it into a model, using Rails

The goal

Count entries on association table and inject it into a model, using Rails (v. 4.1).

The scenario

There is game.rb model:

class Game < ActiveRecord::Base
  has_and_belongs_to_many :genres
end

and there is also a genre.rb model:

class Genre < ActiveRecord::Base
end

In the database, there are three tables: games, genres, games_genres – and games is still empty because I'm still developing genres area. So, genres' table is like following:

+----+-----------+
| id | name      |
+----+-----------+
|  1 | Action    |
|  2 | RPG       |
+----+-----------+

And this is games_genres table:

+----+--- -----+----------+
| id | game_id | genre_id |
+----+---------+----------+
|  1 |       1 |        1 |
|  2 |       1 |        2 |
|  3 |       2 |        1 |
+----+---------+----------+

The problem

My application has an API and to retreive genres, I'm doing this way:

class API::V1::TargetsController < ApplicationController
  def index
    render json: Genre.all.to_json
  end
end

The output is something like this:

[
  {
    id: 1,
    name: 'Action'
  },
  {
    id: 2,
    name: 'RPG'
  }
]

But, I want to inject the count of how many products has each genre. The query is simple:

SELECT COUNT(genre_id) AS products_quantity FROM game_genres

So, how can I inject products_quantity see above's query within Genre model? Something to get the JSON's output like this:

[
  {
    id: 1,
    name: 'Action',
    products_quantity: 2
  },
  {
    id: 2,
    name: 'RPG',
    products_quantity: 1
  }
]

Upvotes: 0

Views: 67

Answers (1)

Bart Jedrocha
Bart Jedrocha

Reputation: 11570

You can add a method option to the to_json method. Thus you can define a product_quantity method on your Genre model

def product_quantity
  game_genres.count
end

and then have it included in the to_json call.

class API::V1::TargetsController < ApplicationController
  def index
    render json: Genre.all.to_json(methods: :product_quantity)
  end
end

While the above will work, I would suggest you use something more robust like rabl to handle JSON responses.

Upvotes: 2

Related Questions