Created
March 24, 2010 07:16
-
-
Save kblake/342057 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!{|attribute| "object.#{attribute}"}.join(",") << "]" | |
end | |
def do_attributes_sort(collection, attributes) | |
attribute_array_string = build_attributes(attributes) | |
collection.sort_by{|object| eval(attribute_array_string)} | |
end | |
end | |
Array.class_eval do | |
def sortable_attributes? | |
self.all? {|object| @attributes.all?{|attribute| object.respond_to?(attribute)}} | |
end | |
def class_type | |
klass = self.first.class | |
is_same = self.all?{|object| object.class == klass} | |
raise "All objects must be of the same class type" unless is_same | |
raise "All objects must respond to sort criteria"unless sortable_attributes? | |
klass | |
end | |
def attr_sort(options = {}) | |
@attributes = options[:sort_by] | |
raise "You must pass in sort_by criteria" unless @attributes | |
class_type.do_attributes_sort(self, @attributes) | |
end | |
end | |
end | |
end | |
# tests that reflect changes ################################################################### | |
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 | |
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("All objects must respond to sort criteria") | |
end | |
it "raise error if objects are not of same class type" do | |
@people << "some other object" | |
lambda {test_sort([:age],[@p1, @p2, @p5, @p4, @p3])}.should raise_error("All objects must be of the same class type") | |
end | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment