A voting extension from scratch for Rails 3 (Part 5 – Migration Generators)

In the last episode we took a look at the model and schema of the MakeVoteable gem.

However the schema in the spec folder just sets up our required database fields for the testing environment, but does not help us when the gem gets installed in a Rails application. Therefore are the migration files defined in the application itself (which again create the schema file for the application).

One way would be to tell the user in the documentation of the external gem exactly about the migration details the gem needs. As setting up a migration file can be quite time consuming, error prone and boring, there is a much more convenient way for users of your gem … using generators.

There are very different kinds of generators and most likely you have used them for various tasks (creating scaffolds, controllers, and so on). Many of those generators just call other generators again. Here we are interested in migration generators (that by the way are also called when generating scaffolds or models).

Read the rest of this entry »

A voting extension from scratch for Rails 3 (Part 4 – models and migrations)

Better late than never … finally Part 4 of the blog series about developing MakeVoteable, a voting gem for Rails 3.

In the last episode we took a deeper look how to get the logic inside our gem. In this episode we focus on the model this logic acts on. As we use ActiveRecord to store our model in a SQL database, it has to inherit from ActiveRecord::Base.

I decided for MakeVoteable to have just one model named Voting. This Voting model stores the connection between a Voteable and a Voter after a vote took place. That way it is possible to fetch the information afterwards what voters voted for what voteables. MakeVoteable tries to be agnostic about what a voter or voteable exactly is. A voter could even be a voteable (like a user that votes other users). To archive that MakeVoteable makes use of polymophic associations.

# lib/make_voteable/voting.rb
module MakeVoteable
  class Voting < ActiveRecord::Base
    attr_accessible :voteable, :voter, :up_vote
 
    belongs_to :voteable, :polymorphic => true
    belongs_to :voter, :polymorphic => true
  end
end

Read the rest of this entry »

A voting extension from scratch for Rails 3 (Part 3 – logic concerns)

After some busy days I finally had the time for part 3 of the MakeVoteable blog series. In the previous episodes we looked at setting up the basic gem structure and configuring our testing environment. Now it’s time to investigate the core logic of make_voteable.

A voting system normally has someone who votes (a voter) and something that is voted for (a voteable). Ruby makes it really easy to have well understandable, concise and beautiful APIs. So if we have a user named scarlett (yeah, I know … you wish to have) as voter and a question object named dumb_question it would totally make sense to make the voting through a call like scarlett.up_vote(dump_question) (hey, what do you expect?! … she’s blond). Most of the other MakeVoteable methods are also called from the user object. That is what I call “user centric” in MakeVoteable. For the other methods (like down_vote, unvote) have a look in the README.

But the big question is, how do we get those methods inside a user and question model? The Ruby On Rails Guides do have an extra section about that topic. Unfortunately it is a bit out of date (but still working!) and with Rails 3 there are much smoother solutions.

Read the rest of this entry »

Mass animations with jQuery

In a recent web app project that uses jQuery on the client we needed to animate many many HTML elements (about 1500) at once and synchronously. As the normal animate method of jQuery does the animation on each element setting its element style one gets pretty fast into performance troubles when doing such mass animations. It also never looked really synchronous as the first element in the jQuery object started its animation earlier than the last one.

To solve that problem we thought about animating styles of a class that is common to all that elements. We then also found jQuery RuleAnimation that depends on jQuery Rule for style rule mainpulations. Unfortunately both seem to be unmaintained and incompatible with newer (>= 1.4.3) jQuery versions. So we decided to create a new jQuery extension that focuses exactly on the animation problem.

As result we came up with jQuery Mass Animate.

$.massanimate("div.custom-class")
.css({width: 10, opacity: 1})
.animate({width:200, opacity: 0}, 1000)
.remove();

In the example a new style rule is created and initial styles are set (note that you can also use Mass Animate to just set custom style rules at runtime without animating at all). Then an animation is performed on exactly that style rule. Afterwards the style rule is removed again (after the animation was finished). So pretty straightforward and using the same syntax as the normal jQuery methods for working on elements. Mass Animate even uses the original methods with some hacks to make them work with style rules.

Here is a little Demo. The code (MIT, GPL dual licensed) and documentation can be found at the jQuery Mass Animate GitHub repo. Mass Animate is fully Unit tested and tested on nearly all current browsers (FF3/4, Chrome, Opera 11, IE7/8/9).

A voting extension from scratch for Rails 3 (Part 2 – Testing environment)

In the last episode we created the basic structure for the make_voteable gem. With “test first” in mind we now set up our RSpec testing environment for developing the make_voteable gem. We already installed RSpec at the beginning of this blog series. First we need to create a testing folder (named spec) directly under the project root (make_voteable/spec). We also create a file named spec_helper.rb in this spec folder containing the testing configurations.

  1. # spec/spec_helper.rb
  2. require 'rubygems'
  3. require 'bundler'
  4. require 'logger'
  5. require 'rspec'
  6. require 'active_record'
  7. require 'database_cleaner'
  8.  
  9. $LOAD_PATH.unshift(File.dirname(__FILE__) + '/../lib')
  10. require 'make_voteable'
  11.  
  12. ActiveRecord::Base.logger = Logger.new(File.dirname(__FILE__) + '/debug.log')
  13. ActiveRecord::Base.configurations = YAML::load_file(File.dirname(__FILE__) + '/database.yml')
  14. ActiveRecord::Base.establish_connection(ENV['DB'] || 'sqlite3')
  15.  
  16. ActiveRecord::Base.silence do
  17.   ActiveRecord::Migration.verbose = false
  18.  
  19.   load(File.dirname(__FILE__) + '/schema.rb')
  20.   load(File.dirname(__FILE__) + '/models.rb')
  21. end
  22.  
  23. RSpec.configure do |config|
  24.   config.filter_run :focus => true
  25.   config.run_all_when_everything_filtered = true
  26.   config.filter_run_excluding :exclude => true
  27.  
  28.   config.mock_with :rspec
  29.  
  30.   config.before(:suite) do
  31.     DatabaseCleaner.strategy = :truncation
  32.     DatabaseCleaner.clean
  33.   end
  34.  
  35.   config.after(:each) do
  36.     DatabaseCleaner.clean
  37.   end
  38. end

Read the rest of this entry »

A voting extension from scratch for Rails 3 (Part 1 – Overview and setup)

This blog series is about creating a voting extension for Ruby On Rails. There are already some others voting extensions available, but none is currently up-to-date 1 or ActiveRecord compatible 2. So let’s build one from scratch. It is also (or maybe even more) a blueprint of current best practices on how to build those “acts_as_something” like Rails 3 extensions.

The full and working source code inclusive documentation can be fetched from the GitHub make_voteable repository or from RubyGems (gem install make_voteable).

Here are some features that come into my mind what such a voting extension should fulfill:

  • Allow up and down votes
  • Be voteable agnostic (everything can be voted on)
  • Be voter agnostic (everything can vote)
  • Only one vote per voter on one voteable
  • Full access to voting info (when / what / who)
  • Good performance (optimized model structure and queries)
  • Support for Rails 3 and ActiveRecord … not /dev/null
  • Easy to setup (migration generators)
  • Fully tested (RSpec)
  • Easy distribution (Github and RubyGems)
  • Free and open license (MIT License)

For the gem name I chose make_voteable as the acts_as is already occupied by the older above mentioned gems. I also think it is a nice “namespace” that is not yet so worn out like the “acts_as” one. I also didn’t like the extension to be on steroids.

Read the rest of this entry »

Check your params

I just asked myself (and the community) where validating and cleaning up the GET/POST parameters would fit best in Rails. lebreeze at Stackoverflow suggested a sanitize_params method that is called by a before_filter in the ApplicationController. I agree that the ApplicationController is a good place, but I don’t like the fact that it is called and parameters are checked for every controller and action (since they all inherit from the ApplicationController by default) regardless of whether any parameters are needed at all in the action. A workaround would be to check the controller name and action (by using controller_name and action_name methods) in the sanitize_params method and act accordingly, but this is not very intuitive in my opinion. So I decided against a before_filter and call a fetch_param method from within every action with the parameter name I’d like to fetch. That way one could also pass extra options that influence how the parameters are fetched. Here is a little example how the fetch_param method in the ApplicationController may look like. By setting it as helper_method I also ensure that it can be accessed by the view templates.

