我正在尝试做一个开源贡献,下面带有options.merge()
的star_rating方法中的代码行(这是我尝试提交的更改)被踢回以下消息“这是无效的Ruby语法(1.8.7和1.9.3)......“我的问题是为什么?我检查了ruby交互式shell上的Hash#merge
方法,它似乎有效。
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
答案 0 :(得分:2)
根据第一版“红宝石编程语言”的第6.4.4章
如果Ruby是方法的最后一个参数(或者如果后面的唯一参数是一个块参数,前缀为&),则允许您省略散列文字周围的花括号。
您的方法调用的格式为method a => b, c => d, {e => f, g => h}, i => j
,因为hash.merge将返回一个哈希值。所以你要分解哈希,而不是放入一个哈希,并且编译器假定a => b, c=>d
是一个哈希,这不会是最后一个参数,打破了最后一个参数规则。
另外,根据同一节
如果省略括号,那么必须省略花括号。
你的hash.merge返回花括号中的哈希值,这会破坏该规则。
编辑:只要哈希不是唯一的参数,这实际上就可以了。
答案 1 :(得分:1)
通常,将options
传递给Ruby方法通常是通过将其作为最后一个参数来完成的。在某些情况下,它实际上需要是最后一个参数。
答案 2 :(得分: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运算符来执行您想要的操作will be **
for hashes:
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}