Can I put some form of If..End blocks inside of a hash definition?
I am creating a web application to integrate with Chargify. I want to return a hash with customer_id
set if the user has a cust开发者_如何转开发omer associated with the account, and customer_attributes
if a customer has to be created.
Is there any way that I could do this with an if..end block inside of the hash definition. For example, I would be wanting to do something like the following (does not work):
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
Use Hash.merge
to conditionally merge one set (or another) of key-value pairs:
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
Tried the ternary operator?
While you can specify a single value using :key => if bool then val1 else val2 end
, there's no way to use an if statement to choose whether to insert a key-value pair while in a literal hash.
That being said, you could use the oft-overlooked Object#tap
method available in Ruby 1.8.7 and Ruby 1.9+ to conditionally insert values into the hash:
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"}
The idiomatic way to do this is to take advantage of default nil values in hashes.
> myHash = {:x => :y} # => {:x=>:y}
> myHash[:d] # => nil
So, you can set either :customer_id
or :customer_attributes
, no if statement required, and later test for which one is present. You might give preference to :customer_id
, when you do this.
unless purchase[:customer_id].nil?
@customer = Customer.find(purchase[:customer_id])
else
@customer = Customer.create!(purchase[:customer_attributes])
end
精彩评论