在Ruby的最后一个参数魔法哈希中添加一个非文字哈希元素?

时间:2011-07-08 15:20:33

标签: ruby hash literals

许多Rails助手使用惯用选项哈希作为最后一个参数; Ruby会自动在该哈希中插入额外的方法参数。我经常发现自己想要有条件地插入一个元素,或者编写一个提供元素的帮助器。伪Ruby中的两个例子:

link_to "Example 1", "http://www.example.com", needs_confirmation? ? :confirm => "Are you sure?" : nil    # syntax error; nil can't be a hash element

link_to "Example 2", "http://www.example.com", unique_link_id

# I don't want to return a hash; I want to return an element of a hash
def unique_link_id
  :id => "our_link_#{user.id}"    # Syntax error
  {:id => "our_link_#{user.id}"}  # valid, but returns a hash that ends up being an element of the options hash
  {:id => "our_link_#{user.id}"}.flatten_into_my_parent_hash  # What's in my brain
end

有一些优雅的方法吗?显然,我无法控制Rails助手,所以我不能强迫它们压扁哈希。 (呃,不是说有Hash#flatten方法,但即使有。)

我可以在方法调用之前将哈希构建为变量,当然,也可以选择添加元素,但是...... ick。

让我们规定这些是人为的例子,并假设帮助者不允许:confirm => nil:id => nil,并且unique_link_id可能想要遗漏ID。我对哈希语法比解决Rails问题更感兴趣。

任何?

1 个答案:

答案 0 :(得分:2)

我认为您应该尝试以下内容:

link_to "Example 1", "http://www.example.com", :confirm => needs_confirmation? ? "Are you sure?" : nil

对于第二种情况,你可以用类似的话说出以下内容:

link_to "Example 2", "http://www.example.com", :id=>unique_link_id

注意:unique_link_id应该返回一个字符串(如果你不想拥有id,则返回nil)

要回答您的问题,您需要了解rails如何处理您在方法中传递的这些参数(例如帮助程序)。

大多数铁路助手都是这样开始的:

def a_helper(*args)
  options = args.extract_options!
  ...
end

您应该了解以上内容:假设将Array作为参数传入。所有:something =>您还添加的值将转换为哈希值,该哈希值是此数组的最后一个元素。因此extract_options!将正常参数与哈希选项分开。因此,为了您想要的工作,所有选项最终应该在一个哈希中。

在这里做一个长篇故事排序就是你应该做的一个例子:

 link_to "Example 1", "http://www.example.com",{:confirm=>"Are you sure?"}.merge(unique_link_id)

在这种情况下,unique_link_id返回一个哈希并与其他选项合并。如果unique_link_id返回空哈希值({}),则您的选项中不会添加任何内容,并且每个人都很高兴:)

如果您的选项太复杂,我建议您在调用所需的帮助程序(或方法)之前创建一个选项变量。在将{1}}作为方法的最后一个参数传递之前,options应该是与其他哈希合并的哈希值。

提示:非常有用的哈希函数是hash.merge(),hash.merge!()和hash.reverse_merge()