【问题标题】:Resolve all ActiveRecord Associations using Grape::Entity (SQL Join)使用 Grape::Entity (SQL Join) 解决所有 ActiveRecord 关联
【发布时间】:2014-06-27 14:12:34
【问题描述】:

问题

我一直在搞乱 ruby​​、grape、grape-entity 和 activerecord。一切都很顺利,但是当使用 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

葡萄 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

错误

/configuration 中的 NoMethodError 4:Fixnum 的未定义方法“id”

Ruby /Library/Ruby/Gems/2.0.0/gems/grape-entity-0.4.2/lib/grape_entity/entity.rb:在delegate_attribute,第465行 Web GET 本地主机/配置

删除 :using 以使其“工作”

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

【问题讨论】:

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


    【解决方案1】:

    我对葡萄实体并不太熟悉,但我认为您需要将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 格式化为Device 对象,它是一个数字(Fixnum)。 Device::Entity 指定暴露 idname 属性,但由于没有在数字 4 上定义相应的方法,解释器会引发 NoSuchMethod 错误。

    【讨论】:

    • 哇,这么简单,但很明显,我忽略了很长时间。谢谢
    • sinatra 有类似的东西吗?
    • grape-entity,你的意思是?我相信您也可以将它与 Sinatra 一起使用。您可能还想查看ROAR,我在自己的项目中使用它。
    • 认为你可以在这里帮助我:stackoverflow.com/questions/25769645/… 遇到类似问题
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-02-29
    • 1970-01-01
    相关资源
    最近更新 更多