If you have a better (or alternative) solution then I would like to hear.

# app/controllers/application_controller.rb
...
helper_method :fetch_param
 
def fetch_param(:name, :options = {})
@fetched_params ||= Hash.new
 
  if name == :page
    @fetched_params[:page] ||= check_integer(params[:page], 1, :min => 1)
  elsif name == :per_page
    @fetched_params[:per_page] ||= check_integer(params[:per_page], 25, :min => 1, :max => options[:max])
  elsif ...
  ...
end
...

The check_integer method is part of a small gem named ParamChecker that I created for handling those recurring parameter checking tasks. ParamChecker also contains functions for checking floats (check_float), strings (check_string), symbols (check_symbol) and booleans (check_boolean).

For more info please see the ParamChecker GitHub repository.

Index external models with Sunspot/Solr

Lately I wanted to index all tags of ActsAsTaggableOn for full text search and autosuggestions using Solr resp. Sunspot. The ActiveRecord models of ActsAsTaggableOn are unfortunately not directly accessible as they are located in the ActsAsTaggableOn gem. Fortunately that is pretty easy to solve by using metaprogramming techniques. So I added an additional initializer named sunspot_index.rb into the config/initializers directory with the below content.

# config/initializers/sunspot_index.rb
ActsAsTaggableOn::Tagging.class_eval do
  after_save :index_tag
 
  def index_tag
    tag.index
  end
end
 
ActsAsTaggableOn::Tag.class_eval do
  searchable do
    text :name
    integer :count do
      self.taggings.count
    end
  end
end

This adds an Sunspot/Solr index for the tag name and also one for the tag count (how often the tag is used). The tag also gets reindexed when a tagging was added or removed. (Side note: ActsAsTaggableOn uses tag and tagging together to represent a tag of a taggable. Have a look at the ActsAsTaggableOn source for more info, it is very well commented).

One other minor pitfall is that the rake task rake sunspot:reindex does not include the above specified index. That’s because it just looks up the defined indexes of models in the the main model directory. There is an easy solution for this problem, too. Just use the rake task rake sunspot:reindex[,ActsAsTaggableOn::Tag] to index/reindex the external Tag model. (Don’t forget to also index/reindex your normal models by using rake sunspot:reindex.)

Intend to extend (metaprogramming in Ruby)

In this post I want to illustrate the different ways of how to extend Ruby classes and instances. As being a former Java developer it is always impressive, but also sometimes a bit confusing how many ways are available in Ruby to achieve that. There is already a lot written about this topic (see resources below), but as it is such an essential Ruby topic it is always nice to see things from different views.

Inheritance

One of the most common ways to add further functionality to an already existing class is to inherit from it and add the new stuff to the inherited class. Ruby isn’t here much different than any other object oriented language.

class Lifeform
  def eat
    puts "Yam"
  end
end
 
class Dog < Lifeform
  def eat
    puts "Yummi " + super
  end
 
  def bark
    puts "Wuff"
  end
end
 
Lifeform.new.eat # Yam
Lifeform.new.bark # NoMethodError
Dog.new.eat # Yummi Yam
Dog.new.bark # Wuff

Read the rest of this entry »

QuerySolr – a jQuery Solr library

Today I released QuerySolr. It is a small jQuery library for easily sending Ajax Solr requests.

A Solr query using QuerySolr looks like this:

$.querysolr({
  host: "127.0.0.1",
  port: "8983",
  params: {
    q: "*:*",
    fq: "type:car"
  },
  callback: function(data) {
    // do something with the returned Solr JSON results
  }
}).query(); // and finally send the request.

The code (qUnit tested) is dual licensed (MIT/GPL) and available at the QuerySolr GitHub repository. For further documentation please have a look there.