【问题标题】:Is there a way to transform only some keys in Rails using transform_keys method?有没有办法使用 transform_keys 方法只转换 Rails 中的一些键?
【发布时间】:2019-06-27 01:39:06
【问题描述】:

我有一个看起来像这样的哈希:

 "properties": [
    {
        "accommodates": 14,
        "adr": 1336.69,
        "host_id": 23724674,
        "property_id": 4576625,
        "bathrooms": 4.5,
        "bedrooms": 5,
        "business_ready": false,
        "cancellation": "strict",
        "check_in": "Anytime after 4PM",
        "check_out": "11AM",
        "cleaning_fee": 200,
        "days_a_ltm": 138,
        "days_b_ltm": 24,
        "days_r_ltm": 203,
        "extra_person_charge": 50,
        "img_count": 26,
        "img_cover": "",
        "instant_book": true,
        "last_calendar_update": "2018-02-16",
        "latitude": 39.7610167973274,
        "listed_dt": "2014-10-24",
        "listing_url": "rooms/4576625",
        "location": {
            "city": "Denver",
            "country": "United States",
            "msa": "Denver-Aurora-Lakewood, CO Metro Area",
            "neighborhood": [
                "Highland"
            ],
            "state": "Colorado",
            "zipcode": "80211"
        },
        "longitude": -105.008507384098,
        "minimum_stay": 2,
        "num_res_ltm": 64,
        "occ": 0.595308,
        "price_monthly": 17000,
        "price_nightly": 725,
        "price_weekly": 5600,
        "property_type": "Entire house",
        "rating_overall": 9.9,
        "response_rate": 100,
        "response_time": 229,
        "revenue": 271348,
        "reviews": 124,
        "room_type": "Entire home/apt",
        "scraped_dt": "2018-02-25",
        "security_deposit": 1000,
        "superhost": true,
        "title": "Huge Home in the Heart of Lohi! Groups Welcome!"
    },
    {
        "accommodates": 15,
        "adr": 781.576,
        "host_id": 14178014,
        "property_id": 9944575,
        "bathrooms": 5,
        "bedrooms": 6,
        "business_ready": true,
        "cancellation": "strict",
        "check_in": "Anytime after 3PM",
        "check_out": "12PM (noon)",
        "cleaning_fee": 200,
        "days_a_ltm": 46,
        "days_b_ltm": 7,
        "days_r_ltm": 312,
        "extra_person_charge": 15,
        "img_count": 49,
        "img_cover": "",
        "instant_book": true,
        "last_calendar_update": "2018-02-15",
        "latitude": 39.7349220878173,
        "listed_dt": "2015-12-11",
        "listing_url": "rooms/9944575",
        "location": {
            "city": "Denver",
            "country": "United States",
            "msa": "Denver-Aurora-Lakewood, CO Metro Area",
            "neighborhood": [
                "Capitol Hill"
            ],
            "state": "Colorado",
            "zipcode": "80218"
        }
 ]

我想更改属性数组哈希中的一些键,我想使用一些简单的东西,例如 transform_keys 或 deep_transform_keys;但是,这些方法替换了所有键,这需要使用下面的所有键创建一个新映射才能更改 2 或 3。特别是,我希望重命名 adr、revenue 和 occ。有谁知道是否有办法仅在某些键上执行 transform_key 或 deep_transform_key 方法?比如:

hash_name.deep_transform_keys{|k| {:adr=>'adr_ltm', :revenue => 'revenue_ltm'}[k] if k == 'adr'||'revenue'}

【问题讨论】:

    标签: ruby-on-rails hash ruby-on-rails-5


    【解决方案1】:

    有什么特定的原因你不能循环过去吗?

    hash[:properties].each_with_index do |property, i|
      hash[:properties][i][:adr_ltm] = property.delete(:adr)
      hash[:properties][i][:revenue_ltm] = property.delete(:revenue)
    end
    

    【讨论】:

    • 散列可以相当大并且嵌套,因此循环似乎效率低下且丑陋
    【解决方案2】:

    在这些情况下,有一些序列化/反序列化 gem 可以帮助您。它们允许从您的模型中渲染 json 并解析 json 以更新您的 Ruby 对象。长期维护代码非常灵活。

    # deserialize
    song = Song.new
    SongRepresenter.new(song).from_json('{"id":1, "title":"Fallout"}')
    song.id    #=> 1
    song.title #=> "Fallout"
    
    # serialize
    SongRepresenter.new(song).to_json #=> {"id":1, title":"Fallout"}
    

    【讨论】:

    • 谢谢,这实际上可能对我有很大帮助。我将查看两者,看看我是否可以根据需要实现它们。完成检查后,我会发布更新。
    【解决方案3】:

    你可以monkey patchClass Hash中的私有方法,或者重新实现你自己的,就是这个思路

    class Hash
    
    
      private
    
        def _deep_transform_keys_in_object(object, &block)
          case object
          when Hash
            object.each_with_object({}) do |(key, value), result|
              # define what key you want to run
              return unless key != :key_name
              result[yield(key)] = _deep_transform_keys_in_object(value, &block)
            end
          when Array
            object.map {|e| _deep_transform_keys_in_object(e, &block) }
          else
            object
          end
        end
    end
    

    deep_transform_keys 使用这个方法是这样的:

    def deep_transform_keys(&block)
      _deep_transform_keys_in_object(self, &block)
    end
    

    这是基本思想,不是功能齐全的代码,你需要确保它自己工作。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-12-23
      • 1970-01-01
      • 2023-01-20
      • 1970-01-01
      • 2017-08-20
      • 2018-04-05
      相关资源
      最近更新 更多