从两个数据源创建哈希的最优雅方法

时间:2019-03-25 05:15:39

标签: ruby-on-rails ruby ruby-on-rails-4

我有一个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 个答案:

答案 0 :(得分:2)

通用方法,接受键列表作为参数:

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 :(得分:1)

可能有很多解决方案可以实现这一目标,但是,这是一个更简单的解决方案:

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

答案 2 :(得分:1)

我认为您的操作方式正确,但是building变量将被覆盖,您需要定义一个新变量,例如 building2 = {}

答案 3 :(得分:1)

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

答案 4 :(得分:0)

您可以使用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