【问题标题】:In Rails, why are my controller params being modified by the class在 Rails 中,为什么我的控制器参数被类修改
【发布时间】:2016-06-30 17:08:13
【问题描述】:

我有一个类似于此的控制器操作:

def reports
  puts params
  @stats = Client.stats(params)
  puts params
end

初始参数可能如下所示:

{ end: '2012-01-01 21:00:19' }

在我的客户端模型中,我有这个:

def self.stats(opts)
  opts[:start] = (Time.now - 30.days).to_i
  ...do some calculations..
  return stats
end

如果我检查函数运行前后发送的 params 对象,我可以看到它已被 self.stats 方法修改。

在上面的示例中,我没有在初始参数中发送“开始”,该方法将其添加到计算中 - 正如预期的那样。

我没想到的是该函数会修改原始哈希!

有人可以解释为什么会这样吗?

--编辑--

我忘了说我尝试创建参数的副本并改用它,同样的问题。

def reports
  a = params
  @stats = Client.stats(a)
  puts params
end

参数还在更新?!

【问题讨论】:

  • 只是补充一点,永远不要改变方法的参数可能是一个好习惯。它会使该方法的调用者感到困惑。
  • 为什么不会修改你传入的内容?创建对同一对象的新引用不会创建新对象,而是创建新引用。也许您想克隆或深度克隆对象?
  • 因为我们必须将日期标准化为标准格式,然后我们在跨不同数据库的多个查询中进行修改 - mysql、mongo、redis 查询、elasticsearch 和 big query。我们更容易从标准时间开始,然后根据我们使用的查询进行修改。

标签: ruby ruby-on-rails-4


【解决方案1】:

那是因为您的函数调用获取对参数的引用而不是副本。如果您执行 opts[:start] = (Time.now - 30.days).to_i 之类的操作,则您正在编辑 params 对象。

a = params: 现在两个变量都指向内存中的同一个地方。您只复制了指针。

Google 搜索 ruby object copyruby deep copy 或在 stackoverflow 上搜索。第一次尝试你可以试试params.clone

【讨论】:

  • 我尝试制作副本,查看编辑,并且也已更新。那我怎样才能复制这个对象呢??
  • 不,你没有。 paramsa 指向内存中的同一个地方。您只复制了指针。谷歌ruby object copyruby deep copy 或在stackoverflow 上搜索。第一次尝试你可以试试params.clone
  • 我不知道这一点!太好了,你能补充一下你的答案吗?我会接受的。
【解决方案2】:

每当您更新参数的任何值时,请像这样获取参数的副本

a = params.clone

它将在内存中创建一个新元素

如果你这样做,它不会在内存中创建一个新元素,它将指向相同的内存

a = 参数

试试这个

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-02-13
    • 2018-10-01
    • 1970-01-01
    • 1970-01-01
    • 2019-01-09
    • 1970-01-01
    相关资源
    最近更新 更多