How to merge strings just like ActiveRecord conditions do

While you can achieve the same functionality using sprintf, this may provide a cleaner approach and one that you are more familiar with. This will allow you to build a string the same way you can use ActiveRecord and the :conditions option.
Basically how this works is by overriding the Array class and adding a method to merge the string and values together into unified string! Enough talk, lets see some code:

class Array
  def merge
    statement, *values = self
    expected = statement.count("?")
    provided = values.size
    raise "wrong number of bind variables (#{provided} for #{expected}) in: #{statement}" unless expected.eql?(provided)
    bound = values.dup
    statement.gsub("?") { bound.shift }
  end
end

As you can see, if you do not provide the right number of values for the statement, it will raise and error. Here is how you would use it:

puts ['Hello ?, how are you', 'John'].merge
#=> Hello John, how are you

Likewise, you can use variables to hold values:

message = "Hello ?, how are you"
name = 'John'
puts [message, name].merge
#=> Hello John, how are you

This will also work with multiple values:

puts ['Hello ?, ? and ?, how are you', 'John', 'Joe', 'Jim'].merge
#=> Hello John, Joe, and Jim, how are you

The only downside to this currently is that you cannot use a ? in the string you are merging, as it will think its a binding character.

NoMethodError on nil.each?

Have you ever have to iterate over an array from say the params hash? You probably have added some code to make sure that data exists in the hash element first before doing the loop. This is a cool little trick to help condense some code. Normally I would write this:

if params[:accounts] and params[:accounts].size > 0
  params[:accounts].each do |account|
    # Do something with account here
  end
end

As you can see, kind of ugly. Here is the change:

(params[:accounts] || []).each do |account|
  # Do something with account
end

AHH!!! Must nicer!

Moving files in Rails using String

Since ruby allow for really easy overriding of objects and classes, I decided to make it easier and cleaner to move my files. Here is how you currently do it:

FileUtils.move("/path/to/file", "/path/to/new/file")

I know this isn’t a huge deal, but I would like to clean it up a little bit. I used an initializer (RAILS_ROOT/config/initializers/core_extensions.rb) to override the String class as such:

class String
   def move(to = nil)
     if to
       if File.exist?(self)
         FileUtils.move(self, to)
       end
     end
   end
end

This allows me to do the following to move files:

"/path/to/file".move("/path/to/new/file")

I though it was pretty cool!

Rails sessions round two - Turn off by request type

This is a follow up to my previous post about clearing out sessions. It turns out I was pulling a lot of crap sessions from rss feeds and xml requests which I didn’t need. I had over 14k new sessions in less than one day. To help combat this, I came up with a solution to turn sessions off based on a request type. I added this to application.rb file:

session :off, :if => Proc.new { |req| ['xml', 'rss'].include?(req.params[:format]) }

You could ideally just add this to an individual controller, and add :only or :except to it as well, but I wanted to eliminate all of the controllers and actions.

OMFG Sessions!! Clear them out!!

So since my site, jamzee.com has been in production for over a year now, I have gotten ambitious and decided to do some database maintenance. The first thing I did was log into the server and run a:

mysqlcheck -o database -u username -p

This runs a bunch of mysql tasks; repair, optimize, etc. I notice this was taking a long time on one of the tables which happened to be the sessions table. I got suspicious and logged into the database for a peak.

What did I find, LOTS AND LOTS of rows, 150k+. This seemed relatively unnecessary so after some research found out that I can run the following:

rake db:sessions:clear

After some time of running that, we have a nice clear, and smaller database now! Next task is to throw that on a cron, probably run on a weekly interval.

Moral of the story, CLEAR THOSE SESSIONS!

Number of Jamzee Updates!

I have made a bunch of new updates to jamzee. They are as follows:

  • Added ability to search for YouTube videos by the URL from youtube.
  • Updated searching functionality to be more friendly and intuitive. You can preview videos and search for more videos on the fly.
  • Added ability to sort playlists videos.
  • Freshened up the main page some.

I have also been playing with working on an official myspace application, although receiving some resistance from myspace regarding the fact that the jamzee site searching through youtube. Hopefully we can work this out with them.

Easy True/False Select Tag with Rails

It’s been a while since my last post. I have been pretty busy with other things, but thats no excuse. Anyway, I came across a problem where I needed to create a select tag with just a true and false option in it and came up with the following quick and easy solution. (This would presumably work with more/different options as well):

First, create a file in the config/initializers directory. This is where your global variables will go for use in the select tags. I called mine select_tag_globals.rb:

TRUE_FALSE = { 'True'=>true, 'False'=>false }

Make sure the values are set to whatever the fields data type is. In this case I want the labels to say True or False, and the value saved to the database will be true or false. Now all we have to do is use this in a select tag in a view like so:

<%= f.select :database_field, TRUE_FALSE %>

This should give you a normal select box with True and False labels. Yay rails!

ActiveRecord and Transactions!

If you ever have to do multiple actions with activerecord, you should group it into a transaction like so:

Post.transaction do
  posts.each do |post|
    post = Post.new(:body=>'Whatever')
    post.save!
  end
end

This will rollback too if the save fails.

Bulk update using ActiveRecord without SQL!

Here is a cool way you can update columns in a table without writing any SQL using ActiveRecord. Suppose you have a form with checkboxes that are for deleting posts for the ones that are checked:

<input type="checkbox" name="posts[]" value="<%= post.id %>">

Now you can update this in the method of your controller that this form posts to:

Post.update_all({:removed=>true}, {:id=>params[:posts]})

ActiveRecord will take of the fact that you want to update 1 record or multiple!

ActiveRecord counting with associations

The other day I had to display the number of children items an object had so I decided to do the following:

# Controller
@customers = Customer.find(:all, :include=>[:receive_payments])
 
#View
<%= customer.receive_payments.count %>

While this worked for what I needed, it executed the following sql every iteration:

SELECT count(*) AS count_all FROM "receive_payments" WHERE ("receive_payments".customer_ref_list_id = E'850000-1071531366')

I thought this wasn’t right considering I used an association, however when you use count, it forces the use of count(*) on the database. This is where size comes in!!!!

<%= customer.receive_payments.size %>

Now we get the same results without the extra database counts!