ar_orderable 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/.gitignore +3 -0
- data/.rvmrc +1 -0
- data/Gemfile +15 -0
- data/README.textile +57 -0
- data/Rakefile +17 -0
- data/VERSION +1 -0
- data/ar_orderable.gemspec +73 -0
- data/init.rb +1 -0
- data/lib/orderable.rb +101 -0
- data/spec/order_belongs_to_association_spec.rb +26 -0
- data/spec/order_case_sensitivity_spec.rb +56 -0
- data/spec/order_multiple_attributes_spec.rb +19 -0
- data/spec/order_spec.rb +29 -0
- data/spec/spec_helper.rb +23 -0
- data/spec/support/database.yml +11 -0
- data/spec/support/factories.rb +7 -0
- data/spec/support/lib/activerecord_test_connector.rb +60 -0
- data/spec/support/matchers/be_in_order.rb +28 -0
- data/spec/support/models/developer.rb +5 -0
- data/spec/support/models/game.rb +5 -0
- data/spec/support/schema.rb +12 -0
- metadata +112 -0
data/.gitignore
ADDED
data/.rvmrc
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
rvm 1.8.7@ar_orderable
|
data/Gemfile
ADDED
@@ -0,0 +1,15 @@
|
|
1
|
+
source "http://rubygems.org"
|
2
|
+
|
3
|
+
gem "activerecord", "2.3.5"
|
4
|
+
gem "jeweler"
|
5
|
+
gem "gemcutter"
|
6
|
+
|
7
|
+
group :test do
|
8
|
+
gem "activesupport", "2.3.5"
|
9
|
+
gem "factory_girl"
|
10
|
+
gem "rspec", "~> 1.3.0"
|
11
|
+
gem "rspec-rails", "~> 1.3.0"
|
12
|
+
gem "sqlite3-ruby"
|
13
|
+
gem "pg"
|
14
|
+
gem "mysql"
|
15
|
+
end
|
data/README.textile
ADDED
@@ -0,0 +1,57 @@
|
|
1
|
+
h2. Introduction
|
2
|
+
|
3
|
+
ar_orderable is a small ActiveRecord addition that makes ordering of results easier and cleaner.
|
4
|
+
|
5
|
+
Supported features are:
|
6
|
+
|
7
|
+
* Ordering by an attribute in associated model (@belongs_to@ or @has_one@)
|
8
|
+
* Ordering by multiple attributes
|
9
|
+
* Defaults to case-insensitive ordering (@a < B@), optionally case-sensitive
|
10
|
+
* Direction can be specified, defaults to ascending
|
11
|
+
* Protects from SQL injection by checking the attribute to order by is in a predefined set of orderable attributes
|
12
|
+
|
13
|
+
Tested with ActiveRecord 2.3.5. Should work without hassle using any 2.3.x version of ActiveRecord. Support for ActiveRecord 3.0.x is upcoming.
|
14
|
+
|
15
|
+
Supported & tested database adapters include PostgreSQL, MySQL and SQLite3. Might work with others.
|
16
|
+
|
17
|
+
h2. Installation
|
18
|
+
|
19
|
+
Using Bundler with Rails 2.3.x add this to your Gemfile:<pre><code>
|
20
|
+
gem "ar_orderable", :require => "orderable"
|
21
|
+
</code></pre>
|
22
|
+
|
23
|
+
As plugin:<pre><code>
|
24
|
+
./script/plugin install git://github.com/mnylen/ar_orderable.git
|
25
|
+
</code></pre>
|
26
|
+
|
27
|
+
h2. Usage
|
28
|
+
|
29
|
+
In model:<pre><code>
|
30
|
+
class Game < ActiveRecord::Base
|
31
|
+
belongs_to :developer
|
32
|
+
orderable :by => [:name, :"developer.name"], :default => :name
|
33
|
+
end
|
34
|
+
</code></pre>
|
35
|
+
|
36
|
+
In controller:<pre><code>
|
37
|
+
Game.order(:name) # or Game.order("name")
|
38
|
+
</code></pre>
|
39
|
+
|
40
|
+
To order by association's attribute:<pre><code>
|
41
|
+
Game.order(:"developer.name") # or Game.order("developer.name")
|
42
|
+
</code></pre>
|
43
|
+
|
44
|
+
To order in descending order:<pre><code>
|
45
|
+
Game.order(:"name!desc") # or Game.order("name!desc")
|
46
|
+
</code></pre>
|
47
|
+
|
48
|
+
To order in case-sensitive manner:<pre><code>
|
49
|
+
Game.order(:name, :case_sensitive => true)
|
50
|
+
</code></pre>
|
51
|
+
|
52
|
+
To order by multiple attributes:<pre><code>
|
53
|
+
Game.order([:"developer.name", :name]) # orders results first by developer name, then by game name
|
54
|
+
</code></pre>
|
55
|
+
|
56
|
+
If trying to order by an attribute that is not orderable by, it will order by the default attribute:<pre><code>
|
57
|
+
Game.order(:updated_at) # will order by name
|
data/Rakefile
ADDED
@@ -0,0 +1,17 @@
|
|
1
|
+
begin
|
2
|
+
require 'jeweler'
|
3
|
+
|
4
|
+
Jeweler::Tasks.new do |gemspec|
|
5
|
+
gemspec.name = "ar_orderable"
|
6
|
+
gemspec.summary = "A small ActiveRecord addition that makes ordering of results easier and cleaner"
|
7
|
+
gemspec.description = "ar_orderable adds a consistent way to order results at database level using ActiveRecord. Supports ordering by multiple attributes and by associated model's attributes."
|
8
|
+
gemspec.email = "mikko.nylen@gmail.com"
|
9
|
+
gemspec.homepage = "http://github.com/mnylen/ar_orderable"
|
10
|
+
gemspec.authors = ["Mikko Nylén"]
|
11
|
+
gemspec.add_dependency("activerecord", "~> 2.3.5")
|
12
|
+
end
|
13
|
+
|
14
|
+
Jeweler::GemcutterTasks.new
|
15
|
+
rescue LoadError
|
16
|
+
puts "Jeweler not available. Install it with: gem install jeweler"
|
17
|
+
end
|
data/VERSION
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
0.1.0
|
@@ -0,0 +1,73 @@
|
|
1
|
+
# Generated by jeweler
|
2
|
+
# DO NOT EDIT THIS FILE DIRECTLY
|
3
|
+
# Instead, edit Jeweler::Tasks in Rakefile, and run the gemspec command
|
4
|
+
# -*- encoding: utf-8 -*-
|
5
|
+
|
6
|
+
Gem::Specification.new do |s|
|
7
|
+
s.name = %q{ar_orderable}
|
8
|
+
s.version = "0.1.0"
|
9
|
+
|
10
|
+
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
11
|
+
s.authors = ["Mikko Nyl\303\251n"]
|
12
|
+
s.date = %q{2010-09-19}
|
13
|
+
s.description = %q{ar_orderable adds a consistent way to order results at database level using ActiveRecord. Supports ordering by multiple attributes and by associated model's attributes.}
|
14
|
+
s.email = %q{mikko.nylen@gmail.com}
|
15
|
+
s.extra_rdoc_files = [
|
16
|
+
"README.textile"
|
17
|
+
]
|
18
|
+
s.files = [
|
19
|
+
".gitignore",
|
20
|
+
".rvmrc",
|
21
|
+
"Gemfile",
|
22
|
+
"README.textile",
|
23
|
+
"Rakefile",
|
24
|
+
"VERSION",
|
25
|
+
"ar_orderable.gemspec",
|
26
|
+
"init.rb",
|
27
|
+
"lib/orderable.rb",
|
28
|
+
"spec/order_belongs_to_association_spec.rb",
|
29
|
+
"spec/order_case_sensitivity_spec.rb",
|
30
|
+
"spec/order_multiple_attributes_spec.rb",
|
31
|
+
"spec/order_spec.rb",
|
32
|
+
"spec/spec_helper.rb",
|
33
|
+
"spec/support/database.yml",
|
34
|
+
"spec/support/factories.rb",
|
35
|
+
"spec/support/lib/activerecord_test_connector.rb",
|
36
|
+
"spec/support/matchers/be_in_order.rb",
|
37
|
+
"spec/support/models/developer.rb",
|
38
|
+
"spec/support/models/game.rb",
|
39
|
+
"spec/support/schema.rb"
|
40
|
+
]
|
41
|
+
s.homepage = %q{http://github.com/mnylen/ar_orderable}
|
42
|
+
s.rdoc_options = ["--charset=UTF-8"]
|
43
|
+
s.require_paths = ["lib"]
|
44
|
+
s.rubygems_version = %q{1.3.7}
|
45
|
+
s.summary = %q{A small ActiveRecord addition that makes ordering of results easier and cleaner}
|
46
|
+
s.test_files = [
|
47
|
+
"spec/order_belongs_to_association_spec.rb",
|
48
|
+
"spec/order_case_sensitivity_spec.rb",
|
49
|
+
"spec/order_multiple_attributes_spec.rb",
|
50
|
+
"spec/order_spec.rb",
|
51
|
+
"spec/spec_helper.rb",
|
52
|
+
"spec/support/factories.rb",
|
53
|
+
"spec/support/lib/activerecord_test_connector.rb",
|
54
|
+
"spec/support/matchers/be_in_order.rb",
|
55
|
+
"spec/support/models/developer.rb",
|
56
|
+
"spec/support/models/game.rb",
|
57
|
+
"spec/support/schema.rb"
|
58
|
+
]
|
59
|
+
|
60
|
+
if s.respond_to? :specification_version then
|
61
|
+
current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
|
62
|
+
s.specification_version = 3
|
63
|
+
|
64
|
+
if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
|
65
|
+
s.add_runtime_dependency(%q<activerecord>, ["~> 2.3.5"])
|
66
|
+
else
|
67
|
+
s.add_dependency(%q<activerecord>, ["~> 2.3.5"])
|
68
|
+
end
|
69
|
+
else
|
70
|
+
s.add_dependency(%q<activerecord>, ["~> 2.3.5"])
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
data/init.rb
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
require 'orderable'
|
data/lib/orderable.rb
ADDED
@@ -0,0 +1,101 @@
|
|
1
|
+
module Orderable
|
2
|
+
def self.included(base)
|
3
|
+
base.extend ActiveRecordAdditions
|
4
|
+
end
|
5
|
+
|
6
|
+
module ActiveRecordAdditions
|
7
|
+
def orderable(options = {})
|
8
|
+
allowed_attrs = options[:by] || {}
|
9
|
+
default_attr = options[:default] || allowed_attrs.first
|
10
|
+
|
11
|
+
named_scope :order, lambda {
|
12
|
+
|*attrs| do_order_by(attrs.shift, attrs.shift || {}, allowed_attrs, default_attr)
|
13
|
+
}
|
14
|
+
end
|
15
|
+
|
16
|
+
|
17
|
+
private
|
18
|
+
|
19
|
+
def do_order_by(attr_names, options, allowed_attrs, default_attr)
|
20
|
+
attr_names = [attr_names] unless attr_names.kind_of?(Array)
|
21
|
+
find_options = {}
|
22
|
+
|
23
|
+
attr_names.each do |attr_name|
|
24
|
+
attr_name, direction = attr_name.to_s.split('!')
|
25
|
+
direction ||= "asc"
|
26
|
+
|
27
|
+
unless allowed_attrs.include?(attr_name.to_sym)
|
28
|
+
attr_name = default_attr.to_s
|
29
|
+
end
|
30
|
+
|
31
|
+
find_options = merge_find_options(find_options, order_by_single_attribute(attr_name, direction, options))
|
32
|
+
end
|
33
|
+
|
34
|
+
find_options
|
35
|
+
end
|
36
|
+
|
37
|
+
|
38
|
+
def merge_find_options(old_find_options, other_find_options)
|
39
|
+
joins = old_find_options[:joins].to_s + " " + other_find_options[:joins].to_s
|
40
|
+
order = unless old_find_options[:order]
|
41
|
+
other_find_options[:order]
|
42
|
+
else
|
43
|
+
old_find_options[:order] + ", " + other_find_options[:order]
|
44
|
+
end
|
45
|
+
|
46
|
+
{:order => order, :joins => joins}
|
47
|
+
end
|
48
|
+
|
49
|
+
|
50
|
+
def order_by_single_attribute(attr_name, direction, options)
|
51
|
+
attr_name, association_name = attr_name.split('.').reverse
|
52
|
+
unless association_name.nil?
|
53
|
+
association_order(association_name, attr_name, direction, options)
|
54
|
+
else
|
55
|
+
{:order => sql_order_attribute(nil, nil, attr_name, direction, options)}
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
|
60
|
+
def association_order(association_name, attr_name, direction, options)
|
61
|
+
reflection = self.reflect_on_association(association_name.to_sym)
|
62
|
+
join_table = reflection.quoted_table_name
|
63
|
+
join_alias = reflection.table_name + "_join_for_order_by"
|
64
|
+
|
65
|
+
if reflection.macro == :has_one
|
66
|
+
fk_column = join_alias + "." + self.name.foreign_key
|
67
|
+
pk_column = self.quoted_table_name + "." + get_primary_key(self.name)
|
68
|
+
elsif reflection.macro == :belongs_to
|
69
|
+
fk_column = self.quoted_table_name + "." + reflection.association_foreign_key
|
70
|
+
pk_column = join_alias + "." + get_primary_key(reflection.klass.name)
|
71
|
+
end
|
72
|
+
|
73
|
+
joins = "LEFT JOIN #{join_table} #{join_alias} ON #{fk_column} = #{pk_column}"
|
74
|
+
order = sql_order_attribute(join_alias, reflection, attr_name, direction, options)
|
75
|
+
|
76
|
+
{:joins => joins, :order => order}
|
77
|
+
end
|
78
|
+
|
79
|
+
|
80
|
+
def sql_order_attribute(join_alias, reflection, attr_name, direction, options)
|
81
|
+
order_attribute = join_alias ? "#{join_alias}.#{attr_name}" : "#{self.quoted_table_name}.#{attr_name}"
|
82
|
+
|
83
|
+
unless options[:case_sensitive]
|
84
|
+
# Certain database adapters fail if we try to use LOWER() on non-string values
|
85
|
+
cols_hash = reflection ? reflection.klass.columns_hash : self.columns_hash
|
86
|
+
if cols_hash[attr_name].type == :string
|
87
|
+
order_attribute = "LOWER(#{order_attribute})"
|
88
|
+
end
|
89
|
+
else
|
90
|
+
if self.connection.adapter_name == "MySQL"
|
91
|
+
order_attribute = "BINARY #{order_attribute}"
|
92
|
+
end
|
93
|
+
end
|
94
|
+
|
95
|
+
order_attribute += " #{direction}"
|
96
|
+
order_attribute
|
97
|
+
end
|
98
|
+
end
|
99
|
+
end
|
100
|
+
|
101
|
+
ActiveRecord::Base.send(:include, Orderable)
|
@@ -0,0 +1,26 @@
|
|
1
|
+
require "spec_helper"
|
2
|
+
|
3
|
+
describe "order by attribute in belongs_to association" do
|
4
|
+
before(:each) do
|
5
|
+
@ea_redwood_shores = Factory.create(:developer, :name => "EA Redwood Shores")
|
6
|
+
@dead_space = Factory.create(:game, :name => "Dead Space", :developer => @ea_redwood_shores, :created_at => 10.minutes.ago)
|
7
|
+
|
8
|
+
@rocksteady_studios = Factory.create(:developer, :name => "Rocksteady Studios")
|
9
|
+
@batman = Factory.create(:game, :name => "Batman: Arkham Asylum", :developer => @rocksteady_studios, :created_at => 1.minute.ago)
|
10
|
+
|
11
|
+
@valve = Factory.create(:developer, :name => "Valve")
|
12
|
+
@half_life = Factory.create(:game, :name => "Half-Life", :developer => @valve, :created_at => Time.now)
|
13
|
+
end
|
14
|
+
|
15
|
+
it "should order by developer name given :'developer.name'" do
|
16
|
+
Game.order(:'developer.name').should be_in_order(:'developer.name')
|
17
|
+
end
|
18
|
+
|
19
|
+
it "should behave like order(:'developer.name') given ':'developer.name!asc'" do
|
20
|
+
Game.order(:'developer.name!asc').should be_in_order(:'developer.name')
|
21
|
+
end
|
22
|
+
|
23
|
+
it "should order by developer name in descending order given ':'developer.name!desc'" do
|
24
|
+
Game.order(:"developer.name!desc").reverse.should be_in_order(:'developer.name')
|
25
|
+
end
|
26
|
+
end
|
@@ -0,0 +1,56 @@
|
|
1
|
+
require "spec_helper"
|
2
|
+
|
3
|
+
describe "case-sensitivity of ordering" do
|
4
|
+
before(:each) do
|
5
|
+
|
6
|
+
end
|
7
|
+
|
8
|
+
it "should order in case-insensitive manner by default" do
|
9
|
+
games = [
|
10
|
+
Factory.create(:game, :name => "A"),
|
11
|
+
Factory.create(:game, :name => "a"),
|
12
|
+
Factory.create(:game, :name => "B")
|
13
|
+
]
|
14
|
+
|
15
|
+
Game.order(:name).should == games
|
16
|
+
end
|
17
|
+
|
18
|
+
|
19
|
+
it "should order in case-sensitive manner when :case_sensitive => true" do
|
20
|
+
games = [
|
21
|
+
Factory.create(:game, :name => "A"),
|
22
|
+
Factory.create(:game, :name => "B"),
|
23
|
+
Factory.create(:game, :name => "a")
|
24
|
+
]
|
25
|
+
|
26
|
+
Game.order(:name, :case_sensitive => true).should == games
|
27
|
+
end
|
28
|
+
|
29
|
+
it "should order associated model's attributes in case-insensitive-manner by default" do
|
30
|
+
a1 = Factory.create(:developer, :name => "A")
|
31
|
+
a2 = Factory.create(:developer, :name => "a")
|
32
|
+
b = Factory.create(:developer, :name => "B")
|
33
|
+
|
34
|
+
games = [
|
35
|
+
Factory.create(:game, :name => "game1", :developer => a1),
|
36
|
+
Factory.create(:game, :name => "game2", :developer => a2),
|
37
|
+
Factory.create(:game, :name => "game3", :developer => b)
|
38
|
+
]
|
39
|
+
|
40
|
+
Game.order(:"developer.name").should == games
|
41
|
+
end
|
42
|
+
|
43
|
+
it "should order associated model's attributes in case-sensitive manner when :case_sensitive => true" do
|
44
|
+
a1 = Factory.create(:developer, :name => "A")
|
45
|
+
a2 = Factory.create(:developer, :name => "a")
|
46
|
+
b = Factory.create(:developer, :name => "B")
|
47
|
+
|
48
|
+
games = [
|
49
|
+
Factory.create(:game, :name => "game1", :developer => a1),
|
50
|
+
Factory.create(:game, :name => "game3", :developer => b),
|
51
|
+
Factory.create(:game, :name => "game2", :developer => a2),
|
52
|
+
]
|
53
|
+
|
54
|
+
Game.order(:"developer.name", :case_sensitive => true).should == games
|
55
|
+
end
|
56
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
require "spec_helper"
|
2
|
+
|
3
|
+
describe "ordering by multiple attributes" do
|
4
|
+
before(:each) do
|
5
|
+
valve = Factory.create(:developer, :name => "Valve")
|
6
|
+
portal = Factory.create(:game, :name => "Portal", :developer => valve)
|
7
|
+
half_life = Factory.create(:game, :name => "Half-Life", :developer => valve)
|
8
|
+
|
9
|
+
ea_redwood_shores = Factory.create(:developer, :name => "EA Redwood Shores")
|
10
|
+
the_godfather = Factory.create(:game, :name => "The Godfather", :developer => ea_redwood_shores)
|
11
|
+
dead_space = Factory.create(:game, :name => "Dead Space", :developer => ea_redwood_shores)
|
12
|
+
|
13
|
+
@games_in_order = [dead_space, the_godfather, half_life, portal]
|
14
|
+
end
|
15
|
+
|
16
|
+
it "should order by all attributes in given list" do
|
17
|
+
Game.order([:"developer.name", :name]).should == @games_in_order
|
18
|
+
end
|
19
|
+
end
|
data/spec/order_spec.rb
ADDED
@@ -0,0 +1,29 @@
|
|
1
|
+
require "spec_helper"
|
2
|
+
|
3
|
+
describe "order" do
|
4
|
+
before(:each) do
|
5
|
+
@dead_space = Factory.create(:game, :name => "Dead Space", :created_at => 10.minutes.ago)
|
6
|
+
@batman = Factory.create(:game, :name => "Batman: Arkham Asylum", :created_at => 1.minute.ago)
|
7
|
+
@half_life = Factory.create(:game, :name => "Half-Life", :created_at => Time.now)
|
8
|
+
end
|
9
|
+
|
10
|
+
it "should order by name given ':name' symbol" do
|
11
|
+
Game.order(:name).should be_in_order(:name)
|
12
|
+
end
|
13
|
+
|
14
|
+
it "should order by name given 'name' string" do
|
15
|
+
Game.order("name").should be_in_order(:name)
|
16
|
+
end
|
17
|
+
|
18
|
+
it "should behave like order(:name) given ':name!asc'" do
|
19
|
+
Game.order(:"name!asc").should be_in_order(:name)
|
20
|
+
end
|
21
|
+
|
22
|
+
it "should order by name in descending order given ':name!desc'" do
|
23
|
+
Game.order(:"name!desc").reverse.should be_in_order(:name)
|
24
|
+
end
|
25
|
+
|
26
|
+
it "should use default ordering if the model is not orderable by the given attribute" do
|
27
|
+
Game.order(:updated_at).should be_in_order(:created_at)
|
28
|
+
end
|
29
|
+
end
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,23 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'bundler/setup'
|
3
|
+
Bundler.setup(:default, :test)
|
4
|
+
|
5
|
+
require 'active_record'
|
6
|
+
require File.join(File.dirname(__FILE__), '..', 'init')
|
7
|
+
require File.join(File.dirname(__FILE__), 'support', 'lib', 'activerecord_test_connector')
|
8
|
+
ActiveRecordTestConnector.setup
|
9
|
+
|
10
|
+
require 'spec'
|
11
|
+
require 'active_support'
|
12
|
+
require 'factory_girl'
|
13
|
+
|
14
|
+
# Requires supporting files with custom matchers and macros, etc,
|
15
|
+
# in ./support/ and its subdirectories.
|
16
|
+
Dir[File.expand_path(File.join(File.dirname(__FILE__),'support','**','*.rb'))].each {|f| require f}
|
17
|
+
|
18
|
+
Spec::Runner.configure do |config|
|
19
|
+
config.before(:each) do
|
20
|
+
Game.delete_all
|
21
|
+
Developer.delete_all
|
22
|
+
end
|
23
|
+
end
|
@@ -0,0 +1,60 @@
|
|
1
|
+
require 'active_record'
|
2
|
+
require 'active_record/version'
|
3
|
+
require 'active_record/fixtures'
|
4
|
+
|
5
|
+
# Taken from will_paginate (http://github.com/mislav/will_paginate/)
|
6
|
+
# with small modifications
|
7
|
+
class ActiveRecordTestConnector
|
8
|
+
cattr_accessor :able_to_connect
|
9
|
+
cattr_accessor :connected
|
10
|
+
|
11
|
+
MODELS_PATH = File.join(File.dirname(__FILE__), '..', 'models')
|
12
|
+
|
13
|
+
# Set our defaults
|
14
|
+
self.connected = false
|
15
|
+
self.able_to_connect = true
|
16
|
+
|
17
|
+
def self.setup
|
18
|
+
unless self.connected || !self.able_to_connect
|
19
|
+
setup_connection
|
20
|
+
load_schema
|
21
|
+
add_load_path MODELS_PATH
|
22
|
+
self.connected = true
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
private
|
27
|
+
|
28
|
+
def self.add_load_path(path)
|
29
|
+
dep = defined?(ActiveSupport::Dependencies) ? ActiveSupport::Dependencies : ::Dependencies
|
30
|
+
autoload_paths = dep.respond_to?(:autoload_paths) ? dep.autoload_paths : dep.load_paths
|
31
|
+
autoload_paths.unshift path
|
32
|
+
end
|
33
|
+
|
34
|
+
def self.setup_connection
|
35
|
+
db = ENV['DB'].blank?? 'sqlite3' : ENV['DB']
|
36
|
+
|
37
|
+
configurations = YAML.load_file(File.join(File.dirname(__FILE__), '..', 'database.yml'))
|
38
|
+
raise "no configuration for '#{db}'" unless configurations.key? db
|
39
|
+
configuration = configurations[db]
|
40
|
+
|
41
|
+
ActiveRecord::Base.logger = Logger.new(STDOUT) if $0 == 'irb'
|
42
|
+
puts "using #{configuration['adapter']} adapter" unless ENV['DB'].blank?
|
43
|
+
|
44
|
+
gem 'sqlite3-ruby' if 'sqlite3' == db
|
45
|
+
|
46
|
+
ActiveRecord::Base.establish_connection(configuration)
|
47
|
+
ActiveRecord::Base.configurations = { db => configuration }
|
48
|
+
|
49
|
+
unless Object.const_defined?(:QUOTED_TYPE)
|
50
|
+
Object.send :const_set, :QUOTED_TYPE, ActiveRecord::Base.connection.quote_column_name('type')
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
def self.load_schema
|
55
|
+
ActiveRecord::Base.silence do
|
56
|
+
ActiveRecord::Migration.verbose = false
|
57
|
+
load File.join(File.dirname(__FILE__), '..', 'schema.rb')
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
Spec::Matchers.define :be_in_order do |attr_name|
|
2
|
+
match do |results|
|
3
|
+
ret_val = true
|
4
|
+
previous = nil
|
5
|
+
results.each do |result|
|
6
|
+
unless previous.nil?
|
7
|
+
unless attr_value(result, attr_name) >= attr_value(previous, attr_name)
|
8
|
+
ret_val = false
|
9
|
+
break
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
previous = result
|
14
|
+
end
|
15
|
+
|
16
|
+
ret_val
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
def attr_value(obj, attr_name)
|
21
|
+
current = obj
|
22
|
+
|
23
|
+
attr_name.to_s.split('.').each do |name|
|
24
|
+
current = current.send(name.to_sym)
|
25
|
+
end
|
26
|
+
|
27
|
+
current
|
28
|
+
end
|
metadata
ADDED
@@ -0,0 +1,112 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: ar_orderable
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
hash: 27
|
5
|
+
prerelease: false
|
6
|
+
segments:
|
7
|
+
- 0
|
8
|
+
- 1
|
9
|
+
- 0
|
10
|
+
version: 0.1.0
|
11
|
+
platform: ruby
|
12
|
+
authors:
|
13
|
+
- "Mikko Nyl\xC3\xA9n"
|
14
|
+
autorequire:
|
15
|
+
bindir: bin
|
16
|
+
cert_chain: []
|
17
|
+
|
18
|
+
date: 2010-09-19 00:00:00 +03:00
|
19
|
+
default_executable:
|
20
|
+
dependencies:
|
21
|
+
- !ruby/object:Gem::Dependency
|
22
|
+
name: activerecord
|
23
|
+
prerelease: false
|
24
|
+
requirement: &id001 !ruby/object:Gem::Requirement
|
25
|
+
none: false
|
26
|
+
requirements:
|
27
|
+
- - ~>
|
28
|
+
- !ruby/object:Gem::Version
|
29
|
+
hash: 9
|
30
|
+
segments:
|
31
|
+
- 2
|
32
|
+
- 3
|
33
|
+
- 5
|
34
|
+
version: 2.3.5
|
35
|
+
type: :runtime
|
36
|
+
version_requirements: *id001
|
37
|
+
description: ar_orderable adds a consistent way to order results at database level using ActiveRecord. Supports ordering by multiple attributes and by associated model's attributes.
|
38
|
+
email: mikko.nylen@gmail.com
|
39
|
+
executables: []
|
40
|
+
|
41
|
+
extensions: []
|
42
|
+
|
43
|
+
extra_rdoc_files:
|
44
|
+
- README.textile
|
45
|
+
files:
|
46
|
+
- .gitignore
|
47
|
+
- .rvmrc
|
48
|
+
- Gemfile
|
49
|
+
- README.textile
|
50
|
+
- Rakefile
|
51
|
+
- VERSION
|
52
|
+
- ar_orderable.gemspec
|
53
|
+
- init.rb
|
54
|
+
- lib/orderable.rb
|
55
|
+
- spec/order_belongs_to_association_spec.rb
|
56
|
+
- spec/order_case_sensitivity_spec.rb
|
57
|
+
- spec/order_multiple_attributes_spec.rb
|
58
|
+
- spec/order_spec.rb
|
59
|
+
- spec/spec_helper.rb
|
60
|
+
- spec/support/database.yml
|
61
|
+
- spec/support/factories.rb
|
62
|
+
- spec/support/lib/activerecord_test_connector.rb
|
63
|
+
- spec/support/matchers/be_in_order.rb
|
64
|
+
- spec/support/models/developer.rb
|
65
|
+
- spec/support/models/game.rb
|
66
|
+
- spec/support/schema.rb
|
67
|
+
has_rdoc: true
|
68
|
+
homepage: http://github.com/mnylen/ar_orderable
|
69
|
+
licenses: []
|
70
|
+
|
71
|
+
post_install_message:
|
72
|
+
rdoc_options:
|
73
|
+
- --charset=UTF-8
|
74
|
+
require_paths:
|
75
|
+
- lib
|
76
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
77
|
+
none: false
|
78
|
+
requirements:
|
79
|
+
- - ">="
|
80
|
+
- !ruby/object:Gem::Version
|
81
|
+
hash: 3
|
82
|
+
segments:
|
83
|
+
- 0
|
84
|
+
version: "0"
|
85
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
86
|
+
none: false
|
87
|
+
requirements:
|
88
|
+
- - ">="
|
89
|
+
- !ruby/object:Gem::Version
|
90
|
+
hash: 3
|
91
|
+
segments:
|
92
|
+
- 0
|
93
|
+
version: "0"
|
94
|
+
requirements: []
|
95
|
+
|
96
|
+
rubyforge_project:
|
97
|
+
rubygems_version: 1.3.7
|
98
|
+
signing_key:
|
99
|
+
specification_version: 3
|
100
|
+
summary: A small ActiveRecord addition that makes ordering of results easier and cleaner
|
101
|
+
test_files:
|
102
|
+
- spec/order_belongs_to_association_spec.rb
|
103
|
+
- spec/order_case_sensitivity_spec.rb
|
104
|
+
- spec/order_multiple_attributes_spec.rb
|
105
|
+
- spec/order_spec.rb
|
106
|
+
- spec/spec_helper.rb
|
107
|
+
- spec/support/factories.rb
|
108
|
+
- spec/support/lib/activerecord_test_connector.rb
|
109
|
+
- spec/support/matchers/be_in_order.rb
|
110
|
+
- spec/support/models/developer.rb
|
111
|
+
- spec/support/models/game.rb
|
112
|
+
- spec/support/schema.rb
|