Git Product home page Git Product logo

searchlogic's Introduction

Searchlogic

Searchlogic makes using ActiveRecord named scopes easier and less repetitive. It helps keep your code DRY, clean, and simple.

The specs pass with ActiveRecord 2.3.9 - 2.3.14 on Ruby 1.9.3-p125, 1.9.2-p318, and 1.8.7-p358

Before contacting me directly, please read:

If you find a bug or a problem please post it in the issues section. If you need help with something, please use google groups. I check both regularly and get emails when anything happens, so that is the best place to get help. This also benefits other people in the future with the same questions / problems. Thank you.

Install & use

Install the gem from rubyforge:

sudo gem install searchlogic

Now just set it as a dependency in your project and you are ready to go.

You can also install this as a plugin:

script/plugin install git://github.com/binarylogic/searchlogic.git

See below for usage examples.

Search using conditions on columns

Instead of explaining what Searchlogic can do, let me show you. Let’s start at the top:

# We have the following model
User(id: integer, created_at: datetime, username: string, age: integer)

# Searchlogic gives you a bunch of named scopes for free:
User.username_equals("bjohnson")
User.username_equals(["bjohnson", "thunt"])
User.username_equals("a".."b")
User.username_does_not_equal("bjohnson")
User.username_begins_with("bjohnson")
User.username_not_begin_with("bjohnson")
User.username_like("bjohnson")
User.username_not_like("bjohnson")
User.username_ends_with("bjohnson")
User.username_not_end_with("bjohnson")
User.age_greater_than(20)
User.age_greater_than_or_equal_to(20)
User.age_less_than(20)
User.age_less_than_or_equal_to(20)
User.username_null
User.username_not_null
User.username_blank

Any named scope Searchlogic creates is dynamic and created via method_missing. Meaning it will only create what you need. Also, keep in mind, these are just named scopes, you can chain them, call methods off of them, etc:

scope = User.username_like("bjohnson").age_greater_than(20).id_less_than(55)
scope.all
scope.first
scope.count
# etc...

For a complete list of conditions please see the constants in Searchlogic::NamedScopes::Conditions.

Use condition aliases

Typing out ‘greater_than_or_equal_to’ is not fun. Instead Searchlogic provides various aliases for the conditions. For a complete list please see Searchlogic::NamedScopes::Conditions. But they are pretty straightforward:

User.username_is(10)  # equals
User.username_eq(10)  # equals
User.id_lt(10)        # less than
User.id_lte(10)       # less than or equal to
User.id_gt(10)        # greater than
User.id_gte(10)       # greater than or equal to
# etc...

Search using scopes in associated classes

This is my favorite part of Searchlogic. You can dynamically call scopes on associated classes and Searchlogic will take care of creating the necessary joins for you. This is REALY nice for keeping your code DRY. The best way to explain this is to show you:

Searchlogic provided scopes

Let’s take some basic scopes that Searchlogic provides for every model:

# We have the following relationships
User.has_many :orders
Order.has_many :line_items
LineItem

# Set conditions on association columns
User.orders_total_greater_than(20)
User.orders_line_items_price_greater_than(20)

# Order by association columns
User.ascend_by_order_total
User.descend_by_orders_line_items_price

This is recursive, you can travel through your associations simply by typing it in the name of the method. Again these are just named scopes. You can chain them together, call methods off of them, etc.

Custom associated scopes

Also, these conditions aren’t limited to the scopes Searchlogic provides. You can use your own scopes. Like this:

LineItem.named_scope :expensive, :conditions => "line_items.price > 500"

User.orders_line_items_expensive

As I stated above, Searchlogic will take care of creating the necessary joins for you. This is REALLY nice when trying to keep your code DRY, because if you wanted to use a scope like this in your User model you would have to copy over the conditions. Now you have 2 named scopes that are essentially doing the same thing. Why do that when you can dynamically access that scope using this feature?

Polymorphic associations

Polymorphic associations are tough because ActiveRecord doesn’t support them with the :joins or :include options. Searchlogic checks for a specific syntax and takes care of this for you. Ex:

Audit.belongs_to :auditable, :polymorphic => true
User.has_many :audits, :as => :auditable

Audit.auditable_user_type_username_equals("ben")

The above will take care of creating the inner join on the polymorphic association so that it only looks for type ‘User’. On the surface it works the same as a non polymorphic association. The syntax difference being that you need to call the association and then specify the type:

[polymorphic association name]_[association type]_type

Uses :joins not :include

Another thing to note is that the joins created by Searchlogic do NOT use the :include option, making them much faster. Instead they leverage the :joins option, which is great for performance. To prove my point here is a quick benchmark from an application I am working on:

Benchmark.bm do |x|
  x.report { 10.times { Event.tickets_id_gt(10).all(:include => :tickets) } }
  x.report { 10.times { Event.tickets_id_gt(10).all } }
end
      user     system      total        real
 10.120000   0.170000  10.290000 ( 12.625521)
  2.630000   0.050000   2.680000 (  3.313754)

If you want to use the :include option, just specify it:

User.orders_line_items_price_greater_than(20).all(:include => {:orders => :line_items})

Obviously, only do this if you want to actually use the included objects. Including objects into a query can be helpful with performance, especially when solving an N+1 query problem.

Order your search

Just like the various conditions, Searchlogic gives you some very basic scopes for ordering your data:

User.ascend_by_id
User.descend_by_id
User.ascend_by_orders_line_items_price
# etc...

Use any or all

Every condition you’ve seen in this readme also has 2 related conditions that you can use. Example:

User.username_like_any("bjohnson", "thunt")   # will return any users that have either of the strings in their username
User.username_like_all("bjohnson", "thunt")   # will return any users that have all of the strings in their username
User.username_like_any(["bjohnson", "thunt"]) # also accepts an array

This is great for checkbox filters, etc. Where you can pass an array right from your form to this condition.

Combine scopes with ‘OR’

In the same fashion that Searchlogic provides a tool for accessing scopes in associated classes, it also provides a tool for combining scopes with ‘OR’. As we all know, when scopes are combined they are joined with ‘AND’, but sometimes you need to combine scopes with ‘OR’. Searchlogic solves this problem:

User.username_or_first_name_like("ben")
=> "username LIKE '%ben%' OR first_name like'%ben%'"

User.id_or_age_lt_or_username_or_first_name_begins_with(10)
=> "id < 10 OR age < 10 OR username LIKE 'ben%' OR first_name like'ben%'"

Notice you don’t have to specify the explicit condition (like, gt, lt, begins with, etc.). You just need to eventually specify it. If you specify a column it will just use the next condition specified. So instead of:

User.username_like_or_first_name_like("ben")

You can do:

User.username_or_first_name_like("ben")

Again, these just map to named scopes. Use Searchlogic’s dynamic scopes, use scopes on associations, use your own custom scopes. As long as it maps to a named scope it will join the conditions with ‘OR’. There are no limitations.

