I've been messing with ruby, grape, grape-entity, and activerecord. Everything is going swimmingly however I can't see to get the desired result from grape-entity when using the using
keyword for a expose
item.
My goal is to basically resolve all my activerecord
associations, and then return the resulting JSON. This way I have a complete object for presentation for my configurations API method.
If you need more information, please ask i'll happily provide anything and everything.
Notes: I am using rackup as my server, i'm not using rails at all.
console_game.rb
class ConsoleGame < ActiveRecord::Base
self.table_name = 'console_game'
self.primary_key = :id
has_many :configurations, :class_name => 'Configuration'
class Entity < Grape::Entity
expose :id
expose :value, :as => :console_game
end
end
cloud_user.rb
class CloudUser < ActiveRecord::Base
self.primary_key = :username
has_many :configurations, :class_name => 'Configuration'
has_many :favorites, :class_name => 'Favorite', :foreign_key => :username
class Entity < Grape::Entity
expose :username, :email, :first_name, :last_name
end
end
device.rb
class Device < ActiveRecord::Base
self.table_name = 'device'
self.primary_key = :id
has_many :configurations, :class_name => 'Configuration'
class Entity < Grape::Entity
expose :id
expose :name, :as => :device
end
end
console_system.rb
class ConsoleSystem < ActiveRecord::Base
self.table_name = 'console_system'
self.primary_key = :id
has_many :configurations, :class_name => 'Configuration'
class Entity < Grape::Entity
expose :id
expose :value, :as => :console_system
end
end
configuration.rb
class Configuration < ActiveRecord::Base
self.table_name = 'configuration'
self.primary_key = :id
belongs_to :console_system, :class_name => 'ConsoleSystem', primary_key: :id, foreign_key: :system_id
belongs_to :cloud_user, :class_name => 'CloudUser', primary_key: :username, foreign_key: :creator
belongs_to :device, :class_name => 'Device', primary_key: :id, foreign_key: :device_id
belongs_to :console_game, :class_name => 'ConsoleGame', primary_key: :id, foreign_key: :console_game_id
scope :by_system,->(system){
system_ids = ConsoleSystem.where(value: system).pluck(:id)
where(system_id: system_ids)
}
scope :by_user,->(user){
user_ids = CloudUser.where(username: user).pluck(:username)
where(creator: user_ids)
}
scope :by_device,->(device){
device_ids = Device.where(name: device).pluck(:id)
where(device_id: device_ids)
}
scope :by_game,->(game){
game_ids = ConsoleGame.where(value: game).pluck(:id)
where(console_game_id: game_ids)
}
class Entity < Grape::Entity
expose :id
expose :value
expose :device_id, :as => :device, using: Device::Entity
expose :system_id, :as => :console_system, using: ConsoleSystem::Entity
expose :console_game_id, :as => :console_game, using: ConsoleGame::Entity
expose :creator, :as => :creator, using: CloudUser::Entity
expose :created_date
expose :positive_votes
expose :negative_votes
end
end
resource :configuration do
desc "Returns all configurations."
get do
configs = Configuration.includes(:device, :console_system, :cloud_user, :console_game)
present :data, configs, :with => Configuration::Entity
present :status, "Success"
end
end
NoMethodError at /configuration undefined method `id' for 4:Fixnum
Ruby /Library/Ruby/Gems/2.0.0/gems/grape-entity-0.4.2/lib/grape_entity/entity.rb: in delegate_attribute, line 465 Web GET localhost/configuration
configuration.rb
class Entity < Grape::Entity
expose :id
expose :value
expose :device_id, :as => :device#, using: Device::Entity
expose :system_id, :as => :console_system#, using: ConsoleSystem::Entity
expose :console_game_id, :as => :console_game#, using: ConsoleGame::Entity
expose :creator, :as => :creator#, using: CloudUser::Entity
expose :created_date
expose :positive_votes
expose :negative_votes
end
JSON Result
{
data: [
{
id: 1,
value: "configuration data 1 example",
device: 4,
console_system: 1,
console_game: 1,
creator: "manster",
created_date: null,
positive_votes: 0,
negative_votes: 0
},
{
id: 2,
value: "configuration data 2 example",
device: 4,
console_system: null,
console_game: 2,
creator: "Zombieguy",
created_date: null,
positive_votes: 0,
negative_votes: 0
},
{
id: 3,
value: "configuration data 3 example",
device: 4,
console_system: null,
console_game: 3,
creator: "Justin13692",
created_date: null,
positive_votes: 0,
negative_votes: 0
}
],
status: "Success"
}
Desired Result
{
data: [
{
id: 1,
value: "configuration data 1 example",
device: {
id: 4,
device: "XIM Edge"
},
console_system: {
id: 1,
console_system: "Xbox 360"
}
console_game: {
id: 1,
console_game: "Gears of War 3"
},
creator: {
username: "manster",
email: null,
first_name: null,
last_name: null
},
created_date: null,
positive_votes: 0,
negative_votes: 0
},
{
id: 2,
value: "configuration data 2 example",
device: {
id: 4,
device: "XIM Edge"
},
console_system: null,
console_game: {
id: 2,
console_game: "Battlefield 3"
},
creator: {
username: "Zombieguy",
email: null,
first_name: null,
last_name: null
},
created_date: null,
positive_votes: 0,
negative_votes: 0
},
{
id: 3,
value: "configuration data 3 example",
device: {
id: 4,
device: "XIM Edge"
},
console_system: null,
console_game: {
id: 3,
console_game: "Call of Duty: Modern Warfare 3"
},
creator: {
username: "Justin13692",
email: null,
first_name: null,
last_name: null
},
created_date: null,
positive_votes: 0,
negative_votes: 0
}
],
status: "Success"
}
I'm not overly familiar with grape-entity but I think you need to define Configuration::Entity
as follows:
class Entity < Grape::Entity
expose :id
expose :value
expose :device, using: Device::Entity
expose :console_system, using: ConsoleSystem::Entity
expose :console_game, using: ConsoleGame::Entity
expose :cloud_user, :as => :creator, using: CloudUser::Entity
expose :created_date
expose :positive_votes
expose :negative_votes
end
What you want to be exposing are the objects associated with a Configuration
, not simply their foreign-key IDs.
The error message you're seeing is caused by your code trying to format, say, device_id
, which is a number (a Fixnum
), as a Device
object. Device::Entity
specifies exposing the id
and name
attributes, but as there are no corresponding methods defined on the number 4 the interpreter raises a NoSuchMethod
error.