我可以在哈希定义中放置某种形式的If..End块吗?

时间:2010-04-06 01:53:38

标签: ruby arrays hash

我正在创建一个与Chargify集成的Web应用程序。如果用户有与该帐户关联的客户,我想返回设置为customer_id的哈希,如果必须创建客户,则返回customer_attributes

有没有办法在哈希定义中使用if..end块来做到这一点。例如,我想做类似以下的事情(不起作用):

def subscription_params(product_id)
  {
    :product_id => product_id,
    if customer_id.nil?
      :customer_attributes => customer_params,
    else
      :customer_id => customer_id,
    end
    :credit_card_attributes => credit_card_params
  }
end

4 个答案:

答案 0 :(得分:3)

使用Hash.merge有条件地合并一组(或另一组)键值对:

def subscription_params(product_id)
  {
    :product_id => product_id,
    :credit_card_attributes => credit_card_params
  }.merge(customer_id.nil? ?
    { :customer_attributes => customer_params } :
    { :customer_id => customer_id }
  )
end

答案 1 :(得分:2)

试过三元运算符?

答案 2 :(得分:1)

虽然您可以使用:key => if bool then val1 else val2 end指定单个,但是无法使用if语句选择是否在文字哈希中插入键值对。

话虽这么说,你可以使用Ruby 1.8.7和Ruby 1.9+中常用的常被忽略的Object#tap方法来有条件地将值插入到哈希中:

irb(main):006:0> { :a => "A"}.tap { |h| if true then h[:b] = "B" end }.tap { |h| if false then h[:c] = "D" end }
=> {:b=>"B", :a=>"A"}

答案 3 :(得分:1)

这样做的惯用方法是利用哈希值中的默认nil值。

> myHash = {:x => :y}  # => {:x=>:y}
> myHash[:d]           # => nil

因此,您可以设置:customer_id:customer_attributes,如果需要,则设置no,然后测试哪一个存在。当你这样做时,你可能会优先考虑:customer_id

unless purchase[:customer_id].nil?
  @customer = Customer.find(purchase[:customer_id])
else
  @customer = Customer.create!(purchase[:customer_attributes])
end