Create scope procedures

Sometimes you notice a pattern in your application where you are constantly combining certain named scopes. You want to keep the flexibility of being able to mix and match small named scopes, while at the same time being able to call a single scope for a common task. User searchlogic’s scpe procedure:

User.scope_procedure :awesome, lambda { first_name_begins_with("ben").last_name_begins_with("johnson").website_equals("binarylogic.com") }

All that this is doing is creating a class level method, but what is nice about this method is that is more inline with your other named scopes. It also tells searchlogic that this method is ‘safe’ to use when using the search method. Ex:

User.search(:awesome => true)

Otherwise searchlogic will ignore the ‘awesome’ condition because there is no way to tell that its a valid scope. This is a security measure to keep users from passing in a scope with a named like ‘destroy_all’.

Make searching and ordering data in your application trivial

The above is great, but what about tying all of this in with a search form in your application? What would be really nice is if we could use an object that represented a single search. Like this…

search = User.search(:username_like => "bjohnson", :age_less_than => 20)
search.all

The above is equivalent to:

User.username_like("bjohnson").age_less_than(20).all

You can set, read, and chain conditions off of your search too:

search.username_like                              => "bjohnson"
search.age_gt = 2                                 => 2
search.id_gt(10).email_begins_with("bjohnson")    => <#Searchlogic::Search...>
search.all                                        => An array of users
search.count                                      => integer
# .. etc

So let’s start with the controller…

Your controller

The search class just chains named scopes together for you. What’s so great about that? It keeps your controllers extremely simple:

class UsersController < ApplicationController
  def index
    @search = User.search(params[:search])
    @users = @search.all
  end
end

It doesn’t get any simpler than that.

Your form

Adding a search condition is as simple as adding a condition to your form. Remember all of those named scopes above? Just create fields with the same names:

- form_for @search do |f|
  = f.text_field :username_like
  = f.select :age_greater_than, (0..100)
  = f.text_field :orders_total_greater_than
  = f.submit

When a Searchlogic::Search object is passed to form_for it will add a hidden field for the “order” condition, to preserve the order of the data.

Additional helpers

There really isn’t a big need for helpers in searchlogic, other than helping you order data. If you want to order your search with a link, just specify the name of the column. Ex:

= order @search, :by => :age
= order @search, :by => :created_at, :as => "Created date"

The first one will create a link that alternates between calling “ascend_by_age” and “descend_by_age”. If you wanted to order your data by more than just a column, create your own named scopes: “ascend_by_*” and “descend_by_*”. The “order” helper is a very straight forward helper, checkout the docs for some of the options.

This helper is just a convenience method. It’s extremely simple and there is nothing wrong with creating your own. If it doesn’t do what you want, copy the code, modify it, and create your own. You could even fork the project, modify it there, and use your own gem.

Use your existing named scopes

This is one of the big differences between Searchlogic v1 and v2. What about your existing named scopes? Let’s say you have this:

User.named_scope :four_year_olds, :conditions => {:age => 4}

Again, these are all just named scopes, use it in the same way:

User.search(:four_year_olds => true, :username_like => "bjohnson")

Notice we pass true as the value. If a named scope does not accept any parameters (arity == 0) you can simply pass it true or false. If you pass false, the named scope will be ignored. If your named scope accepts a parameter, the value will be passed right to the named scope regardless of the value.

Now just throw it in your form:

- form_for @search do |f|
  = f.text_field :username_like
  = f.check_box :four_year_olds
  = f.submit

This really allows Searchlogic to extend beyond what it provides internally. If Searchlogic doesn’t provide a named scope for that crazy edge case that you need, just create your own named scope and use it. The sky is the limit.

Pagination (leverage will_paginate)

Instead of recreating the wheel with pagination, Searchlogic works great with will_paginate. All that Searchlogic is doing is creating named scopes, and will_paginate works great with named scopes:

User.username_like("bjohnson").age_less_than(20).paginate(:page => params[:page])
User.search(:username_like => "bjohnson", :age_less_than => 20).paginate(:page => params[:page])

If you don’t like will_paginate, use another solution, or roll your own. Pagination really has nothing to do with searching, and the main goal for Searchlogic v2 was to keep it lean and simple. No reason to recreate the wheel and bloat the library.

Conflicts with other gems

You will notice searchlogic wants to create a method called “search”. So do other libraries like thinking-sphinx, etc. So searchlogic has a no conflict resolution. If the “search” method is already taken the method will be called “searchlogic” instead. So instead of

User.search

You would do:

User.searchlogic

Under the hood

Before I use a library in my application I like to glance at the source and try to at least understand the basics of how it works. If you are like me, a nice little explanation from the author is always helpful:

Searchlogic utilizes method_missing to create all of these named scopes. When it hits method_missing it creates a named scope to ensure it will never hit method missing for that named scope again. Sort of a caching mechanism. It works in the same fashion as ActiveRecord’s “find_by_*” methods. This way only the named scopes you need are created and nothing more.

The search object is just a proxy to your model that only delegates calls that map to named scopes and nothing more. This is obviously done for security reasons. It also helps make form integration easier, by type casting values, and playing nice with form_for. This class is pretty simple as well.

That’s about it, the named scope options are pretty bare bones and created just like you would manually.

Credit

Thanks a lot to Tyler Hunt for helping plan, design, and start the project. He was a big help.

Copyright © 2009 Ben Johnson of Binary Logic, released under the MIT license

searchlogic's People

Contributors

ak47 avatar bernd avatar binarylogic avatar gfguthrie avatar hlubek avatar isc avatar jana4u avatar jcredding avatar jhchabran avatar johndouthat avatar laserlemon avatar namxam avatar nandalopes avatar newellista avatar reddavis avatar retoo avatar rubysolo avatar schof avatar tadman avatar vandrijevik avatar vidmantas avatar zachinglis avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

searchlogic's Issues

Simple OR conditions

It would be nice if one could do a simple OR condition like this.

Article.name_or_content_like("something")

I imagine the method_missing call could do a check for "_or_" in the name, split by it, and add a condition for each resulting attribute.

Order only check columns, why not checking additional values requested via SELECT

Hi Ben,

Looks like the order option only accept valid columns names. What about additional values requested with SELECT.

Example :

SELECT users.*, COUNT(1) as count FROM ... ORDER BY count ASC

In this case, ordering by count can be extremely useful but doesn't look supported right now.

As quick workaround creating the named "scope ascend_by_count" and "descend_by_count" makes the job but still overload your models far to quick while adding such feature to searchlogic would keep things light and clean.

Thanks again for this great lib and excellent rewrite,

Warm regards,

Sebastien Grosjean - ZenCocoon

Modifiers not working

The change log states that modifiers were added quite a while ago. However, I can't seem to use them. I keep getting errors like: "The lower_of_first_name_eq is not a valid condition. You may only use conditions that map to a named scope"

