Possible problem with Asset class having a named_scope called type?

6 views
Skip to first unread message

Bernat Ràfales

unread,
Feb 2, 2012, 10:03:17 AM2/2/12
to ubiquo...@googlegroups.com
Hello people,
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.
The problem comes when you try to do a filtered_search in the Asset class. The used URL looks like this one: http://localhost:3000/ubiquo/assets?filter_text=e&filter_type=5&filter_visibility=public&filter_created_start=&filter_created_end=

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

Bernat Foj Capell

unread,
Feb 9, 2012, 3:10:34 AM2/9/12
to ubiquo...@googlegroups.com
Hi,

As you said, what should be done here is to rename the named scope, as
this name causes a conflict.

Regarding the env, it could be anything, from the ruby version to the
browser. But obviously this should work independently of this.

Cheers,
Bernat

> --
> Heu rebut aquest missatge perquè esteu subscrit al grup "ubiquo" de Google
> Grups.
> Per publicar a aquest grup, envieu un correu electrònic a
> ubiquo...@googlegroups.com.
> Per anul·lar la subscripció a aquest grup, envieu un correu electrònic a
> ubiquo-gnuin...@googlegroups.com.
> Per obtenir més opcions, visiteu aquest grup a
> http://groups.google.com/group/ubiquo-gnuine?hl=ca.

--
Bernat Foj Capell
bf...@gnuine.com

Reply all
Reply to author
Forward
0 new messages