0

Question

Below I give my current API result, however, given the SQL that is executed it isn't my Expected or Desired Result. Can anyone assist me in getting the second SQL queries results instead of the first?

Models

console_game.rb

class ConsoleGame < ActiveRecord::Base
    self.table_name = 'console_game'
    self.primary_key = :id

    has_many :configurations, :class_name => 'Configuration'
end

configuration.rb

class Configuration < ActiveRecord::Base
    self.table_name = 'configuration'
    self.primary_key = :id
end

API

resource :configuration do
  desc "Finds all configurations associated with a game."
  params do
    requires :game, type: String, desc: "Game search.", documentation: { example: 'Battlefield 3' }
  end
  route_param :game do
    get do
      ConsoleGame.where(value: 'Battlefield 3').includes(:configurations)
    end
  end
end

Debug Console

D, [2014-05-06T15:11:59.071493 #31068] DEBUG -- : ConsoleGame Load (0.4ms) SELECT console_game.* FROM console_game WHERE console_game.value = 'Battlefield 3' D, [2014-05-06T15:11:59.073289 #31068] DEBUG -- : Configuration Load (0.3ms) SELECT configuration.* FROM configuration WHERE configuration.console_game_id IN (2) 127.0.0.1 - - [06/May/2014 15:12:08] "GET /configuration/game HTTP/1.1" 200 34 25.9740

Result - get /configuration/game

[
    {
        id: 2,
        value: "Battlefield 3"
    }
]

Desired Result - get /configuration/game

[
    {
        id: 2,
        value: "x",
        device: 4,
        system: null,
        console_game_id: 2,
        creator: "yrdy",
        created_date: null,
        positive_votes: 0,
        negative_votes: 0
    },
    {
        id: 4,
        value: "ffds",
        system: 2,
        console_game_id: 2,
        creator: "gdfs",
        created_date: null,
        positive_votes: 0,
        negative_votes: 0
    }
]

Note: There are a lot of foreign indexes on this table and i'd like to resolve them all but perhaps thats for another day.

Result of ConsoleGame.where(value: 'Battlefield 3').includes(:configurations).as_json(include: :configurations)

[
    {
        id: 2,
        value: "Battlefield 3",
        configurations: [
            {
                id: 2,
                value: "ffds",
                device: 4,
                system: null,
                console_game_id: 2,
                creator: "yrdy",
                created_date: null,
                positive_votes: 0,
                negative_votes: 0
            },
            {
                id: 4,
                value: "x",
                device: 4,
                system: 2,
                console_game_id: 2,
                creator: "gdfs",
                created_date: null,
                positive_votes: 0,
                negative_votes: 0
            }
        ]
    }
]
abc123
  • 17,855
  • 7
  • 52
  • 82
  • @UriAgassi I posted my current Results and my desired Results...I want to get my desired results but I don't understand given that it is executing all the correct SQL why it isn't returning the right results. Updated to have question, hopefully to more clearly define what the goal is – abc123 May 06 '14 at 19:25
  • look at this: http://stackoverflow.com/questions/19137521/activerecord-associations-as-json-with-grape – Uri Agassi May 06 '14 at 19:29
  • @UriAgassi I'm getting `JSON` back, the issue is that my `.includes` is ran as a second SQL query but my `JSON` result is the result of the first query not the second. – abc123 May 06 '14 at 19:31
  • You are querying `ConsoleGame` and expecting to get configurations. You should set up a relationship in the other direction from `Configuration` to `ConsoleGame` and query `Configuration.joins(:console_game).where(console_game:{value:'Battlefield 3'})` this will return `Configuration`s instead of games. or look at scopes which seems even better for you. – engineersmnky May 06 '14 at 19:32
  • Have you tried simply: `ConsoleGame.where(value: 'Battlefield 3').configurations` ? – BroiSatse May 06 '14 at 19:38
  • @BroiSatse I hadn't I got the following result : `{ }` – abc123 May 06 '14 at 19:41
  • @abc123 - Hm, that should work. What does `ConsoleGame.where(value: 'Battlefield 3').configurations` give you in the console? – BroiSatse May 06 '14 at 19:43
  • @BroiSatse `ConsoleGame.where(value: 'Battlefield 3').configurations` gives only `127.0.0.1 - - [06/May/2014 15:47:18] "GET /configuration/game HTTP/1.1" 200 2 0.0043` in the console no SQL at all – abc123 May 06 '14 at 19:47
  • @abc123 - Oh geez, you need to be extra careful, you have a name clash on your model. My advice is to change name of `configurations` name to sth else. It might not seem as the problem now, but It might give you a headache in the future. – BroiSatse May 06 '14 at 20:20

1 Answers1

1

Does this work?

class ConsoleGame < ActiveRecord::Base
  #self.table_name = 'console_game'
  #self.primary_key = :id

  has_many :configurations #, :class_name => 'Configuration'
end

class Configuration < ActiveRecord::Base
  #self.table_name = 'configuration'
  #self.primary_key = :id
  belongs_to :console_game #, class_name: "ConsoleGame", primary_key: 'console_game_id', foreign_key: 'id'  #added relationship for ConsoleGame
end

resource :configuration do
  desc "Finds all configurations associated with a game."
    params do
      requires :game, type: String, desc: "Game search.", documentation: { example: 'Battlefield 3' }
    end
    route_param :game do
      get do
        #Search Configurations based on console game
        Configuration.joins(:console_game).where(console_game:{value: 'Battlefield 3'})
      end
    end
end

Better yet add a scope

class Configuration < ActiveRecord::Base
  #self.table_name = 'configuration'
  #self.primary_key = :id
  belongs_to :console_game #, class_name: "ConsoleGame", primary_key: 'console_game_id', foreign_key: 'id'  #added relationship for ConsoleGame
  scope :by_game,->(game){
           #verbosely
           #game_ids = ConsoleGame.where(value: game).pluck(:id)
           #where(console_game_id: game_ids)
           #one line
           joins(:console_game).where(console_game:{value: game})
           }
end    

Use as

Configuration.by_game('Battlefield 3')

EDIT

I have commented out the lines that are not needed because they are implied by design

engineersmnky
  • 25,495
  • 2
  • 36
  • 52
  • I defined it as `belongs_to :console_game, :class_name => 'ConsoleGame'` but this does work. Scope works as well thank you, this really helped me understand this better...I am just starting with ruby and am doing database first so these classes were generated. – abc123 May 06 '14 at 19:49
  • @abc123 no problem. Also as a heads up `:id` is always assumed to be the `primary_key` so you don't have to say so I have commented out the lines that are not needed to show you – engineersmnky May 06 '14 at 19:55