Hobo Scopes _contains

52 views
Skip to first unread message

Jim Harvey

unread,
Sep 8, 2011, 2:28:53 PM9/8/11
to hobo...@googlegroups.com
I'm getting what is, for me, unexpected behavior using scopes and I'm not sure if its a bug or what I need to do to resolve it. I have the following in a few of my controllers:

def index

Jim Harvey

unread,
Sep 8, 2011, 2:33:57 PM9/8/11
to hobo...@googlegroups.com
(didn't mean to post yet - here is the continuation)

def index
  hobo_index Model.apply_scopes(
     :name_contains => params[:q]
  )
  ...
end

This works just fine if the query string is anywhere in the name EXCEPT the beginning. For example, "mat" as the query string will not receive a record with the name "Math". Is this the desired behavior? I know there is a _starts scope but I can't chain them together as far as I can tell because then only records that match both conditions will be retrieved. Is there a way use OR logic instead? Any insight is, as usual, greatly appreciated. Thanks!

kevinpfromnm

unread,
Sep 8, 2011, 2:43:22 PM9/8/11
to hobo...@googlegroups.com
is it the beginning part or is it case sensitive?  most db that will match except postgres which won't be because of the different case.  I just tried this in an rails3 branch (edge) and had it work for User.name_contains "k" so if it's not case sensitivity might help if you post the version of hobo you're using.

Jim Harvey

unread,
Sep 8, 2011, 3:40:12 PM9/8/11
to hobo...@googlegroups.com
Good point, Kevin. It is indeed a case sensitive issue with postgres. Is there any way I can set a case insensitive flag at the "hobo level"? The data itself is mixed case and I would like to continue using apply_scopes if I can...

Matt Jones

unread,
Sep 8, 2011, 4:52:04 PM9/8/11
to hobo...@googlegroups.com

On Sep 8, 2011, at 3:40 PM, Jim Harvey wrote:

> Good point, Kevin. It is indeed a case sensitive issue with postgres. Is there any way I can set a case insensitive flag at the "hobo level"? The data itself is mixed case and I would like to continue using apply_scopes if I can...

Not at present. You can use apply_scopes with any scope, though - so you could define one for your case (in model.rb):

scope :name_icontains, lambda { |x| where(['name LIKE ?', "%#{x}%"]) }

(this is the Rails 3 flavor)

As an alternative, you could use the auto-generated search scope, which may (depending on your application) be better anyways:

Model.apply_scopes(:search => [params[:q], :name])

The search scope does some additional processing to make searches more intuitive in most cases:

- splits the query on spaces and looks for each word individually. This matches records that contain the search terms with intervening text.

- if you pass more than one field, constructs a query that allows any record that has the search terms in any combination of fields. For instance, if you've got records with a 'name' and a 'description' field then this:

Model.search('foo bar', :name, :description)

will match a record with 'foo' in the name and 'bar' in the description.

As to the larger question, I'm not 100% sure what the best approach is. Off the top of my head, here are some possibilities:

- add a global configuration option to switch 'LIKE' to 'ILIKE' in generated scopes. Probably a really bad idea.

- add a model-level configuration option: better, since some models might prefer case-sensitive comparison vs. others.

- add a *field*-level configuration option: this is much chattier than the previous, but would be the most powerful. Essentially, you'd add an :ignore_case => true flag to the field declaration. Also possibly useful in dealing with :unique validation.

I have to admit, I don't really have much of a perspective on this - most of my development work has been on MySQL, where the case-sensitivity issue is (for better or for worse) totally absent. Any Postgres, etc. users want to weigh in?

--Matt Jones

kevinpfromnm

unread,
Sep 8, 2011, 4:52:55 PM9/8/11
to hobo...@googlegroups.com
You can define your own scope.

          named_scope :name_contains, lambda { |str|
            { :conditions => ["table_name.name ILIKE ?", "%#{str}%"] }
          }

To get case insensitive with postgres it's ILIKE instead of like.  Depending on whether you need to worry about multiple db support you might want to make that conditional so it doesn't break if someone if used with another db.  Warning, above code is untested and based on the hobo automatic scope to boot.

kevinpfromnm

unread,
Sep 8, 2011, 4:59:44 PM9/8/11
to hobo...@googlegroups.com
I'm half tempted to say we should make case insensitive the effective default in postgres as it would be a more consistent experience at least.  Given common pattern of dev with sqlite and deploy to heroku (postgres) it would avoid some of these sticking points.


Jim Harvey

unread,
Sep 8, 2011, 5:30:29 PM9/8/11
to hobo...@googlegroups.com
@Matt, @kevin - thanks for the feedback! really really helpful. You saved me from adding another field to store a lowercase name, which I was about to do and which would have been a *really* hacky mess. Custom scopes are great now I realize that I can do that (even though I've read the docs, it didn't sink in.) However, in this case, the search scope works perfectly. 

As far as configuration options, I would argue for field-level since it provides the most flexibility. I can see Kevin's point about the common sqlite to heroku dev pattern but I'm not sure you'd want to override behavior that might be expected by experienced postgres users. 

tonym

unread,
Dec 11, 2012, 4:20:35 PM12/11/12
to hobo...@googlegroups.com

Trying to find a neat solution for this myself. Post is a year old, but I think it's still very relevant.  Currently I'm having to build scopes for what should really be the norm.
I think a default of case insensitive makes perfect sense - that's the way it is for MYSQL, so having a simple config switch would stop a lot of headaches for Heroku users and still make it possible to switch off if someone wants case sensitive (though I can't see a situation where you'd want to globally be case sensitive with searches, they would be one off specifics only in reality).  Could we get this in to v2.0pre....?

Anthony.

Owen Dall

unread,
Dec 11, 2012, 7:42:08 PM12/11/12
to hobo...@googlegroups.com
I agree with making case insensitive the default.  Will save a lot of headaches....

On Thu, Sep 8, 2011 at 4:59 PM, kevinpfromnm <kevinp...@gmail.com> wrote:
I'm half tempted to say we should make case insensitive the effective default in postgres as it would be a more consistent experience at least.  Given common pattern of dev with sqlite and deploy to heroku (postgres) it would avoid some of these sticking points.



--
You received this message because you are subscribed to the Google Groups "Hobo Users" group.
To view this discussion on the web visit https://groups.google.com/d/msg/hobousers/-/sKR3-TdzBzUJ.

To post to this group, send email to hobo...@googlegroups.com.
To unsubscribe from this group, send email to hobousers+...@googlegroups.com.
For more options, visit this group at http://groups.google.com/group/hobousers?hl=en.



--
-Owen
 

Owen Dall

Vice President | Chief Technology Officer

Barquin International 

www.barquin.com

Office: 202.296.7147 | Mobile: tel:410.991.0811

Fax: 202.296.8903 | email: od...@barquin.com


Bryan Larsen

unread,
Dec 12, 2012, 4:37:30 AM12/12/12
to hobo...@googlegroups.com
given that we already adjust for case sensitivity for the search
scope, it seems reasonable to do so for our other automatic scopes.

https://github.com/Hobo/hobo/commit/d49ae630bdd631145e0bcc47265b7849e783a924

Bryan
Reply all
Reply to author
Forward
0 new messages