Make blank params[] nil
Consider what you're doing here by using filters in the controller to affect how a model behaves when saved or updated. I think a much cleaner method would be a before_save
call back in the model or an observer. This way, you're getting the same behavior no matter where the change originates from, whether its via a controller, the console or even when running batch processes.
Example:
class Customer < ActiveRecord::Base
NULL_ATTRS = %w( middle_name )
before_save :nil_if_blank
protected
def nil_if_blank
NULL_ATTRS.each { |attr| self[attr] = nil if self[attr].blank? }
end
end
This yields the expected behavior:
>> c = Customer.new
=> #<Customer id: nil, first_name: nil, middle_name: nil, last_name: nil>
>> c.first_name = "Matt"
=> "Matt"
>> c.middle_name = "" # blank string here
=> ""
>> c.last_name = "Haley"
=> "Haley"
>> c.save
=> true
>> c.middle_name.nil?
=> true
>>
How to remove empty parameters from params hash?
Put this after the hash:
.reject{|_, v| v.blank?}
Passing params without nil
You can get category parameters by defining a method like,
def category_params
params.fetch(:category, {})
end
And, then look up for Products by,
@search_name = params[:search]
@category = category_params[:name]
@products = Product.search(@search_name, @category)
In my opinion, if you are making a direct query on Product, then you should do like,
def product_params
params.fetch(:product, {})
end
@category = product_params[:category_id]
@title = product_params[:title]
@products = Product.search(@category, @title)
And in product model,
def self.search(category, title)
where("category_id = ? AND title LIKE ?", category, "%#{title}%")
end
If params[:object].nil? :object = value
I my opinion it is the models responsiblity to keep itself in a valid state. Furthermore it is the best solution according to DRY principles if multiple controllers change of update the same model. Therefore I would do something like this in the Post
model:
before_validation :set_default_title
private
def set_default_title
self.title = title.presence || 'Unnamed'
end
Rails converts empty arrays into nils in params of the request
After much searching, I discovered that you starting in Rails 4.1 you can skip the deep_munge "feature" completely using
config.action_dispatch.perform_deep_munge = false
I could not find any documentation, but you can view the introduction of this option here:
https://github.com/rails/rails/commit/e8572cf2f94872d81e7145da31d55c6e1b074247
There is a possible security risk in doing so, documented here: https://groups.google.com/forum/#!topic/rubyonrails-security/t1WFuuQyavI
Rails - Strong parameters with empty arrays
The temporary solution I've come down to is:
params[:foo_ids] ||= [] if params.has_key?(:foo_ids)
params.permit(foo_ids: [])
Here, foo_ids
is set to an empty array only if is passed. If it is not passed in the request, it is ignored.
I'm still hoping to find a better solution to this, as this sort of thing will be quite common in the project I'm working on - please do suggest better ideas if you have any.
Related Topics
Nested Object Creation with JSON in Rails
Ruby: Character to Ascii from a String
How to Convert a String to a Class Method
Case-Insensitive Array#Include
Failed to Build Gem Native Extension
How to Test If a Div Has a Certain CSS Style in Rspec/Capybara
Migrating from Rails 2 to Rails 3
Rendering a Partial from a Controller in Rails
Rails Search with Optional Parameters
What's the Difference Between Process.Fork and Process.Spawn in Ruby 1.9.2
Transforming Datetime into Month, Day and Year
Which Algorithm Does Ruby's Sort Method Use
Activerecord Select Except Columns
Match String That Doesn't Contain a Specific Word