0

我试图做一个开源贡献,下面的 star_rating 方法中的代码行options.merge()(这是我试图提交的更改)被踢回了以下消息“这是无效的 Ruby 语法(在 1.8.7和 1.9.3)..." 我的问题是为什么?我检查了Hash#mergeruby​​ 交互式 shell 上的方法,它似乎有效。

def star_rating(options = {})
   ##original line of code
   has_many :rates_without_dimension, :as => :rateable, :class_name => 'RateMe', :dependent => :destroy, :conditions => {:dimension => nil}  

  ##line of code I tried to submit
  has_many :rates_without_dimension, :as => :rateable, options.merge(:class_name => 'RateMe'), :dependent => :destroy, :conditions => {:dimension => nil}  
end
4

3 回答 3

2

根据“The Ruby Programming Language”第一版的第 6.4.4 章

如果哈希字面量是方法的最后一个参数(或者它后面的唯一参数是块参数,以 & 为前缀),Ruby 允许您省略围绕哈希字面量的花括号

您的方法调用的形式为method a => b, c => d, {e => f, g => h}, i => j,因为 hash.merge 将返回一个哈希值。因此,您要分解散列,而不是放入单个散列,并且编译器假定这a => b, c=>d是一个散列,这将不是最后一个参数,从而破坏了最后一个参数规则。

另外,根据同一节

如果省略括号,则必须省略花括号。

您的 hash.merge 返回花括号中的哈希,这违反了该规则。

编辑:只要哈希不是唯一的参数,这实际上就可以了。

于 2012-07-04T04:04:52.603 回答
1

通常,传递options给 Ruby 方法通常是通过将其作为最后一个参数来完成的。在某些情况下,它实际上需要作为最后一个参数。

于 2012-07-04T02:49:08.230 回答
1

这确实是无效的语法。方法调用的最后一个参数可以是 Hash,在这种情况下 Ruby 允许您删除封闭的{}:

foo(1, 2, 3, :a => 4, :b => 5)
# equivalent to:
foo(1, 2, 3, {:a => 4, :b => 5})

在您的情况下,您:as => :rateable之前有一个简单的参数 ( options.merge),这是不允许的。

如果你倒置它们,你仍然不会得到你想要的效果:

has_many :rates_without_dimension, options.merge(:class_name => 'RateMe'), :as => :rateable, :dependent => :destroy, :conditions => {:dimension => nil}
# same as
has_many :rates_without_dimension, options.merge(:class_name => 'RateMe'), {:as => :rateable, :dependent => :destroy, :conditions => {:dimension => nil}}
# => has 3 arguments, not 2.

你可以在这里做的是确保你传递了两个参数。一种方法:

has_many :rates_without_dimension, options.merge(:class_name => 'RateMe', :as => :rateable, :dependent => :destroy, :conditions => {:dimension => nil})

请注意,在 Ruby 2.0 中,可以*使用与数组 ( )等效的 splat 运算符来执行您想要的操作,这**用于哈希

h = {:b => 2}
foo(:a => 1, **h, :c => 3)
# same as
foo(:a => 1, :b => 2, :c => 3) 

# so you will be allowed to write:
has_many :rates_without_dimension, :as => :rateable, **options.merge(:class_name => 'RateMe'), :dependent => :destroy, :conditions => {:dimension => nil}
于 2012-07-04T04:04:50.830 回答