Are modifiers available in the latest release?

Reverse named_scopes not only for just equal

It would be very cool to also have "reverse" named_scope for all conditions, not only equal.

For example :

  User.username_not_blank
  User.username_not_empty
  User.username_does_not_end_with("bjohnson")
  User.username_does_not_begin_with("bjohnson")

and so on...

I may try to help for this :).

Nicolas

Equality Checks not Working

For some reason, when I try to do an _is(#) or _equals(#) or _eq(#), I always get an error about there being the wrong number of arguments.

Table:

Workflow(id: integer, created_by: integer, held_by: integer, prefix: integer, project_id: integer, form_id: integer,
fields: text, subject: string, priority: integer, status: integer, due_date: datetime, created_at: datetime, updated_at:
 datetime)

Records:

+----+--------+--------+--------+--------+--------+--------+--------+--------+--------+--------+--------+--------+
| id | cre... | hel... | prefix | pro... | for... | fields | sub... | pri... | status | due... | cre... | upd... |
+----+--------+--------+--------+--------+--------+--------+--------+--------+--------+--------+--------+--------+
| 4  | 1      | 1      | 0      | 3      | 9      | 28d... |        | 2      | 0      |        | 200... | 200... |
| 5  | 1      | 1      | 0      | 2      | 7      |        |        | 2      | 0      |        | 200... | 200... |
+----+--------+--------+--------+--------+--------+--------+--------+--------+--------+--------+--------+--------+

Trying to execute Workflow.status_is(0) results in:

ArgumentError: wrong number of arguments (2 for 1)
        from C:/Ruby/lib/ruby/gems/1.8/gems/searchlogic-2.3.5/lib/searchlogic/named_scopes/conditions.rb:93:in `attribut
e_condition'
        from C:/Ruby/lib/ruby/gems/1.8/gems/searchlogic-2.3.5/lib/searchlogic/named_scopes/conditions.rb:93:in `create_p
rimary_condition'
        from C:/Ruby/lib/ruby/gems/1.8/gems/searchlogic-2.3.5/lib/searchlogic/named_scopes/conditions.rb:151:in `call'
        from C:/Ruby/lib/ruby/gems/1.8/gems/searchlogic-2.3.5/lib/searchlogic/named_scopes/conditions.rb:151:in `scope_o
ptions'
        from C:/Ruby/lib/ruby/gems/1.8/gems/activerecord-2.2.2/lib/active_record/named_scope.rb:91:in `call'
        from C:/Ruby/lib/ruby/gems/1.8/gems/activerecord-2.2.2/lib/active_record/named_scope.rb:91:in `named_scope'
        from C:/Ruby/lib/ruby/gems/1.8/gems/activerecord-2.2.2/lib/active_record/named_scope.rb:96:in `call'
        from C:/Ruby/lib/ruby/gems/1.8/gems/activerecord-2.2.2/lib/active_record/named_scope.rb:96:in `status_equals'
        from C:/Ruby/lib/ruby/gems/1.8/gems/searchlogic-2.3.5/lib/searchlogic/named_scopes/conditions.rb:175:in `send'
        from C:/Ruby/lib/ruby/gems/1.8/gems/searchlogic-2.3.5/lib/searchlogic/named_scopes/conditions.rb:175:in `create_
alias_condition'
        from C:/Ruby/lib/ruby/gems/1.8/gems/searchlogic-2.3.5/lib/searchlogic/named_scopes/conditions.rb:83:in `create_c
ondition'
        from C:/Ruby/lib/ruby/gems/1.8/gems/searchlogic-2.3.5/lib/searchlogic/named_scopes/conditions.rb:66:in `method_m
issing'
        from C:/Ruby/lib/ruby/gems/1.8/gems/searchlogic-2.3.5/lib/searchlogic/named_scopes/association_conditions.rb:19:
in `method_missing'
        from C:/Ruby/lib/ruby/gems/1.8/gems/searchlogic-2.3.5/lib/searchlogic/named_scopes/association_ordering.rb:27:in
 `method_missing'
        from C:/Ruby/lib/ruby/gems/1.8/gems/searchlogic-2.3.5/lib/searchlogic/named_scopes/ordering.rb:30:in `method_mis
sing'
        from C:/Ruby/lib/ruby/gems/1.8/gems/searchlogic-2.3.5/lib/searchlogic/named_scopes/or_conditions.rb:24:in `metho
d_missing'
        from C:/Ruby/lib/ruby/gems/1.8/gems/activerecord-2.2.2/lib/active_record/base.rb:1833:in `method_missing'
        from (irb):11

Array and Range scope values

I love searchlogic, but it leaves out conditions with Array or Range values. For instance, a named scope may look like:

class State < ActiveRecord::Base
  named_scope :by_abbreviation, lambda{|a| {:conditions => {:abbreviation => a}} }
end

One could pass a number of different types of arguments to such a scope:

State.by_abbreviation('MI')
State.by_abbreviation(['MI', 'WA'])
State.by_abbreviation('MA'..'MZ')

These produce the following queries, respectively:

SELECT * FROM `states` WHERE (`states`.`abbreviation` = 'MI')
SELECT * FROM `states` WHERE (`states`.`abbreviation` IN ('MI','WA'))
SELECT * FROM `states` WHERE (`states`.`abbreviation` BETWEEN 'MA' AND 'MZ')

Could these sorts of scopes be built into searchlogic, using "in" and "between" shorthand in the scope names?

Association chains that mention the same table twice produce incorrect results

For the example, take the following schema:

Product: id
ProductCategory: id, product_id, category_id
Category: id

Rows: You have one product in multiple categories
Product id: 1

ProductCategory id: 1, category_id: 1, product_id: 1
ProductCategory id: 2, category_id: 2, product_id: 1

Category id: 1
Category id: 2

Say you want to find all categories that contain a product which is also in category X.

The following scope returns 2 copies of category 1, since the where sql references the wrong product_categories table. It should return categories 1 and 2

Category.product_categories_product_product_categories_category_id_equals(1)

SELECT categories.* FROM categories
INNER JOIN product_categories ON product_categories.category_id = categories.id
INNER JOIN products ON products.id = product_categories.product_id
INNER JOIN product_categories product_categories_products ON product_categories_products.product_id = products.id
WHERE (product_categories.category_id = 235)

Double JOIN with order

I guess the example below will speak on it's own :

named_scope :select_with_authors,
:joins => "LEFT OUTER JOIN authors ON authors.id = posts.author_id"

Post.select_with_authors.descend_by_author_name
ActiveRecord::StatementInvalid: Mysql::Error: Not unique table/alias: 'authors': SELECT posts.* FROM posts INNER JOIN authors ON authors.id = posts.author_id LEFT OUTER JOIN authors ON authors.id = posts.author_id ORDER BY authors.name DESC

Please let me know if you like further details.

searchlogic :order => 'ascend_by_id' throws Errors when having a named_scope :order in the model

Having a named_scope :order (for the obvious reason of ordering) in a model, searchlogic ordering won't work anymore.

class Blog < ActiveRecord::Base
named_scope :order, lambda {|order| {:order => order}}
end

Blog.searchlogic(:order => "ascend_by_id")
results in:
ActiveRecord::StatementInvalid: Mysql::Error: Unknown column 'ascend_by_id' in 'order clause': SELECT * FROM blogs ORDER BY ascend_by_id DESC LIMIT 1

must have something to do with the def scope? method in search.rb

cheers

#search ignores :order argument on associations which have an order defined

Consider a class Foo, with associated Bars:

@@@ ruby
class Foo < ActiveRecord::Base
has_many :bars, :order => :name
end
@@@

If you do:

@@@ ruby
Foo.bars.search(:order => "ascend_by_size").all
@@@

The results are still sorted by :name -- i.e. the "ascend_by_size" :order argument to the #search method is ignored.

The SQL query looks like:

@@@ sql
SELECT * FROM bars WHERE bars.foo_id = 1 ORDER BY bars.name;
@@@

Is this a bug?

original LH ticket

This ticket has 0 attachment(s).

Limit option?

>> Track.descend_by_updated_at.limit(20)
undefined method `limit' for #<Class:0x00000102685488>

It seems like a logical method. Hopefully you agree.

Range values clobbered by search method

Typecasting Range values isn't working and although Ranges aren't typically passed into the arguments for the search method, it's certainly not impossible (as I found out). The individual scopes work correctly, but when accessed through the search method, they fall apart. I've forked the repo, added a failing test and presented a solution.

http://github.com/laserlemon/searchlogic

ISSUE, table name specified more than once

ERROR MESSAGE: "ActiveRecord::StatementInvalid (PGError: ERROR: table name "tender_flags" specified more than once"

I am using a join with one table and as I use order by with that table it gives this error
Also any association based sorting by default use INNER JOIN but in my scenario I require LEFT JOIN any suggestion for getting through that issue. thanks.

Inconsistent result of "order" method

Please have a look at this:

@@@ ruby

Document.search("descend_by_datetime" => true).order
=> nil

Document.search(:order => "descend_by_datetime").order
=> "descend_by_datetime"

Document.search(:order => "datetime DESC").order
=> "datetime DESC"
@@@

IMHO the "order" method should always return the same result.

original LH ticket

This ticket has 0 attachment(s).

Only works when config.cache_classes = false

I love search logic, but cannot get it to run in production mode. I found out that the cache_classes setting was the culprit. I know searchlogic works dynamically, but is there a way to enable searchlogic with class_caching?

When the classes are not cached I get:
undefined method cached_tags_contains' for #<Array:0x4e064c0> or undefined methodid_contains' for #Array:0x4e064c0

respond_to? :paginate returns false

For some reason Searchlogic::Search.respond_to?(:paginate) returns false, even though you can call paginate on it.

This was messing up Hobo, so I monkey patched it:
class Searchlogic::Search
def respond_to?(symbol)
return true if symbol === :paginate
old_respond_to? symbol
end
end

Existing named scopes are ignored

An existing named scope that shares its name with one of the model's columns is ignored when accessed via the search method. The normalize_scope_name method appends "_equals" with no regard for whether the scope already exists. I've forked the repo, added a failing test and presented a solution.

http://github.com/laserlemon/searchlogic

date_select not working

I found some old issues, concerning the date_select helper. It looks like there should be support to use this helper in combination with searchlogic.

But when I use <%= f.date_select :start_after, :include_blank => true %> it fails with
"The is not a valid condition. You may only use conditions that map to a named scope"

Multiple record copies returned for habtm association

I committed a test case that reproduces the problem in http://github.com/infrared/searchlogic/commit/34d3b89122812df2b4fa9a0c8339674ecf25f206

When you have two models joined with has_and_belongs_to_many and you search one of them with something like:

FirstModel.search(:second_models_id_equals_any => [1, 2]).all

multiple copies of the same FirstModel record will be returned if a the record happens to be associated with more than one SecondModels.

not_group support

hey,

is something like a ’not_group’ available within searchlogic (or in combination with ActiveRecord)?

e.g.:
s=System.new_search
=> #<SystemSearch {:limit=>25}>

g=s.conditions.not_group
=> #
g.name_equals="test"
=> "test"
g.descr_equals="test"
=> "test"
s.count
=> 95

generated sql:
SQL (0.5ms) SELECT count("systems".id) AS count_id FROM "systems" WHERE (NOT (("systems"."name" = ’test’ AND "systems"."descr" = ’test’)))

original LH ticket

This ticket has 0 attachment(s).

Problem with "OR" named_scopes in forms

It seems its not working from the form:

- form_for @search do |f|
  %p
    = f.text_field :name_or_description_like
    = f.submit "Search"

It works from the console, using Report.name_or_description_like but when I use it in the form I just get a "false" result in the text field, and no filters are applied (I checked the logs).

Let me know if you need any more info (I'm using the latest version of searchlogic and rails 2.3.2).

I also run a test creating a new rails app from scratch with rails 2.3.3 and exactly the same happens, it doesn't get filtered and it shows a "false" string in the form (as a response).

Thanks a lot for a great plugin!

searchlogic uses NULL value on search by date (created_at_gte)

Doing a simple search on the created_at column will produce SQL that has a NULL value for the date.

In the form, I input in ISO date format (YYYY-MM-DD), and the values shows in the params in the logs:

Parameters: {"commit"=>"Search", "action"=>"index", "controller"=>"foos", "search"=>{"city_like"=>"", "created_at_gte"=>"2009-04-13"}}

But the resulting SQL gives a NULL for the date:

SELECT * FROM "foos" WHERE (foos.created_at >= NULL)

order Helper doesn't honor existing search params

Changing the end of order() to something like the following will work:

new_params = params[options[:params_scope]].merge({:order => new_scope})
link_to options[:as], url_for(options[:params_scope] => new_params), html_options

It worked for my simple app, not sure if its a comprehensive solution, though.

Sorting on a single table Help

I tried out using the example code on my controller i.e @search = new_search(params[:search]) and I am able to sort and view pages in 10, 25 etc.. However, when I add conditions the data is displayed correctly but the sorting and page links don’t work. I am trying this on a single table of data. Your comments and advised would be helpful.

original LH ticket

This ticket has 0 attachment(s).

Exception "undefined method `call' for nil:NilClass"

Hi,

I had a weird exception on my production server when using a Searchlogic named_scope, here is
the code :

def index
  @products = Product.available.ascend_by_position.all
  # ... 
end

available is a regular named_scope and ascend_by_position is a Searchlogic named_scope on the position column.

The exception :

Error Message:
--------------
NoMethodError: undefined method `call' for nil:NilClass

Where:
------
orders#index
[GEM_ROOT]/gems/activerecord-2.3.4/lib/active_record/named_scope.rb, line 97

Backtrace:
----------
[GEM_ROOT]/gems/activerecord-2.3.4/lib/active_record/named_scope.rb:97:in `ascend_by_position'
[GEM_ROOT]/gems/activerecord-2.3.4/lib/active_record/named_scope.rb:181:in `send'
[GEM_ROOT]/gems/activerecord-2.3.4/lib/active_record/named_scope.rb:181:in `method_missing'
[GEM_ROOT]/gems/activerecord-2.3.4/lib/active_record/base.rb:2143:in `with_scope'
[GEM_ROOT]/gems/activerecord-2.3.4/lib/active_record/named_scope.rb:113:in `__send__'
[GEM_ROOT]/gems/activerecord-2.3.4/lib/active_record/named_scope.rb:113:in `with_scope'
[GEM_ROOT]/gems/activerecord-2.3.4/lib/active_record/named_scope.rb:174:in `method_missing'
[RAILS_ROOT]/app/controllers/orders_controller.rb:4:in `index'
[GEM_ROOT]/gems/actionpack-2.3.4/lib/action_controller/base.rb:1331:in `send'
[GEM_ROOT]/gems/actionpack-2.3.4/lib/action_controller/base.rb:1331:in `perform_action_without_filters'
[GEM_ROOT]/gems/actionpack-2.3.4/lib/action_controller/filters.rb:617:in `call_filters'
[GEM_ROOT]/gems/actionpack-2.3.4/lib/action_controller/filters.rb:610:in `perform_action_without_benchmark'
[GEM_ROOT]/gems/actionpack-2.3.4/lib/action_controller/benchmarking.rb:68:in `perform_action_without_rescue'
[GEM_ROOT]/gems/activesupport-2.3.4/lib/active_support/core_ext/benchmark.rb:17:in `ms'
[GEM_ROOT]/gems/activesupport-2.3.4/lib/active_support/core_ext/benchmark.rb:10:in `realtime'
[GEM_ROOT]/gems/activesupport-2.3.4/lib/active_support/core_ext/benchmark.rb:17:in `ms'
[GEM_ROOT]/gems/actionpack-2.3.4/lib/action_controller/benchmarking.rb:68:in `perform_action_without_rescue'
[GEM_ROOT]/gems/actionpack-2.3.4/lib/action_controller/rescue.rb:160:in `perform_action_without_flash'
[GEM_ROOT]/gems/actionpack-2.3.4/lib/action_controller/flash.rb:146:in `perform_action'
[GEM_ROOT]/gems/actionpack-2.3.4/lib/action_controller/base.rb:532:in `send'
[GEM_ROOT]/gems/actionpack-2.3.4/lib/action_controller/base.rb:532:in `process_without_filters'
[GEM_ROOT]/gems/actionpack-2.3.4/lib/action_controller/filters.rb:606:in `sass_old_process'
[GEM_ROOT]/gems/haml-2.2.3/rails/../lib/sass/plugin/rails.rb:19:in `process'
[GEM_ROOT]/gems/actionpack-2.3.4/lib/action_controller/base.rb:391:in `process'
[GEM_ROOT]/gems/actionpack-2.3.4/lib/action_controller/base.rb:386:in `call'
[GEM_ROOT]/gems/actionpack-2.3.4/lib/action_controller/routing/route_set.rb:437:in `call'
[GEM_ROOT]/gems/actionpack-2.3.4/lib/action_controller/dispatcher.rb:87:in `dispatch'
[GEM_ROOT]/gems/actionpack-2.3.4/lib/action_controller/dispatcher.rb:121:in `_call'
[GEM_ROOT]/gems/actionpack-2.3.4/lib/action_controller/dispatcher.rb:130:in `build_middleware_stack'
/opt/ruby-enterprise/lib/ruby/gems/1.8/gems/passenger-2.2.5/vendor/rack-1.0.0-git/lib/rack/head.rb:9:in `call'
/opt/ruby-enterprise/lib/ruby/gems/1.8/gems/passenger-2.2.5/vendor/rack-1.0.0-git/lib/rack/head.rb:9:in `call'
/opt/ruby-enterprise/lib/ruby/gems/1.8/gems/passenger-2.2.5/vendor/rack-1.0.0-git/lib/rack/methodoverride.rb:24:in `call'
[GEM_ROOT]/gems/actionpack-2.3.4/lib/action_controller/params_parser.rb:15:in `call'
[GEM_ROOT]/gems/rails-2.3.4/lib/rails/rack/metal.rb:47:in `call'
[GEM_ROOT]/gems/actionpack-2.3.4/lib/action_controller/session/abstract_store.rb:122:in `call'
[GEM_ROOT]/gems/activerecord-2.3.4/lib/active_record/query_cache.rb:29:in `call'
[GEM_ROOT]/gems/activerecord-2.3.4/lib/active_record/connection_adapters/abstract/query_cache.rb:34:in `cache'
[GEM_ROOT]/gems/activerecord-2.3.4/lib/active_record/query_cache.rb:9:in `cache'
[GEM_ROOT]/gems/activerecord-2.3.4/lib/active_record/query_cache.rb:28:in `call'
[GEM_ROOT]/gems/activerecord-2.3.4/lib/active_record/connection_adapters/abstract/connection_pool.rb:361:in `call'
[GEM_ROOT]/gems/actionpack-2.3.4/lib/action_controller/failsafe.rb:26:in `call'
/opt/ruby-enterprise/lib/ruby/gems/1.8/gems/passenger-2.2.5/vendor/rack-1.0.0-git/lib/rack/lock.rb:11:in `call'
/opt/ruby-enterprise/lib/ruby/gems/1.8/gems/passenger-2.2.5/vendor/rack-1.0.0-git/lib/rack/lock.rb:11:in `synchronize'
/opt/ruby-enterprise/lib/ruby/gems/1.8/gems/passenger-2.2.5/vendor/rack-1.0.0-git/lib/rack/lock.rb:11:in `call'
[GEM_ROOT]/gems/actionpack-2.3.4/lib/action_controller/dispatcher.rb:106:in `call'
/opt/ruby-enterprise/lib/ruby/gems/1.8/gems/passenger-2.2.5/lib/phusion_passenger/rack/request_handler.rb:95:in `process_request'
/opt/ruby-enterprise/lib/ruby/gems/1.8/gems/passenger-2.2.5/lib/phusion_passenger/abstract_request_handler.rb:207:in `main_loop'
/opt/ruby-enterprise/lib/ruby/gems/1.8/gems/passenger-2.2.5/lib/phusion_passenger/railz/application_spawner.rb:378:in `start_request_handler'
/opt/ruby-enterprise/lib/ruby/gems/1.8/gems/passenger-2.2.5/lib/phusion_passenger/railz/application_spawner.rb:336:in `handle_spawn_application'
/opt/ruby-enterprise/lib/ruby/gems/1.8/gems/passenger-2.2.5/lib/phusion_passenger/utils.rb:183:in `safe_fork'
/opt/ruby-enterprise/lib/ruby/gems/1.8/gems/passenger-2.2.5/lib/phusion_passenger/railz/application_spawner.rb:334:in `handle_spawn_application'
/opt/ruby-enterprise/lib/ruby/gems/1.8/gems/passenger-2.2.5/lib/phusion_passenger/abstract_server.rb:352:in `__send__'
/opt/ruby-enterprise/lib/ruby/gems/1.8/gems/passenger-2.2.5/lib/phusion_passenger/abstract_server.rb:352:in `main_loop'
/opt/ruby-enterprise/lib/ruby/gems/1.8/gems/passenger-2.2.5/lib/phusion_passenger/abstract_server.rb:196:in `start_synchronously'
/opt/ruby-enterprise/lib/ruby/gems/1.8/gems/passenger-2.2.5/lib/phusion_passenger/abstract_server.rb:163:in `start'
/opt/ruby-enterprise/lib/ruby/gems/1.8/gems/passenger-2.2.5/lib/phusion_passenger/railz/application_spawner.rb:213:in `start'
/opt/ruby-enterprise/lib/ruby/gems/1.8/gems/passenger-2.2.5/lib/phusion_passenger/spawn_manager.rb:262:in `spawn_rails_application'
/opt/ruby-enterprise/lib/ruby/gems/1.8/gems/passenger-2.2.5/lib/phusion_passenger/abstract_server_collection.rb:126:in `lookup_or_add'
/opt/ruby-enterprise/lib/ruby/gems/1.8/gems/passenger-2.2.5/lib/phusion_passenger/spawn_manager.rb:256:in `spawn_rails_application'
/opt/ruby-enterprise/lib/ruby/gems/1.8/gems/passenger-2.2.5/lib/phusion_passenger/abstract_server_collection.rb:80:in `synchronize'
/opt/ruby-enterprise/lib/ruby/gems/1.8/gems/passenger-2.2.5/lib/phusion_passenger/abstract_server_collection.rb:79:in `synchronize'
/opt/ruby-enterprise/lib/ruby/gems/1.8/gems/passenger-2.2.5/lib/phusion_passenger/spawn_manager.rb:255:in `spawn_rails_application'
/opt/ruby-enterprise/lib/ruby/gems/1.8/gems/passenger-2.2.5/lib/phusion_passenger/spawn_manager.rb:154:in `spawn_application'
/opt/ruby-enterprise/lib/ruby/gems/1.8/gems/passenger-2.2.5/lib/phusion_passenger/spawn_manager.rb:287:in `handle_spawn_application'
/opt/ruby-enterprise/lib/ruby/gems/1.8/gems/passenger-2.2.5/lib/phusion_passenger/abstract_server.rb:352:in `__send__'
/opt/ruby-enterprise/lib/ruby/gems/1.8/gems/passenger-2.2.5/lib/phusion_passenger/abstract_server.rb:352:in `main_loop'
/opt/ruby-enterprise/lib/ruby/gems/1.8/gems/passenger-2.2.5/lib/phusion_passenger/abstract_server.rb:196:in `start_synchronously'
/opt/ruby-enterprise/lib/ruby/gems/1.8/gems/passenger-2.2.5/bin/passenger-spawn-server:61

The weird thing is that I only had this exception on my production server, never had it on my development box.
I tried with and without the .all at the end of line without success. I had to remove the searchlogic named_scope and replace it by a regular named_scope to get rid of this exception.

scope on a column beginning with the name of an association

Giving this models :
User has_many :classifieds
Classified

User model has the column "classifieds_count".

This search throws an error, because it seems to ignore User.classifieds_count column and to search on the associated Classified model :
User.classifieds_count_greater_than(5)

Emilien

Bug: Problems with multiple scopes beginning with the same name

Please have a look at this small example:

@@@ ruby
class Contact < ActiveRecord::Base
has_many :documents, :as => :object
has_many :involvements
has_many :documents_involved, :through => :involvements, :source => :object, :source_type => ’Document’
end

Contact.search(:documents_involved_title_like => ’foo’).all

=> NoMethodError: undefined method `involved_title_like’ for #Class:...

@@@

Using Rails 2.3.3 and searchlogic plugin 2.1.13 released 2009-07-29

original LH ticket

This ticket has 0 attachment(s).

Critical Named Scope not created properly

User.id_ne(10).login_not_like("root").count
=> 2644
User.id_ne(10).login_not_like("root").count
=> 2643

this produces

SQL (1.7ms) SELECT count() AS count_all FROM users WHERE (users.login LIKE '%root%')
SQL (3.9ms) SELECT count(
) AS count_all FROM users WHERE ((users.login LIKE '%root%') AND (users.id != 10))

Searching for NOT existing associations

I'm looking for a way to use Searchlogic to find records which DON'T HAVE records for a given association. For example: "Find all Contacts which have no addresses"

class Contact < ActiveRecord::Base
  has_many :addresses
end
class Address < ActiveRecord::Base
  belongs_to :contact
end

In SQL, this query does the job:

SELECT contacts.* FROM contacts LEFT JOIN addresses ON (addresses.contact_id = contacts.id) WHERE (addresses.ID IS NULL) 

So far as I understand, Searchlogic does not support this. Of course, I can creare a named scope for this:

class Contact
  named_scope :without_addresses, :joins => 'LEFT JOIN addresses ON addresses.contact_id = contacts.id', :conditions => 'addresses.id IS NULL'
end

But I would like to have a more dynamic way, means Searchlogic creating this scope on the fly. What do you think?

parameter being converted to hash?

in the server console, parameters coming in fine:

Processing GamesController#index (for 127.0.0.1 at 2009-10-16 07:12:36) [GET]
Parameters: {"commit"=>"Submit", "search"=>{"year_ge"=>"1920", "order"=>"", "year_le"=>"2009", "segment"=>"reg"}}

but gets passed incorrectly to the scope:

NoMethodError (undefined method `year_ge' for {}:Hash):

Problem with Multiple Conditions on STI Models

The following is a result of the following example search condition

Ride.make_name_equals("Chevrolet").model_name_equals("Tahoe")

@@@ sql
SELECT count(*) AS count_all FROM rides INNER JOIN make_models ON make_models.id = rides.model_id AND (make_models.type = ’Model’ ) INNER JOIN make_models makes_rides ON makes_rides.id = rides.make_id AND (makes_rides.type = ’Make’ ) WHERE ((((rides.deleted_at IS NULL) AND (make_models.name LIKE ’%Tahoe%’)) AND (make_models.name LIKE ’%Chevrolet%’)) AND (rides.deleted_at IS NULL))
@@@

I currently have Makes and Models as subclasses to MakeModels, which is self-referential using nested_sets. So

Make has_many Models
Model belongs_to Make

Now... I don’t think this is necessarily a "bug".... but how would one go about changing this

@@@ sql
(make_models.name LIKE ’%Tahoe%’)) AND (make_models.name LIKE ’%Chevrolet%’)
@@@

to this with OR which will fix my dilemma (and hopefully any one else)

@@@ sql
(make_models.name LIKE ’%Tahoe%’)) OR (make_models.name LIKE ’%Chevrolet%’)
@@@

