While developing a project using ubiquo with the latest 0.8-stable release, I found an interesting problem that arises on my environment but not on others.
When doing the filtered search, since the last changes we made to make all controllers use the new paginated_filtered_search, this is done in the Asset model this way:
def self.filtered_search(filters = {}, options = {})
new_filters = {}
filters.each do |key, value|
if key == :type
new_filters["filter_type"] = value
elsif key == :text
new_filters["filter_text"] = value
elsif key == :visibility
new_filters["filter_visibility"] = value
elsif key == :created_start
new_filters["filter_created_start"] = value
elsif key == :created_end
new_filters["filter_created_end"] = value
else
new_filters[key] = value
end
end
super new_filters, options
end
This step is necessary because some older projects might still use filtered_search. In here we simply transform the old filters to new ones and call super to perform the filtering.
Then in ubiquo_core we have the filtered_search extension, that does this:
def filtered_search(params = {}, options = {})
scopes = select_scopes(params, options[:scopes])
scopes.inject(self) do |results, pair|
pair.last.blank? ? results : results.send(pair.first, pair.last)
end.all(options.except(:scopes))
end
This basically applies the named scopes on the filters if the filter is actually set (!pair.last.blank?).
This works fine until the "filter_type" filter is evaluated.
Asset has this named_scope:
named_scope :type, lambda {|type|{
:conditions => ["asset_type_id IN (?)", type.to_s.split(',').map(&:to_i)]
}}
When the "filter_type" filter, having the pair [:type, "5"] (5 is an example, any other type id would work), is evaluated during the inject sequence, if it's the first non nil filter evaluated,the code will do something like this:
Asset.send(:type, "5").
And this will successfully apply the named scope, returning the Assets that have an asset_type_id of 5.
However, if a previous filter is applied, this will fail. When doing Asset.send(:type, "5") in a previously filter-injected results, what the send method will try to execute will be the "type" method of the named scope, which takes no arguments, resulting in an exception.
Example:
ree-1.8.7-2011.03 :002 > Asset.visibility("Public").type("5")
Asset Load (0.8ms) SELECT * FROM "assets" WHERE ("assets"."type" = 'AssetPublic')
ArgumentError: wrong number of arguments (1 for 0)
from /home/brafales/.rvm/gems/ree-1.8.7-2011.03@comradio/gems/activerecord-2.3.11/lib/active_record/named_scope.rb:114:in `type'
from /home/brafales/.rvm/gems/ree-1.8.7-2011.03@comradio/gems/activerecord-2.3.11/lib/active_record/named_scope.rb:114:in `__send__'
from /home/brafales/.rvm/gems/ree-1.8.7-2011.03@comradio/gems/activerecord-2.3.11/lib/active_record/named_scope.rb:114:in `type'
from (irb):2
Note that evaluating the type filter the first one will give no problems since will actually call the name scope:
ree-1.8.7-2011.03 :003 > Asset.type("5").visibility("Public")
Asset Load (1.0ms) SELECT * FROM "assets" WHERE (("assets"."type" = 'AssetPublic') AND (asset_type_id IN (5)))
=> [#<AssetPublic id: 3, name: "Spotify", description: "", asset_type_id: 5, resource_file_name: "Spotify_Icon_set_by_91maan90.png", resource_file_size: 5994, resource_content_type: "image/png", type: "AssetPublic", is_protected: false, created_at: "2012-02-02 13:44:47", updated_at: "2012-02-02 13:44:47", keep_backup: true, station_id: nil>, #<AssetPublic id: 1, name: "Ender", description: nil, asset_type_id: 5, resource_file_name: "enders_game.jpg", resource_file_size: 23105, resource_content_type: "image/jpeg", type: "AssetPublic", is_protected: false, created_at: "2012-02-01 09:32:04", updated_at: "2012-02-01 09:32:04", keep_backup: true, station_id: nil>]
This has happened using Rails 2.3.11 and Ruby Enterprise Edition 1.8.7 (ruby 1.8.7 (2011-02-18 patchlevel 334) [i686-linux], MBARI 0x8770, Ruby Enterprise Edition 2011.03)
Somehow, in my environment the type filter is not evaluated the first one and fails, but in other environments this will work just fine. I guess this has to do with the order ruby uses to iterate over a hash.
I'd appreciate if some of the more Ubiquo experienced guys could help me with that, if this can be confirmed as a bug or not, and how could we solve it without too much of a hassle.
In the end I guess that having a named_scope called type is not a good idea.
Cheers!
--
Bernat Ràfales
braf...@gnuine.com
gnuine
www.gnuine.com
C/ Pamplona, 96
Local 17
22@ - 08018 Barcelona
Tel: +34.93.567.94.94
Fax: +34.93.567.94.95