Ruby on Rails似乎破坏了方法中的常量

5hcedyr0  于 2023-11-18  发布在  Ruby
关注(0)|答案(2)|浏览(140)

我的常数似乎被修改,但它是如何。
环境是rails 7.0.7.2 Ruby 3.1.2p20 via rbenv
考虑

module ArrayTestMethods
  PROFILE_PARAMS = [["id","id"],["customer_id","contactId"],["channelId","channelId"],["identifierId","identifierId"],["platform","platform"],["identifier","identifier"],["created","createdAt"],["updated","updatedAt"]].freeze

  def showme
    params = {"id"=>"d1", "contactId"=>"contact1", "channelId"=>"bbc2", "identifierId"=>"ident2", "platform"=>"events", "inheritedFrom"=>"", "createdAt"=>"2023-10-19T17:03:58Z", "updatedAt"=>"2023-10-19T17:03:58Z", "identifier"=>"353860872561"}
    x = model_from_hash(params, PROFILE_PARAMS)
    pp x

  end
  def json_walker(params, *args)
    args.each do | arg|
      params = params[arg]
      return nil if params.nil?
    end
    return params
  end
   def model_from_hash(params, array_map, debug = false)
    #im doing the below as a test i've tried
    # array = array_map.clone same result
    # i've also tried using array_map on its own
    array =  Array.new
    array << array_map
    attributes_array = array[0]

    puts "array map before"
    pp attributes_array
    attr_hash = Hash.new

    attributes_array.each do | arr|
      model_attribute = arr[0]
      arr.shift
      data = json_walker(params, *arr)
      puts "arr0 - #{model_attribute} data - #{data}" if debug
    end
    puts "array map after "
    pp array_map
    return array_map
  end
  module_function :json_walker, :model_from_hash, :showme

字符串
如果你运行一次ArrayTestMethods::showme,你会得到

如果你运行第二次,你会得到

结果应该是

euoag5mw

euoag5mw1#

arr.shift修改数组。
因此,无需修改each块中的数组,您可以将值从一个变量传递到另一个变量,而无需修改原始数组。
我会努力改变

attributes_array.each do | arr|
  model_attribute = arr[0]
  arr.shift
  data = json_walker(params, *arr)
  puts "arr0 - #{model_attribute} data - #{data}" if debug
end

字符串

attributes_array.each do | arr|
  model_attribute = arr[0]                # first element
  data = json_walker(params, arr[1..-1])  # elements from second position to the end
  puts "arr0 - #{model_attribute} data - #{data}" if debug
end

5q4ezhmt

5q4ezhmt2#

首先,你似乎对Ruby中的.freeze有不切实际的期望。它不会深度冻结包含在另一个对象中的对象。例如:

[1, 2, 3].freeze.push(0) # can't modify frozen Array: [1, 2, 3] (FrozenError)
[[1, 2, 3]].freeze.tap {|x| x[0].push(4)} == [[1, 2, 3, 4]] # true

字符串
这并不是数据被“损坏”了,而是语言的工作方式,Rails并没有改变Ruby的基本原理。
如果你想做的是规范化一组输入参数或产生序列化的输出,有更好的方法可以实现。
您可以简单地创建一个Hash,其中包含输入键和规范化形式的Map:

MAPPING = {
  "contactId"   => "customer_id"
  "createdAt"   => "created"
  "updatedAt"   => "updated"
}.freeze


然后你只需转换哈希的键:

params.transform_keys(MAPPING)
{"id"=>"d1",
 "customer_id"=>"contact1",
 "channelId"=>"bbc2",
 "identifierId"=>"ident2",
 "platform"=>"events",
 "inheritedFrom"=>"",
 "created"=>"2023-10-19T17:03:58Z",
 "updated"=>"2023-10-19T17:03:58Z",
 "identifier"=>"353860872561"}

的字符串
如果任务更复杂,则创建一个带有属性的对象(类),并在setter、初始化器或工厂方法中处理转换。

class ThingAdapter
  attribute_accessor :customer_id
  alias_method :contactId=, :customer_id=

  def initialize(**params)
    params.each do |k,v|
      self.send("#{k}=", v)
    end
  end
end


一般来说,在Rails中,无论何时你在做任何类型的繁重的数组或哈希操作,你几乎肯定是做错了。

相关问题