Reputation: 3899
Is there a better way to check for items_attributes than the following code? I have to check params[:order] first since sometimes that may not exist, but I hate the look of the long conditional.
if params[:order] and params[:order][:items_attributes]
UPDATE for ruby 2.3, now you can use the dig method
params.dig(:order, :item_attributes)
Upvotes: 5
Views: 2936
Reputation: 354
You can create helper method for easier work with nested hashes. Create ruby_ext.rb file in your lib folder, and write this function:
module RubyExt
module SafeHashChain
def safe(*args)
if args.size == 0 then self # Called without args ...
elsif args.size == 1 then self[args[0]] # Reached end
elsif self[args[0]].is_a?(Hash) then self[args[0]].safe(*args[1..-1])
else nil end # Reached end-value too soon
end
end
end
class Hash; include RubyExt::SafeHashChain; end
After this you can call safe method on nested hashes like this:
params.safe(:order,:items_attributes)
It will return value from items_attributes. If order or items_attributes don`t exist it will return nil.
Upvotes: 1
Reputation: 2999
You'll may like fetch with a default?
order = params.fetch(:order, {})
if order[:item_attributes]
# ...
end
Upvotes: 0
Reputation: 2724
Params is actually an instance of ActionController::Parameters
and has built in white list filtering features.
This makes it possible to do stuff like this:
# White list for Order params
def order_params
params.require(:order).permit(:items_attributes)
end
// If :order is missing exception, and then filter only permitted.
valid_params = order_params()
// Also make these calls safe without risk for unwanted params
order = Order.new(order_params())
order.save!
Upvotes: 0
Reputation: 5998
If I have such problem I would think about extending basic ruby class Hash
with something like this (this is just an idea)
class Hash
def has_nested_values?(*args)
current_value = self.dup
args.each do |arg|
current_value = current_value[arg]
break unless current_value
end
!!current_value
end
end
and the result is
h[:a] = {b: {c: {d: 1}}}
h.has_nested_values?(:a, :b, :c)
=> true
h.has_nested_values?(:a, :b, :cc)
=> false
PS I don't like dup
in implementation but it works
Upvotes: 0
Reputation: 4226
You can use try
, like so:
params[:order].try(:[], :items_attributes)
The try method returns nil
if the receiver does not respond to it, instead of raising an exception.
Hope it's helpful!
Upvotes: 0
Reputation: 160181
If you're using the andand gem:
if params[:order].andand[:items_attributes]
You could also use try
.
Upvotes: 0