Как определить динамический ключ в драгоценном камне виноградной сущности?

Допустим, у меня есть модель User, и я выставляю объект User через Grape::Entity. Итак, здесь я хочу определить динамический ключ, имя и значение которого будут основаны на значении других ключей (id, name, email).

module API
  module Entities
    class User < Grape::Entity
      expose :id
      expose :name
      expose :email
      expose :dynamic_key # dynamic key name will be generated based on other keys(`id`, `name`, `email`) value

      private

      def dynamic_key
       #dynamic key value here based on other keys(`id`, `name`) value
      end
    end
  end
end

Как я мог это сделать? Заранее спасибо!


person Junan Chakma    schedule 06.11.2017    source источник


Ответы (3)


У вас есть доступ к экземпляру с object:

def dynamic_key
  "#{object.id}_#{object.name}"
end

Изменить: неправильно понял вопрос. Не думайте, что вы можете получить динамический ключ таким образом. Можете ли вы просто сделать что-то вроде этого:

 expose "#{object.id}_#{object.name}".to_sym
person EJAg    schedule 06.11.2017
comment
Я знаю, что мой экземпляр object доступен здесь. Но мне нужно также динамически генерировать ключ dynamic_key (например, :foo_dynamic_key, :bar_dymanic_key) - person Junan Chakma; 06.11.2017
comment
отредактировал мой ответ, но, по общему признанию, сам не проверял. - person EJAg; 09.11.2017
comment
object не доступен там. получаю сообщение об ошибке undefined local variable or method object for API::Entities::CostCenter:Class Did you mean? object_id - person Junan Chakma; 09.11.2017

Почему вы хотите это сделать? Если вам нужно что-то динамичное, это должно быть значение, которому соответствует ключ, а не сам ключ. Потребитель вашего API должен иметь возможность полагаться на то, что имена ключей соответствуют вашим задокументированным определениям, а также помнить, что ключи должны иметь имя, на которое вы можете постоянно ссылаться, которое сопоставляется с динамическим значением. Итак, если вы хотите предоставить какой-либо атрибут dynamic_key с динамически сгенерированным значением, вы можете сделать это:

expose :id
expose :name
expose :email
expose :dynamic_key do |object, _options|
  "#{object.id}_#{object.name}"
end

Хэш { id: 1, name: 'Foo', email: '[email protected]' } будет представлен как:

{ id: 1, name: 'Foo', email: '[email protected]', dynamic_key: '1_Foo' }
person Allison    schedule 04.09.2020

Если кто-то ищет решение, вот что я делаю:

class Trucs < Grape::Entity
  expose :id

  # expose custom / dynamic fields
  expose :details, merge: true # merge true to avoid "details": {...} in response

  private

  def details
    details_list = {}
    list_of_fields = %w[first_key second_key third_key] # keys can be dynamically created, this is just a sample.
    list_of_fields.each do |field_name|
      details_list[field_name.to_sym] = "#{field_name} value" # OR object.send(field_name) OR anythig you need
    end
    return details_list
  end
end

Результат:

{
  "id": 1,
  "first_key": "first_key value",
  "second_key": "second_key value",
  "third_key": "third_key value"
}

Или для простого случая с одним динамическим ключом на основе идентификатора и имени.

def details
  {"#{object.id}_#{object.title}": 'my dynamic value'}
end
person LiKaZ    schedule 15.06.2021