original LH ticket

This ticket has 0 attachment(s).

Search through association with column named "name" fails

Take the following models
Earnings: belongs_to :period
Period: has_many :earnings
if Period has a string column titled "name" the following search fails
Earnings.period_name_like("Q309") with a MySQL error that the Table/Alias periods is not unique. If I look at the generated MySQL, it creates both an inner and and outer join on the periods table against the earnings table.

If I instead call Earning.period_id_is(7) it works fine and no error is generated. The MySQL query only includes one outer join and no inner join.

Attribute with multiple parameters

Hello, here is a feature request

Using named scope like "created_at_after" with helper like "form.date_select" which produces created_at(1i), created_at(2i) ... are not handled.

@@@ html
<% form_for(@foos) do |f| %>


<%= f.label :bar_at, ’Bar at after’ %>
<%= f.date_select :bar_at_after %>

<p>
  <%#= f.label :bar_at, &rsquo;Bar at after&rsquo; %>
  <%#= f.text_field :bar_at %>
</p>

<p>
  <%= f.label :bar %>
  <%= f.text_field :bar_equals %>
</p>

<p>
  <%= f.submit :search %>
</p>

@@@

It ends in an obvious attribute(xi) not recognized. I can still used a text_field helper and pass a string as shown in the example, but that’s not always what can be expected in a search form.

