Created
March 23, 2010 21:01
-
-
Save kblake/341649 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
module AttributesSort | |
def self.included(receiver) | |
receiver.instance_eval do | |
def build_attributes(attributes) | |
"[" + attributes.map!{|a| "object.#{a}"}.join(",") + "]" | |
end | |
def do_attributes_sort(collection, options={}) | |
attributes = build_attributes(options[:sort_by]) | |
collection.sort_by{|object| eval(attributes)} | |
end | |
end | |
Array.class_eval do | |
def attr_sort(options = {}) | |
raise "You must pass in sort_by criteria" unless options[:sort_by] | |
begin | |
klass = self.first.class | |
klass.do_attributes_sort(self, options) | |
rescue NoMethodError | |
raise "You must sort by an attribute that exists in the object that you are sorting" | |
end | |
end | |
end | |
end | |
end | |
#and corresponding tests ########################################### | |
require File.expand_path(File.dirname(__FILE__) + '/spec_helper') | |
class Person | |
include AttributesSort | |
attr_accessor :firstname,:lastname,:age | |
def initialize(firstname="",lastname="",age=0) | |
@firstname = firstname | |
@lastname = lastname | |
@age = age | |
end | |
end | |
describe "AttributesSort" do | |
before(:each) do | |
@p1 = Person.new("joe","blow",89) | |
@p2 = Person.new("joe","blow",12) | |
@p3 = Person.new("mary","watson",32) | |
@p4 = Person.new("annie","watson",9) | |
@p5 = Person.new("bob","builder",12) | |
@people = [@p1, @p2, @p3, @p4, @p5] | |
end | |
def test_sort(criteria, result) | |
@people.attr_sort(:sort_by => criteria).should == result | |
end | |
it "sort_by standard ruby" do | |
@people.sort_by{|person| [person.age,person.firstname]}.should == [@p4, @p5, @p2, @p3, @p1] | |
end | |
it "object must have attr accessible attributes for sort_by to work" do | |
p = Person.new | |
p.should respond_to(:firstname) | |
p.should respond_to(:lastname) | |
p.should respond_to(:age) | |
end | |
#new test to show what build attributes is doing | |
it "build attributes string array to be eval'd at deferred time in sort_by block'" do | |
criteria = [:lastname, :age, :firstname] | |
Person.build_attributes(criteria).should == "[object.lastname,object.age,object.firstname]" | |
end | |
it "sort by last name" do | |
test_sort([:lastname], [@p1, @p2, @p5, @p4, @p3]) | |
end | |
it "sort by age" do | |
test_sort([:age], [@p4, @p2, @p5, @p3, @p1]) | |
end | |
it "sort by age then by first name" do | |
test_sort([:age, :firstname], [@p4, @p5, @p2, @p3, @p1]) | |
end | |
it "sort by age then by last name" do | |
test_sort([:age, :lastname], [@p4, @p2, @p5, @p3, @p1]) | |
end | |
it "sort by last name then by first name then by age" do | |
test_sort([:lastname,:firstname,:age], [@p2, @p1, @p5, @p4, @p3]) | |
end | |
it "raise error if criteria is not provided" do | |
lambda {test_sort(nil, [@p1, @p2, @p5, @p4, @p3])}.should raise_error("You must pass in sort_by criteria") | |
end | |
it "raise error if criteria is not a valid attribute of class" do | |
lambda {test_sort([:blah], [@p1, @p2, @p5, @p4, @p3])}.should raise_error("You must sort by an attribute that exists in the object that you are sorting") | |
end | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment