使用Grape :: Entity解析所有ActiveRecord关联(SQL Join)

时间:2014-05-09 18:10:32

标签: ruby activerecord grape grape-api grape-entity

问题

我一直在搞乱红宝石,葡萄,葡萄实体和活跃的记录。一切都在游泳,但是当using项使用expose关键字时,我无法从葡萄实体中获得所需的结果。

我的目标是基本上解析所有activerecord个关联,然后返回生成的JSON。这样我就有了一个完整的对象来展示我的配置API方法。

如果您需要更多信息,请您快乐地提供任何内容。

注意: 我使用rackup作为我的服务器,我根本不使用rails。

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

Grape API

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

错误

  / p配置中的NoMethodError   未定义的方法`id&#39; 4:Fixnum

     

Ruby /Library/Ruby/Gems/2.0.0/gems/grape-entity-0.4.2/lib/grape_entity/entity.rb:在delegate_attribute中,第465行   Web GET localhost / configuration

删除:使用它来工作&#34;

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结果

{
    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"
}

期望的结果

{
    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"
}

1 个答案:

答案 0 :(得分:3)

我对葡萄实体并不过分熟悉,但我认为你需要定义Configuration::Entity如下:

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

您想要曝光的是与Configuration相关联的对象,而不仅仅是其外键ID。

您看到的错误消息是由您的代码尝试格式化,例如device_id,这是一个数字(Fixnum),作为Device对象。 Device::Entity指定公开idname属性,但由于在数字4上没有定义相应的方法,解释程序会引发NoSuchMethod错误。