簡體   English   中英

如何在Ruby中創建每個鍵值對作為新對象時將哈希值分配給對象

[英]How to assign hash values to an object while creating each key-value pair as a new object in Ruby

我有一個person對象,從webservice調用(大約400個鍵值對)獲取有關該人的大量信息。 散列中的每個項目都有些不同,並且在向用戶顯示之前必須以不同方式處理(例如,轉換的時間戳值,處理的nils或者轉換的文本等),並且鍵本身在其他地方也很重要並且必須是從固定的映射列表中“翻譯”。

目前,在Rails視圖中直接訪問屬性的哈希值,然后在幫助器中清除返回值,如

<%= clean_up(person.attributes["some_strangly_formatted_name"]) %>

要么

<%= show_timestamp(person.attributes["some_nonhuman_time"]) %>

我試圖弄清楚如何動態地將這些值分配給人物對象本身,同時還將每個屬性創建為不同類別(例如屬性)的自己的對象,以在那里移動相關行為,作為數量和輔助方法的復雜性正在失去控制。

理想情況下,在視圖中,我可以調用person.some_timestamp ,它將返回人類可讀時間或person.name並返回該人名的字符串

我已經嘗試過如此處所示的變量賦值,但似乎必須在對象上預定義屬性,並且我試圖避免400個attr_accessors並且還試圖容納可以添加新屬性的可能性Set Attribute Ruby對象的動態 具有哈希,以Ruby DRY方式 設置對象屬性 以將哈希值分配給對象

非工作方法看起來像

  def process_attributes(attributes)
    attributes.each {|k,v| public_send("#{k}=", v)}
  end

我怎樣才能實現這個目標? 更一般地說,這種策略是否有意義?

編輯

我開始對下面的答案進行討論,但它讓我想到“在Ruby / Rails中通常有一種內置的方法來實現這一點”,我會查看SimpleDelgator,如果有人想利用它來創建模型就像PersonAttributor < SimpleDelgator並在其中進行轉換一樣,我贊成它。


不確定這是否是您想要的方向,但您可以使用JSON序列化做一些事情。 如果您碰巧使用Postgres,則可以使用JASONB列類型並將數據存儲為可以直接查詢的JSON。 但是普通的序列化可能會發生如下:

person.attributes = {'one' => 'something', 'two' => 'some_other_thing'}.to_json
=> "{\"one\":\"something\",\"two\":\"some_other_thing\"}"
person.save

JSON(person.attributes)
=> {"one"=>"something", "two"=>"some_other_thing"}

JSON(person.attributes)["one"]
=> "something"

這是一個非常簡單的,袖手旁觀的例子。 它將所有鍵/值對放入一列而不會產生大量的attr_accessors。 當哈希首次分配給此人時,您可以進行清理。

這並不包括將這些屬性移動到自己的類中的想法。 如果你想在飛行中創建這些對象,我不確定你是通過這樣做來節省自己的。 如果您希望它們可以作為方法訪問,您可以以某種方式使用OpenStruct,這里是一個:

在你的人模型中你可以有一個方法:

class Person < ApplicationRecord
...
def attr_object
  OpenStruct.new(self.attributes)
end
...

然后,您將獲得一個包含所有鍵作為方法的對象,並將您的值作為這些方法的返回...

os_obj = person.attr_object
=> #<OpenStruct one='something', two='something_else'....>

你現在有一個對象,它為你提供方法oneone= 您可以使用方法將所有轉換應用於該對象...

os_obj.one
=> 'something'
os_obj.one = 'something new'
=> 'something new'

您可以創建一個繼承自Person的模型並創建OpenStruct對象。 它還可以通過將其序列化為JSON來存儲OpenStruct對象中更新的鍵/值對:

person.attr_store = os_obj.to_h.to_json
"{\"one\":\"something new\"....}"

new_obj = Openstruct.new(JSON(person.attr_store))
=> #<OpenStruct one='something_new', two='something_else'....>

希望能為您帶來有用的東西。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM