【问题标题】:rails-settings: NoMethodError: undefined method `merge' for []:Arrayrails-settings: NoMethodError: undefined method `merge' for []:Array
【发布时间】:2011-09-05 13:20:59
【问题描述】:

我正在尝试使用 Ruby 1.8.7 将 rails-settings gem (https://github.com/100hz/rails-settings) 实现到我的 Rails 3 项目中

设置和检索设置完美无缺,但如果我尝试获取特定用户的所有设置,则会出现错误。

因此,在“rails 控制台”中,以下工作:

user = User.find(123)
user.settings.color = :red
user.settings.color

但如果我尝试获取所有设置:

user.settings.all

我明白了:

NoMethodError: []:Array 的未定义方法“合并”

来自 /[...]/.rvm/gems/ruby-1.8.7-p334/bundler/gems/rails-settings-883114dfd933/lib/rails-settings/settings.rb:55:in `all'

来自 (irb):5

settings.rb 中的第 55 行:

#retrieve all settings as a hash (optionally starting with a given namespace)
def self.all(starting_with=nil)
  options = starting_with ? { :conditions => "var LIKE '#{starting_with}%'"} : {}
  vars = thing_scoped.find(:all, {:select => 'var, value'}.merge(options))

  result = {}
  vars.each do |record|
    result[record.var] = record.value
  end
  # line 55 is below this one...
  @@defaults.select{ |k| k =~ /^#{starting_with}/ }.merge(result).with_indifferent_access
end

这里有什么问题?或者这是 ruby​​ 1.8.7 vs. 1.9.2 的事情?

【问题讨论】:

标签: ruby ruby-on-rails-3


【解决方案1】:

这看起来像是在尝试对 Array 进行合并,这不是 Ruby 中 Array 类的方法。哈希支持合并,看起来您返回的对象不是正确的类型。作者绝对依赖于哈希,在最后一行的下一行中调用了“with_indifferent_access”,它试图允许您从带有字符串或符号的哈希中选择项目。

我现在无法进一步检查这颗宝石,我希望我能提供一个更有帮助的答案。如果这个问题稍后没有得到答复,我会回来帮助你。

不知道作者为什么在选项和变量中使用双引号和单引号。他还尝试手动填充散列而不是注入。无论如何,这并不糟糕,但我认为您从文件中发布的一小段代码仍有改进的空间。

【讨论】:

    【解决方案2】:

    这是 Ruby 1.8.7 与 1.9.2 的区别

    ruby 1.8.7下的Hash select方法会返回一个Array of Arrays。

    例子:

    {:a => 'a', :b => 'b', :c => 'c'}.select {|k, v| v > 'a'} #=> [[:b,'b'],[:c,'c']]
    

    虽然运行 Ruby 1.9.2 会返回相同的结果:

    {:a => 'a', :b => 'b', :c => 'c'}.select {|k, v| v > 'a'} #=> {:b => 'b',:c => 'c'}
    

    您需要发布处理结果并再次将其转换为 hsah 或使用 inject 之类的内容。

    编辑:

    这是inject的一个快速/丑陋的例子

    {:a => 'a', :b => 'b', :c => 'c'}.inject({}) {|r, e| e[1] > 'a' ? r.merge({e[0] => e[1]}) : r }
    

    语义上:

    collection.inject(container) { |container, element| select_condition ? container + element : container }
    

    编辑 2:(基于@CaleyWoods 帖子)

    Hash[*@@defaults.select{ |k,v| k =~ /^#{starting_with}/ }.flatten].merge(result)
    

    |k, v| 将防止不必要的警告。

    【讨论】:

    • This post 也说明了这一点,并给出了使用 * 和 flatten 创建哈希的示例。
    • @Caley_Woods 这是一个很棒的帖子!我将“窃取”* + flatten 技术。
    • @Harry 我会在 Github 上联系维护人员,让他们知道您必须使用RUBY_VERSION
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2020-09-24
    • 1970-01-01
    • 2017-07-04
    • 2012-02-01
    • 2015-03-19
    • 2016-08-13
    • 1970-01-01
    相关资源
    最近更新 更多