开发者

rails-settings: NoMethodError: undefined method `merge' for []:Array

开发者 https://www.devze.com 2023-03-09 06:05 出处:网络
I\'m trying to implement the rails-settings gem (https://github.com/100hz/rails-settings) into my Rails 3 project using Ruby 1.8.7

I'm trying to implement the rails-settings gem (https://github.com/100hz/rails-settings) into my Rails 3 project using Ruby 1.8.7

Setting and retrieving the settings works perfectly, but I get an error if I try getting all settings of a specific user.

So, in the 'rails console' the following works:

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

But if I try to get all settings:

user.settings.all

I get:

NoMethodError: undefined method `merge' for []:Array

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

from (irb):5

line 55 in the settings.rb:

#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 th开发者_如何学Cis one...
  @@defaults.select{ |k| k =~ /^#{starting_with}/ }.merge(result).with_indifferent_access
end

Whats the problem here? Or is this a ruby 1.8.7 vs. 1.9.2 thing?


That's a Ruby 1.8.7 vs. 1.9.2 thing

The Hash select method under ruby 1.8.7 will return an Array of Arrays.

Example:

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

While the same thing running Ruby 1.9.2 will return:

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

You will need to post process the result and turn it into a hsah again or use something like inject.

Edit:

Here is a quick/ugly example of the inject

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

Semantically speaking:

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

Edit 2: (Based on @CaleyWoods post)

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

The |k, v| will prevent unnecessary warnings.


This looks like it's trying to do a merge on an Array which is not a method the Array class in Ruby. Merge is supported for Hash, it looks like your returned object is not the correct type. The author was definitely relying on a hash, in the next to last line 'with_indifferent_access' is called which is trying to allow you to select items from the hash with strings or symbols.

I can't examine the gem further right now and I wish I could provide a more helpful answer. If this hasn't been answered later i'll come back and help you out.

Not sure why the author is using double and single quotes in options and vars. He's also trying to populate the hash by hand instead of with inject. It's not awful by any means but I think there's room for improvement in the small bit of code you posted from the file.

0

精彩评论

暂无评论...
验证码 换一张
取 消