It would be nice feature to have.

JH. Chabran

original LH ticket

This ticket has 0 attachment(s).

OR conditions with Search class

Could be possible to add OR support even to Search class. I would like do this
Book.search(:title_or_description_like => 'ruby')
or in chain
s = Book.search
s.title_or_description_like('ruby')

Now it produce only
s.conditions => {:title_or_description_like => false}

Thanks for wonderful work.

ascend and descend

s = Person.search
s.ascend_by_name true
s.all
| Andy
| Bob
| Charlie
. . . . .
s.descend_by_name true
s.all
| Andy
| Bob
| Charlie
. . . . .
s.ascend_by_name false
s.all
| Zita
| Yvonne
| Xaviere
. . . . .

searching boolean columns?

What is the "right" way to search on boolean columns?

>>  Invite.code_equals('F0LzDetW')
=> [#<Invite id: 29, created_at: "2009-11-14 20:53:51", updated_at: "2009-11-14 20:53:51", code: "F0LzDetW", table: nil, item: 11, accepted: nil, email: "[email protected]">]
>>  Invite.code_equals('F0LzDetW').accepted_equals(false)
=> []
>>  Invite.code_equals('F0LzDetW').accepted_equals(nil)
=> []
>>  Invite.code_equals('F0LzDetW').accepted_does_not_equal(false)
=> []
>>  Invite.code_equals('F0LzDetW').accepted_does_not_equal(nil)
=> []
>> 

Does not work with virtual attributes

Ben seems to show examples of "User.age_greater_than(20)" but age as an attribute is often used in models as a virtual attribute which calculates the current age from DOB.

When I use age as a virtual attribute and search on it, I get a "undefined method `age_greater_than' for #Class:0x48fff80"

What am I missing?

associations and arrays

if Car has_many Tires
Tire has an integer column called size

I should be able to do :
Car.tires_size_equals([4,5,6])

That fails though. I am able to do a single item though like Car.tires_size_equals(4)
Here is the error:
/Library/Ruby/Gems/1.8/gems/searchlogic-2.3.6/lib/searchlogic/named_scopes/conditions.rb:111: warning: multiple values for a block parameter (2 for 1)
from /Library/Ruby/Gems/1.8/gems/searchlogic-2.3.6/lib/searchlogic/named_scopes/conditions.rb:173
ActiveRecord::PreparedStatementInvalid: wrong number of bind variables (2 for 1) in: support_regions.region_id IN (?)
from /Library/Ruby/Gems/1.8/gems/activerecord-2.3.4/lib/active_record/base.rb:2398:in raise_if_bind_arity_mismatch' from /Library/Ruby/Gems/1.8/gems/activerecord-2.3.4/lib/active_record/base.rb:2350:inreplace_bind_variables'
from /Library/Ruby/Gems/1.8/gems/activerecord-2.3.4/lib/active_record/base.rb:2341:in sanitize_sql_array' from /Library/Ruby/Gems/1.8/gems/activerecord-2.3.4/lib/active_record/base.rb:2230:insanitize_sql'
from /Library/Ruby/Gems/1.8/gems/activerecord-2.3.4/lib/active_record/base.rb:1494:in merge_conditions' from /Library/Ruby/Gems/1.8/gems/activerecord-2.3.4/lib/active_record/base.rb:1492:ineach'
from /Library/Ruby/Gems/1.8/gems/activerecord-2.3.4/lib/active_record/base.rb:1492:in merge_conditions' from /Library/Ruby/Gems/1.8/gems/activerecord-2.3.4/lib/active_record/base.rb:1804:inadd_conditions!'
from /Library/Ruby/Gems/1.8/gems/activerecord-2.3.4/lib/active_record/base.rb:1687:in construct_finder_sql' from /Library/Ruby/Gems/1.8/gems/activerecord-2.3.4/lib/active_record/base.rb:1548:infind_every'
from /Library/Ruby/Gems/1.8/gems/activerecord-2.3.4/lib/active_record/base.rb:615:in find' from /Library/Ruby/Gems/1.8/gems/activerecord-2.3.4/lib/active_record/named_scope.rb:181:insend'
from /Library/Ruby/Gems/1.8/gems/activerecord-2.3.4/lib/active_record/named_scope.rb:181:in method_missing' from /Library/Ruby/Gems/1.8/gems/activerecord-2.3.4/lib/active_record/base.rb:2143:inwith_scope'
from /Library/Ruby/Gems/1.8/gems/activerecord-2.3.4/lib/active_record/named_scope.rb:113:in __send__' from /Library/Ruby/Gems/1.8/gems/activerecord-2.3.4/lib/active_record/named_scope.rb:113:inwith_scope'
from /Library/Ruby/Gems/1.8/gems/activerecord-2.3.4/lib/active_record/named_scope.rb:174:in method_missing' from /Library/Ruby/Gems/1.8/gems/activerecord-2.3.4/lib/active_record/named_scope.rb:188:inload_found'
from /Library/Ruby/Gems/1.8/gems/activerecord-2.3.4/lib/active_record/named_scope.rb:166:in proxy_found' from /Library/Ruby/Gems/1.8/gems/activerecord-2.3.4/lib/active_record/named_scope.rb:109:ininspect'
from /System/Library/Frameworks/Ruby.framework/Versions/1.8/usr/lib/ruby/1.8/irb.rb:302:in output_value' from /System/Library/Frameworks/Ruby.framework/Versions/1.8/usr/lib/ruby/1.8/irb.rb:151:ineval_input'
from /System/Library/Frameworks/Ruby.framework/Versions/1.8/usr/lib/ruby/1.8/irb.rb:263:in signal_status' from /System/Library/Frameworks/Ruby.framework/Versions/1.8/usr/lib/ruby/1.8/irb.rb:147:ineval_input'
from /System/Library/Frameworks/Ruby.framework/Versions/1.8/usr/lib/ruby/1.8/irb.rb:146:in eval_input' from /System/Library/Frameworks/Ruby.framework/Versions/1.8/usr/lib/ruby/1.8/irb.rb:70:instart'
from /System/Library/Frameworks/Ruby.framework/Versions/1.8/usr/lib/ruby/1.8/irb.rb:69:in catch' from /System/Library/Frameworks/Ruby.framework/Versions/1.8/usr/lib/ruby/1.8/irb.rb:69:instart'

Condition Constants

I am trying to use jqGrid's search function with searchlogic. The rub of it is jqGrid's aliases for 'less than or equal to' and a few others do not map onto searchlogic's. Right now, I am creating a hash constant in the application controller to the mapping. What I would love is to have a configuration file that would allow me to extend the aliases. This way, I could drop that config file in any app I so chose that I wanted to use both libraries in concert. Anyway, thank you for such a wonderful plugin and if you would like me to write up a spec, I would be more than happy to.

cheers,
-xn

Search with empty array returns all results instead of none

Not sure I understand correctly, it might not be a bug.
If I use :

Activity.user_id_equals_any(current_user.friend_ids)
I expect this to be equivalent to
Activity.all(:conditions => {:user_id => current_user.friend_ids})

and it's not. The first expression will return all activities if the user doesn't have friends, and the second no activity, as expected.

thanks !

stack level too deep in merge_scopes_with_or

Class Message < ActiveRecord::Base
  has_many :addresses, :class_name => "MessageAddress"
  named_scope :system,  :joins => 'LEFT JOIN message_addresses ON message_addresses.message_id = messages.id', :conditions => 'message_addresses.id IS NULL'
end

Class MessageAddress < ActiveRecord::Base
  belongs_to :message
  belongs_to :recipeint, :polymorphic => true
  named_scope :for_user, lambda { |user| { :conditions => ["blah blah blah", user] } }
end

Now when I do Message.addresses_for_user_or_system(user) It generates a stack level too deep.

    searchlogic (2.3.1) [v] lib/searchlogic/named_scopes/or_conditions.rb:104:in `send'                                                                                                                                                     
    searchlogic (2.3.1) [v] lib/searchlogic/named_scopes/or_conditions.rb:104:in `merge_scopes_with_or'                                                                                                                                     
    searchlogic (2.3.1) [v] lib/searchlogic/named_scopes/or_conditions.rb:104:in `collect'                                                                                                                                                  
    searchlogic (2.3.1) [v] lib/searchlogic/named_scopes/or_conditions.rb:104:in `merge_scopes_with_or'                                                                                                                                     
    searchlogic (2.3.1) [v] lib/searchlogic/named_scopes/or_conditions.rb:99:in `create_or_condition'                                                                                                                                       
    searchlogic (2.3.1) [v] lib/searchlogic/named_scopes/or_conditions.rb:104:in `send'                                                                                                                                                     
    searchlogic (2.3.1) [v] lib/searchlogic/named_scopes/or_conditions.rb:104:in `merge_scopes_with_or'                                                                                                                                     
    searchlogic (2.3.1) [v] lib/searchlogic/named_scopes/or_conditions.rb:104:in `collect'                                                                                                                                                  
    searchlogic (2.3.1) [v] lib/searchlogic/named_scopes/or_conditions.rb:104:in `merge_scopes_with_or'                                                                                                                                     
    searchlogic (2.3.1) [v] lib/searchlogic/named_scopes/or_conditions.rb:99:in `create_or_condition'                                                                                                                                       
    searchlogic (2.3.1) [v] lib/searchlogic/named_scopes/or_conditions.rb:22:in `addresses_for_user_or_without_addresses'                                                                                                                   
    searchlogic (2.3.1) [v] lib/searchlogic/named_scopes/or_conditions.rb:22:in `send'                                                                                                                                                      
    searchlogic (2.3.1) [v] lib/searchlogic/named_scopes/or_conditions.rb:22:in `method_missing'                                                                                                                                            
    vendor/gems/mislav-will_paginate-2.3.11/lib/will_paginate/finder.rb:170:in `method_missing'                                                                                                                                             
    app/models/message.rb:19:in `for_user'                                                                                                                                                                                                  

There's a couple problems here. Obviously there's a bug that causes the stack level too deep. But the or using an associated named scope seems to be completely unsupported. So maybe my answer is to just not do that. Oh, and I manually patched my searchlogic 2.3.1 with the latest version of or_condition.rb

association perplexity

given a model
Company
with attribute
name

and a model
Contact
with attributes
first_name and last_name

The Models are associated like this:
Contact belongs_to Company
Company has_many Contacts

I wish to make a search field into which I can type a portion of either the contact's first name, the contact's last name or the company name.

This works:
@contacts = Contact.company_name_like(params[:search])

This works:
@contacts = Contact.first_name_or_last_name_like(params[:search])

This does NOT work:
@contacts = Contact.company_name_or_first_name_or_last_name_like(params[:search])
It returns this error:
"The condition 'company_name' is not a valid condition, we could not find any scopes that match this."

Evidently the scope company_name works by itself but not in combination with the other two. And the other two work, but not with company_name. I can only assume this has to do with the association and I am missing something obvious. Can anyone point out how to do it correctly?

The last example (company_name_or_first_name_or_last_name_like) worked in an earlier version of my app, when company was an attribute of Contact. When I made Company a separate model it stopped working.

I believe I have the current version of binarylogic-searchlogic. Rails version is 2.3.2, in development mode with standard sqlite database.

Thank you.

Parameter Not Read Correctly

This is what my search form sends:

"search"=>{"value_equals"=>"0..15000", "property_type_id"=>"1"}

The value_equals parameter is not read as a proper range, like from 0 to 15000 and while it should display as a result a record with value "10000", none is shown.

blank and not_blank conditions

Just as ActiveSupport adds the blank? and present? methods to Object to detect if something is either nil or a blank string/array/whatever, I thought it might be nice to provide the blank and not_blank conditions in searchlogic.

Example:

Person.first_name_blank
# => SELECT * FROM people WHERE first_name != '' OR first_name IS NULL

Just something we've found to be convenient for our app. Patch w/ specs can be found here:

http://gist.github.com/174043

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.