Posts Tagged ‘activerecord’

acts_as_similar - A basic similarity activerecord plugin

Thursday, June 4th, 2009

I had a need to find items that were similar to an item. I looked at acts_as_recommendable, and while this was very nice plugin, it was too slow when working with large data sets. I also decided that the results I needed didn’t need to be scientifically accurate, just a rough match. So I created this plugin to allow for a very elementary way to find items that are similar to the object you are working with. This works best when used with a has_many :through relationship.

Basically all it is doing is looking for other objects of the same class, that have some related value.

Git it here: http://github.com/freezzo/acts_as_similar/tree/master

Example 1
=========
Look for similar playlists, using the videos as what defines similarity.
This will look for all playlists that have a similar video as the playlist you are looking against.

class Playlist
  has_many :playlists_videos
  has_many :videos, :through => :playlists_videos
 
  acts_as_similar :videos
end

Example 2
=========
Look for similar playlists, using the title of the playlist as the similarity item.
This will look for all playlists that have a similar title as the playlist you are looking against.

class Playlist
  has_many :playlists_videos
  has_many :videos, :through => :playlists_videos
 
  acts_as_similar :field => :title
end

Example 3
=========
Look for similar playlists, using the video_id of the playlists_videos as the similarity item.
This will look for all playlists that have a similar video_id as the playlist you are looking against.

class Playlist
  has_many :playlists_videos
  has_many :videos, :through => :playlists_videos
 
  acts_as_similar :playlists_videos, :field => :video_id
end

Execute
=========

@playlist = Playlist.first
@playlist.similar

Note: This is a work in progress.

ActiveRecord - Making :include and :select play nice!

Wednesday, May 20th, 2009

So I have been using a nice plug-in that will allow me to using :select when using :include, and not have it pull the entire data set. You can add the plug-in to your app like this:

script/plugin install git://github.com/blythedunham/eload-select.git

Here are some ways to use the plug-in:

Employee.find :all,
    :select => 'addresses.city, address.state, employees.*',
    :include => :address
Employee.find :first,
    :select => 'now() as current_time, addresses.city, DATE(addresses.created_at) as addresses.created_at, employee.*',
    :include => :address
Employee.find :all,
    :select => 'addresses.city, employees.name, employees.start_date',
    :include => :address

Examples taken from:
http://www.snowgiraffe.com/tech/329/eager-loading-select-plugin-when-select-plays-nice-with-include/

How to merge strings just like ActiveRecord conditions do

Friday, March 13th, 2009

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.

OMFG Sessions!! Clear them out!!

Wednesday, January 14th, 2009

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!

ActiveRecord and Transactions!

Wednesday, October 29th, 2008

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!

Thursday, October 23rd, 2008

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

Wednesday, October 22nd, 2008

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!

Instant Rails Scaling through Asynchronous(Non-blocking) ActiveRecord

Thursday, September 4th, 2008

The guys over at NeverBlock have released a database adapter for Rails application that will severely increase the performance of ActiveRecord. Its also really easy to integrate into your application. Heres how:

Add a line to environment.rb for mongrel or thin servers:

require 'never_block/servers/thin'

or

require 'never_block/servers/mongrel'

Change the adapter in database.yml:

adapter: neverblock_postgresql

or

adapter: neverblock_mysql

You can also specify the number of connections (default of 4):

connections: 12

More information, along with benchmarks, can be found here.

ActiveRecord conditions with association from hash

Friday, August 29th, 2008

I’m sure you all know how to use the :conditions attribute when using ActiveRecord:

User.find(:all, :conditions=>['active = ?', true])

And you may even use associations this way:

User.find(:all, :include=>[:photos], :conditions=>['photos.removed = ? and users.active = ?', false, true])

But did you know that you can do this easier through hashes?

User.find(:all, :conditions=>{:active=>true})
User.find(:all, :include=>[:photos], :conditions=>{'photos.removed'=>false, 'users.active'=>true})

Nothing special there, but I thought it was pretty cool. One thing you have to remember when using associations, is to include that model.