Самый элегантный способ создать хэш из двух источников данных - PullRequest
1 голос
/ 25 марта 2019

У меня есть building_table и api :: building_table, я хотел бы иметь данные из building_table по умолчанию, но если данные не существуют в building_table, я бы хотел получить их по адресу api :: building_table.Проблема в том, что есть атрибуты, которые могут отсутствовать в building_table, но существуют в api building_table.В каждой таблице также есть столбцы с разными именами.

Вот мой пример кода

def get_building_info
  building = Building.find_by(id: params[:id])
  api_building = Api::Building.find_by(id: params[:id])
  building_hash = {}
  building_hash[:name] = building.name || api_building.name
  building_hash[:room] = building.room || api_building.room
  building_hash[:rent] = building.rent || api_building.monthly_fee
...
end

Есть ли более удобный способ сделать это?Кстати, это в моем контроллере.

Ответы [ 5 ]

2 голосов
/ 25 марта 2019

Общий подход, принимающий список ключей в качестве аргумента:

def get_building_info(keys = %i[name room rent].zip(%i[name room fee]))
  building = Building.find_by(id: params[:id])
  api_building = Api::Building.find_by(id: params[:id])
  keys.map do |key, api_key|
    [
      key,
      building.attributes[key.to_s] || api_building.attributes[api_key.to_s]
    ]
  end.to_h
end
1 голос
/ 25 марта 2019

Я думаю, что вы делаете это правильно, но building переменная будет перезаписана, вам нужно определить новую переменную, такую ​​как building2 = {}

1 голос
/ 25 марта 2019
before_action :find_records, only: :get_building_info

def get_building_info
  building_hash = {}
  building_hash[:name] = building_name
  building_hash[:room] = building_room
  # OR
  building_hash[:name], building_hash[:room] = building_name, building_room

end

private

def find_records
  @building = Building.find_by(id: params[:id])
  @api_building = Api::Building.find_by(id: params[:id])
end

def building_name
  @building.name || @api_building.name
end

def building_room
  @building.room || @api_building.room
end
1 голос
/ 25 марта 2019

Для достижения этой цели может существовать множество решений, но, тем не менее, есть более простое решение:

def get_building_info
  building = Hash.new
  building[:name], building[:room] = desired_building.name, desired_building.room 
end

private

 def desired_building
    Building.find_by(id: params[:id]) || 
    Api::Building.find_by(id: params[:id])
 end
0 голосов
/ 25 марта 2019

Вы можете использовать Enumerable # each_with_object :

attrs = [ %i[name name], %i[room room], %i[rent monthly_fee] ]
attrs.each_with_object({}) do |(name, alias_name), h|
  h[name] = building[name] || api_building[alias_name]
end
...