jump to navigation

Subselector, Moneypenny November 1, 2008

Posted by reidmix in ActiveRecord, Code, Database, Example, Monkey Patch, Plugins & Gems, Rails.
Tags: , , , , ,
2 comments

Building on Josh and Damon‘s idea of Hacking a Subselect in ActiveRecord, I wondered if you could bake this kind of functionality into ActiveRecord.  So Doug and I went digging into the rails code, and came up with a plugin that adds subselects to ActiveRecord which we call Subselector.

So far, it only works on the Hash version of conditions.

On a column you wish to perform a subselect, pass a hash with :in, :not_in, :equals, or :not_equals as the only key.  The value is any of the options you normally would pass to ActiveRecord find.  Notice that we make sure to select a single column with the :select option:

Critic.find(:all, :conditions => { :id => {:in => {:select => :id, :conditions => {:active => true} } } })

Although the example may be contrived, here, we are looking for a critics that are in a set of active critics. The SQL:

select * from critics where id in (select id from critics where active = false)

You can see by default it runs the subselect on the table of outer select.  It gets more interesting you want to run a query on another ActiveRecord model:

Critic.find(:all, :conditions => { :id => {:in => {:model => :rankings, :select => :critic_id, :conditions =>
  {:week => 39} } } })

Here we set :model to :rankings.  Rankings is the ActiveRecord model to perform the find, notice we select the :critic_id column, the SQL is:

select * from critics where id in (select critic_id from rankings where week = 39)

And of course you can always just pass a string as a value to the subselect:

Critic.find(:all, :conditions => { :id => {:not_in => 'select id from critics where active = true' } })

Here’s how subselector can be used with the original example:

Post.find(:all, :conditions => :id => {:in => { :select => :post_id, :conditions => {:blog_id => self.id}, :order => "published_at DESC", :limit => options[:limit] || 10, :offset => options[:offset])} }, :order => "published_at DESC")

UPDATE: Subselector now likes Condition Arrays and Named Bind Variables.

Just pass the hash as a bind variable and specify the type (in/equals) of subselect in the string, make sure to enclose your ‘?’ inside parentheses:

Critic.find(:all, :conditions => ['id in (?)', {:select => :id, :conditions => 'active = true' }])
Critic.find(:all, :conditions => ['id not in (?)', {:select => :id, :conditions => {:active => false} }])
Critic.find(:all, :conditions => ['id in (?)', {:model => :rankings, :select => :critic_id, :conditions => {:week => 39} }])

As you can see, you can format the subselect hash just as above and can specify another model to run the subselect on. If you prefer to use named bind variable hashes, they still work (yay) as you would expect. And you can assign the subselect using them:

Critic.find(:all, :conditions => ['id in (:subselect)', {:subselect => {:select => :id, :conditions => {:active => false} } }])

UPDATE 2: Now with no ActiveRecord breakage

We’ve run the rails ActiveRecord tests without any problems. Let me know if you find any problems.

Advertisements

Rails Cron — Craken July 18, 2008

Posted by John Dewey in Capistrano, Code, Command Line, Configuration, Rails, Rake, Ruby.
Tags:
1 comment so far

My good buddy Doug Mciness wrote a rake task to manage and install cronjobs. We have it hooked into our Capistrano deployments, which allows for uber simple cron management. I added a few modifications such as, erb’ed raketab templates, and global/system specific crontabs.

It’s up on GitHubhttp://github.com/latimes/craken/tree/master

In the process of determining if these rakefiles should be yaml instead, would probably be the “more railsy rails way” of doing it.

Giles Bowkett gets props for the groovy name, and improved SEO of this post!

Plug This: css_browser_selector plugin May 22, 2008

Posted by reidmix in Code, Plugins & Gems, Rails.
Tags: , , ,
3 comments

I’m happy to announce my first plugin based on the css_browser_selector javascript which adds the name of the browser and platform as css class selectors that your client is using on the html element in your page. For example:

<html class="gecko mac js">

I’ve released my first version of the plugin (at 0.9.1) and you can download it from on LATimes RubyForge project or from GitHub. You can read how to use the plugin in its README, it offers a way to include the javascript inline into your views and layouts:

<%= javascript_tag css_browser_selector %>

But wait there’s more! What the plugin also does is offer a body (and html) tag helper that will render css selectors into your views from the backend. The real benefit to this is that these selectors will be available within the page without needing javascript enabled:

<% body do %>
  <%= yield %>
<% end %>

And this will add the selectors as you would expect to your body tag:

<body class="gecko mac">

The body helper is currently aware of page caching and will revert to the javascript version if the page is being cached through the caches_page method.

This is my first plugin and, yes, I still have some work to do (complete my tests, better caching awareness, sensitivity to pre-existing body and html tag helpers), but I wanted to share back to the community. Following Giles Bowkett‘s mantra to release software (often and early).

There’s plenty of more options as explained by the README. I welcome feedback, suggestions, improvements, bugs, and diffs! I’d also like to thank Rafeal Lima who implemented and maintains the javascript and his help and support with the plugin