google
yahoo
bing

Where Plugin

January 2nd, 2006

UPDATE: I had to disable comments, because I was getting spammed with hundreds of “cool site” messages. Feel free to contact me in any other way.

Working with RubyOnRails is a really wonderful way of developing applications. The plugin system allows extensions without modifying the core of rails.

Here’s my second plugin: WherePlugin

It’s based on some code by Ezra Zygmuntovic extended by me, further extended by Ezra and packaged as a plugin.

It allows for easier creation of the :conditions => … clause in ActiveRecord find statements.

Here’s how to use it:

c = InVisible::Cond.new do
   year '>', 2005
   name 'like', 'Foo%'
end
Model.find(:all, :conditions => c.where )

or in a combined form:

Model.find_with_conditions(:all) do
   year '>', 2005
   name 'like', 'Foo%'
end

Installation

$cd /my/rails/project
$ruby script/plugin discover
$ruby script/plugin install -x where

The subversion repository is located at http://invisible.ch/svn/projects/plugins/where

Usage

You can use the following types of clauses in the definition of the Condition block:

  • name ‘operator’, value
  • name ‘between’, value, value
  • sql ‘some sql statement’, value

Examples:

  • first_name ‘=’, ‘Ezra’
  • start_date ‘between’, ’2006-01-01′, ’2006-01-30′
  • last_name ‘like’, ‘Zyg%’
  • sql ‘hosts.id = something.id’

You can extend an existing condition block like this:

c = Cond.new
c < < ['name', 'Jens-Christian']
c << ['age', '>', 30]

Caveats

There is one caveat, if you use self in the block:

Task.find(:all, :conditions => ["project_id = ?", self.id] )

Task.find_with_conditions(:all) do
    project_id '=', self.id
end

will break, because self inside the block will refer to another object. A workaround is to use temporary variables:

self_id = self.id
Task.find_with_conditions(:all) do
    project_id '=', self_id
end

I will see, if there is a better solution for this.

Revision history

v. 0.2 (svn 36), 2.1.2006

  • Added Ezra’s Cond Class
  • removed the Where Class (breaking old code, but the Cond class is nicer)
  • fixed the Model.findwithconditions method to use the Cond class

Comments, ideas etc. very welcome

Technorati Tags: ,

Entry Filed under: Uncategorized

12 Comments

  • 1. Scott  |  March 1st, 2006 at 04:10

    I’m using your where plugin in a small webapp (thanks!)

    Using the install command ruby script/plugin install -x where gives me the trunk revision – is there a variation on this to allow me to checkout a specific revision (e.g. 36 for 0.2)?

    RailsEngines uses the more standard trunk, branches, tags etc. structure so I can use the url to determine the tag I want to checkout.

    Basically I need to be sure that my plugin code is only updated when I want it to be (so I can test the integration with my application).

    Also, your server was down for a while today. I use SwittchTower to deploy – since this pulls the source from svn my deployments were failing until your site came back up. This experience is making me reconsider the use of svn:externals for plugins since doing so leaves me at the mercy of multiple servers, any of which can cause my deployment to fail.

    I guess if I do an actual checkout of the code (more likely an export/import) I can get around both of these problems at the expense of it becoming a little more difficult to receive updates.

    Cheers,

    Scott

  • 2. Administrator  |  March 1st, 2006 at 08:13

    Thanks for your comments. When I’ll release the next version, I’ll switch to the trunks/tags format to alleviate this problem.

    My hoster had a
    network blip
    – so everything was gone for a while. I don’t know the best way around situations like that.

    It looks like the whole plugin system needs some thought in order to make it more safe to use.

    jc

  • 3. Benjamin  |  April 11th, 2006 at 02:55

    Your plugin is definetely useful for people who want an alternative style to crafting their conditions. You could actually put conditions in a seperate file entirely if you wanted a really clean looking file and just have condition definitions elsewhere. That’d be an interesting way to organize them. Thoughts?

  • 4. iktorn  |  May 19th, 2006 at 11:43

    The plugin is awesome. I was looking for a clean way to add multiple conds to find. BUT – 2 things:
    I use:

    name 'like', '%' + params[:search] + '%' unless params[:search].nil

    1. params is inaccessible is this the same thing as with self?
    2. if there are no conditions (all are nil?):

      Task.findwithconditions(:all) do
      end

      I get a SQL error it produces ‘AND ()’.
  • 5. iktorn  |  May 19th, 2006 at 11:49

    Update – I think the no 1 is the issue with method_missing…
    I don’t know how to fix it though

  • 6. Administrator  |  May 23rd, 2006 at 06:28

    iktorn, yes you are right, params is not accesible in that context. Take a look at Ezra’s ezwhere plugin (http://agilewebdevelopment.com/plugins/ezwhere) which has this problem solved (and expands the whole thing with a beautiful ruby like way of doing the query)

    I’ll take a look at the second problem when I find some time

  • 7. iktorn  |  May 25th, 2006 at 10:20

    A new bug found… :)

    options = args.last.class.is_a?(Hash) ? args.pop : {}
    

    should be

    options = args.last.is_a?(Hash) ? args.pop : {}
    
  • 8. Administrator  |  May 25th, 2006 at 17:49

    Thanks iktorn, I commited a new version with 2 out 3 of your problems fixed. I’ll look into the third (availability of variables in block) later

    jc

  • 9. Alan  |  May 31st, 2006 at 20:17

    So exactly how do you use the examples? Do you put your example code in a view protected with <% markup? I could not get it to work.

  • 10. Jens-Christian Fischer  |  May 31st, 2006 at 23:22

    Alan, I’m not sure I understand your question. I usually use this plugin in my models when there’s a

    Model.find( ... )

    statement that has a very complex :conditions => {} part. Does that answer your question? Otherwise, please provide more information on what you are trying to do

  • 11. Michael Mahemoff  |  August 29th, 2006 at 20:02

    For anyone who’s interested, here’s how I got the internal test (where_test.rb) running for mysql.

    • Changed database in test_helper.rb from “sqllite” to “mysql”. (I didn’t have env[db] setup.)
    • Created a DB – “create database whereplugintest”
    • Set DB name (whereplugintest), username, and password in the where project’s database.yml
      … Green Bar!
  • 12. Going Up » Simplifi&hellip  |  October 25th, 2006 at 15:27

    [...] So I’ve tried Ezra’s “ez_where” and InVisible’s “where” plugins, but in the end I just couldn’t get past the hackish feeling I got when I used them. [...]

Trackback this post


Most Recent Posts

I wrote the book