convenient_scopes 0.4.0
Sign up to get free protection for your applications and to get access to all the features.
- data/.document +5 -0
- data/.gitignore +21 -0
- data/LICENSE +20 -0
- data/README.rdoc +19 -0
- data/Rakefile +55 -0
- data/VERSION +1 -0
- data/convenient_scopes.gemspec +65 -0
- data/lib/convenient_scopes.rb +182 -0
- data/test/helper.rb +48 -0
- data/test/test_all_and_any_conditions.rb +19 -0
- data/test/test_associations.rb +53 -0
- data/test/test_conditions.rb +70 -0
- data/test/test_ordering.rb +27 -0
- metadata +116 -0
data/.document
ADDED
data/.gitignore
ADDED
data/LICENSE
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
Copyright (c) 2009 Ivan Schneider
|
2
|
+
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
4
|
+
a copy of this software and associated documentation files (the
|
5
|
+
"Software"), to deal in the Software without restriction, including
|
6
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
7
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
8
|
+
permit persons to whom the Software is furnished to do so, subject to
|
9
|
+
the following conditions:
|
10
|
+
|
11
|
+
The above copyright notice and this permission notice shall be
|
12
|
+
included in all copies or substantial portions of the Software.
|
13
|
+
|
14
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
15
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
16
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
17
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
18
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
19
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
20
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.rdoc
ADDED
@@ -0,0 +1,19 @@
|
|
1
|
+
= convenient_scopes
|
2
|
+
|
3
|
+
Dynamic scopes by convention for ActiveRecord 3.
|
4
|
+
|
5
|
+
Pretty much the same API as searchlogic except it's compatible with ActiveRecord 3, unlike searchlogic as of now. The whole feature set of searchlogic isn't implemented yet in convenient_scopes though.
|
6
|
+
|
7
|
+
== Note on Patches/Pull Requests
|
8
|
+
|
9
|
+
* Fork the project.
|
10
|
+
* Make your feature addition or bug fix.
|
11
|
+
* Add tests for it. This is important so I don't break it in a
|
12
|
+
future version unintentionally.
|
13
|
+
* Commit, do not mess with rakefile, version, or history.
|
14
|
+
(if you want to have your own version, that is fine but bump version in a commit by itself I can ignore when I pull)
|
15
|
+
* Send me a pull request. Bonus points for topic branches.
|
16
|
+
|
17
|
+
== Copyright
|
18
|
+
|
19
|
+
Copyright (c) 2010 Ivan Schneider. See LICENSE for details.
|
data/Rakefile
ADDED
@@ -0,0 +1,55 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'rake'
|
3
|
+
|
4
|
+
begin
|
5
|
+
require 'jeweler'
|
6
|
+
Jeweler::Tasks.new do |gem|
|
7
|
+
gem.name = "convenient_scopes"
|
8
|
+
gem.summary = %Q{Dynamic scopes by convention for ActiveRecord 3}
|
9
|
+
gem.description = %Q{Dynamic scopes by convention for ActiveRecord 3}
|
10
|
+
gem.email = "isc@massivebraingames.com"
|
11
|
+
gem.homepage = "http://github.com/isc/convenient_scopes"
|
12
|
+
gem.authors = ["Ivan Schneider"]
|
13
|
+
gem.add_runtime_dependency "activerecord", ">= 3.0.0.beta4"
|
14
|
+
gem.add_development_dependency "shoulda", ">= 0"
|
15
|
+
gem.add_development_dependency "sqlite3-ruby"
|
16
|
+
# gem is a Gem::Specification... see http://www.rubygems.org/read/chapter/20 for additional settings
|
17
|
+
end
|
18
|
+
Jeweler::GemcutterTasks.new
|
19
|
+
rescue LoadError
|
20
|
+
puts "Jeweler (or a dependency) not available. Install it with: gem install jeweler"
|
21
|
+
end
|
22
|
+
|
23
|
+
require 'rake/testtask'
|
24
|
+
Rake::TestTask.new(:test) do |test|
|
25
|
+
test.libs << 'lib' << 'test'
|
26
|
+
test.pattern = 'test/**/test_*.rb'
|
27
|
+
test.verbose = true
|
28
|
+
end
|
29
|
+
|
30
|
+
begin
|
31
|
+
require 'rcov/rcovtask'
|
32
|
+
Rcov::RcovTask.new do |test|
|
33
|
+
test.libs << 'test'
|
34
|
+
test.pattern = 'test/**/test_*.rb'
|
35
|
+
test.verbose = true
|
36
|
+
end
|
37
|
+
rescue LoadError
|
38
|
+
task :rcov do
|
39
|
+
abort "RCov is not available. In order to run rcov, you must: sudo gem install spicycode-rcov"
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
task :test => :check_dependencies
|
44
|
+
|
45
|
+
task :default => :test
|
46
|
+
|
47
|
+
require 'rake/rdoctask'
|
48
|
+
Rake::RDocTask.new do |rdoc|
|
49
|
+
version = File.exist?('VERSION') ? File.read('VERSION') : ""
|
50
|
+
|
51
|
+
rdoc.rdoc_dir = 'rdoc'
|
52
|
+
rdoc.title = "convenient_scopes #{version}"
|
53
|
+
rdoc.rdoc_files.include('README*')
|
54
|
+
rdoc.rdoc_files.include('lib/**/*.rb')
|
55
|
+
end
|
data/VERSION
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
0.4.0
|
@@ -0,0 +1,65 @@
|
|
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{convenient_scopes}
|
8
|
+
s.version = "0.4.0"
|
9
|
+
|
10
|
+
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
11
|
+
s.authors = ["Ivan Schneider"]
|
12
|
+
s.date = %q{2010-07-25}
|
13
|
+
s.description = %q{Dynamic scopes by convention for ActiveRecord 3}
|
14
|
+
s.email = %q{isc@massivebraingames.com}
|
15
|
+
s.extra_rdoc_files = [
|
16
|
+
"LICENSE",
|
17
|
+
"README.rdoc"
|
18
|
+
]
|
19
|
+
s.files = [
|
20
|
+
".document",
|
21
|
+
".gitignore",
|
22
|
+
"LICENSE",
|
23
|
+
"README.rdoc",
|
24
|
+
"Rakefile",
|
25
|
+
"VERSION",
|
26
|
+
"convenient_scopes.gemspec",
|
27
|
+
"lib/convenient_scopes.rb",
|
28
|
+
"test/helper.rb",
|
29
|
+
"test/test_associations.rb",
|
30
|
+
"test/test_conditions.rb",
|
31
|
+
"test/test_ordering.rb"
|
32
|
+
]
|
33
|
+
s.homepage = %q{http://github.com/isc/convenient_scopes}
|
34
|
+
s.rdoc_options = ["--charset=UTF-8"]
|
35
|
+
s.require_paths = ["lib"]
|
36
|
+
s.rubygems_version = %q{1.3.6}
|
37
|
+
s.summary = %q{Dynamic scopes by convention for ActiveRecord 3}
|
38
|
+
s.test_files = [
|
39
|
+
"test/helper.rb",
|
40
|
+
"test/test_all_and_any_conditions.rb",
|
41
|
+
"test/test_associations.rb",
|
42
|
+
"test/test_conditions.rb",
|
43
|
+
"test/test_ordering.rb"
|
44
|
+
]
|
45
|
+
|
46
|
+
if s.respond_to? :specification_version then
|
47
|
+
current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
|
48
|
+
s.specification_version = 3
|
49
|
+
|
50
|
+
if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then
|
51
|
+
s.add_runtime_dependency(%q<activerecord>, [">= 3.0.0.beta4"])
|
52
|
+
s.add_development_dependency(%q<shoulda>, [">= 0"])
|
53
|
+
s.add_development_dependency(%q<sqlite3-ruby>, [">= 0"])
|
54
|
+
else
|
55
|
+
s.add_dependency(%q<activerecord>, [">= 3.0.0.beta4"])
|
56
|
+
s.add_dependency(%q<shoulda>, [">= 0"])
|
57
|
+
s.add_dependency(%q<sqlite3-ruby>, [">= 0"])
|
58
|
+
end
|
59
|
+
else
|
60
|
+
s.add_dependency(%q<activerecord>, [">= 3.0.0.beta4"])
|
61
|
+
s.add_dependency(%q<shoulda>, [">= 0"])
|
62
|
+
s.add_dependency(%q<sqlite3-ruby>, [">= 0"])
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
@@ -0,0 +1,182 @@
|
|
1
|
+
module ConvenientScopes
|
2
|
+
|
3
|
+
def method_missing(name, *args, &block)
|
4
|
+
if scope_data = (define_scope name)
|
5
|
+
scope name, convert_to_scope_arg(scope_data)
|
6
|
+
return send name, *args, &block
|
7
|
+
else
|
8
|
+
super
|
9
|
+
end
|
10
|
+
end
|
11
|
+
|
12
|
+
module Conditions
|
13
|
+
|
14
|
+
def equals_scope name
|
15
|
+
return unless (column = match_suffix_and_column_name name, %w(equals eq is))
|
16
|
+
lambda {|value| where(column => value)}
|
17
|
+
end
|
18
|
+
|
19
|
+
def does_not_equal_scope name
|
20
|
+
match_and_define_scope name, %w(does_not_equal doesnt_equal ne is_not), "%s != ?"
|
21
|
+
end
|
22
|
+
|
23
|
+
def less_than_scope name
|
24
|
+
match_and_define_scope name, %w(less_than lt before), "%s < ?"
|
25
|
+
end
|
26
|
+
|
27
|
+
def less_than_or_equal_scope name
|
28
|
+
match_and_define_scope name, %w(less_than_or_equal lte), "%s <= ?"
|
29
|
+
end
|
30
|
+
|
31
|
+
def greater_than_scope name
|
32
|
+
match_and_define_scope name, %w(greater_than gt after), "%s > ?"
|
33
|
+
end
|
34
|
+
|
35
|
+
def greater_than_or_equal_scope name
|
36
|
+
match_and_define_scope name, %w(greater_than_or_equal gte), "%s >= ?"
|
37
|
+
end
|
38
|
+
|
39
|
+
def like_scope name
|
40
|
+
match_and_define_scope name, %w(like matches contains includes), "%s like ?", "%%%s%%"
|
41
|
+
end
|
42
|
+
|
43
|
+
def not_like_scope name
|
44
|
+
suffixes = %w(not_like does_not_match doesnt_match does_not_contain doesnt_contain does_not_include doesnt_include)
|
45
|
+
match_and_define_scope name, suffixes, "%s not like ?", "%%%s%%"
|
46
|
+
end
|
47
|
+
|
48
|
+
def begins_with_scope name
|
49
|
+
match_and_define_scope name, %w(begins_with bw starts_with sw), "%s like ?", "%s%%"
|
50
|
+
end
|
51
|
+
|
52
|
+
def not_begin_with_scope name
|
53
|
+
suffixes = %w(not_begin_with does_not_begin_with doesnt_begin_with does_not_start_with doesnt_start_with)
|
54
|
+
match_and_define_scope name, suffixes, "%s not like ?", "%s%%"
|
55
|
+
end
|
56
|
+
|
57
|
+
def ends_with_scope name
|
58
|
+
match_and_define_scope name, %w(ends_with ew), "%s like ?", "%%%s"
|
59
|
+
end
|
60
|
+
|
61
|
+
def not_end_with_scope name
|
62
|
+
match_and_define_scope name, %w(not_end_with does_not_end_with doesnt_end_with), "%s not like ?", "%%%s"
|
63
|
+
end
|
64
|
+
|
65
|
+
def null_scope name
|
66
|
+
match_and_define_scope_without_value name, %w(null nil missing), "%s is null"
|
67
|
+
end
|
68
|
+
|
69
|
+
def not_null_scope name
|
70
|
+
match_and_define_scope_without_value name, %w(not_null not_nil not_missing), "%s is not null"
|
71
|
+
end
|
72
|
+
|
73
|
+
def boolean_column_scope name
|
74
|
+
return unless column_names.include? name.to_s
|
75
|
+
return unless boolean_column? name
|
76
|
+
where(name => true)
|
77
|
+
end
|
78
|
+
|
79
|
+
def negative_boolean_column_scope name
|
80
|
+
str_name = name.to_s
|
81
|
+
return unless str_name.gsub!(/^not_/, '')
|
82
|
+
return unless column_names.include? str_name
|
83
|
+
return unless boolean_column? str_name
|
84
|
+
where(str_name => false)
|
85
|
+
end
|
86
|
+
|
87
|
+
end
|
88
|
+
|
89
|
+
include Conditions
|
90
|
+
|
91
|
+
module Ordering
|
92
|
+
|
93
|
+
def ascend_by_scope name
|
94
|
+
ordering_scope name, /^ascend_by_/, 'asc'
|
95
|
+
end
|
96
|
+
|
97
|
+
def descend_by_scope name
|
98
|
+
ordering_scope name, /^descend_by_/, 'desc'
|
99
|
+
end
|
100
|
+
|
101
|
+
end
|
102
|
+
|
103
|
+
def ordering_scope name, prefix, direction
|
104
|
+
str_name = name.to_s
|
105
|
+
return unless str_name.gsub!(prefix, '')
|
106
|
+
determine_order_scope_data str_name, direction
|
107
|
+
end
|
108
|
+
|
109
|
+
def determine_order_scope_data name, direction
|
110
|
+
if column_names.include? name.to_s
|
111
|
+
order("#{quoted_table_name}.#{name} #{direction}")
|
112
|
+
elsif assoc = (possible_association_for_scope name)
|
113
|
+
next_scope = name.to_s.split("#{assoc.name}_").last.to_sym # age
|
114
|
+
scope_arg = assoc.klass.determine_order_scope_data next_scope, direction
|
115
|
+
scope_arg.is_a?(Array) ? [assoc.name] + scope_arg : [assoc.name, scope_arg] if scope_arg
|
116
|
+
end
|
117
|
+
end
|
118
|
+
|
119
|
+
include Ordering
|
120
|
+
|
121
|
+
def association_scope name
|
122
|
+
return unless assoc = (possible_association_for_scope name)
|
123
|
+
next_scope = name.to_s.split("#{assoc.name}_").last.to_sym
|
124
|
+
scope_arg = (assoc.klass.define_scope next_scope) || assoc.klass.scopes[next_scope]
|
125
|
+
scope_arg.is_a?(Array) ? [assoc.name] + scope_arg : [assoc.name, scope_arg] if scope_arg
|
126
|
+
end
|
127
|
+
|
128
|
+
def possible_association_for_scope name
|
129
|
+
reflect_on_all_associations.detect {|assoc| name.to_s.starts_with? assoc.name.to_s}
|
130
|
+
end
|
131
|
+
|
132
|
+
def define_scope name
|
133
|
+
[Conditions, Ordering].map(&:instance_methods).flatten.each do |scope_type|
|
134
|
+
if scope_arg = (send scope_type.to_sym, name)
|
135
|
+
return scope_arg unless scope_arg.nil?
|
136
|
+
end
|
137
|
+
end
|
138
|
+
association_scope name
|
139
|
+
end
|
140
|
+
|
141
|
+
def match_and_define_scope name, suffixes, sql_format, value_format = nil
|
142
|
+
return unless (column = match_suffix_and_column_name name, suffixes)
|
143
|
+
sql = formatted_sql column, sql_format
|
144
|
+
lambda {|value| where([sql, value_format ? (value_format % value) : value])}
|
145
|
+
end
|
146
|
+
|
147
|
+
def match_and_define_scope_without_value name, suffixes, sql_format
|
148
|
+
return unless (column = match_suffix_and_column_name name, suffixes)
|
149
|
+
where(formatted_sql column, sql_format)
|
150
|
+
end
|
151
|
+
|
152
|
+
def formatted_sql column, sql_format
|
153
|
+
sql = sql_format % "#{quoted_table_name}.#{column}"
|
154
|
+
end
|
155
|
+
|
156
|
+
def match_suffix_and_column_name name, suffixes
|
157
|
+
str_name = name.to_s
|
158
|
+
regexp_str = suffixes.map {|suffix| "(_#{suffix})"}.join('|') + '$'
|
159
|
+
return unless str_name.gsub!(Regexp.new(regexp_str), '')
|
160
|
+
return unless column_names.include? str_name
|
161
|
+
str_name
|
162
|
+
end
|
163
|
+
|
164
|
+
def boolean_column? name
|
165
|
+
columns.detect {|c|c.name == name.to_s}.type == :boolean
|
166
|
+
end
|
167
|
+
|
168
|
+
def convert_to_scope_arg scope_data
|
169
|
+
return scope_data unless scope_data.is_a? Array
|
170
|
+
relation_or_proc = scope_data.pop
|
171
|
+
joins_arg = (scope_data.size == 1) ? scope_data.first : {scope_data.first => scope_data.last}
|
172
|
+
if relation_or_proc.is_a? ActiveRecord::Relation
|
173
|
+
relation_or_proc.joins joins_arg
|
174
|
+
else
|
175
|
+
lambda {|*value| relation_or_proc.call(*value).joins joins_arg }
|
176
|
+
end
|
177
|
+
end
|
178
|
+
|
179
|
+
end
|
180
|
+
|
181
|
+
ActiveRecord::Base.extend ConvenientScopes
|
182
|
+
ActiveRecord::Relation.send :include, ConvenientScopes
|
data/test/helper.rb
ADDED
@@ -0,0 +1,48 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'test/unit'
|
3
|
+
require 'shoulda'
|
4
|
+
require 'active_record'
|
5
|
+
|
6
|
+
$LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
|
7
|
+
$LOAD_PATH.unshift(File.dirname(__FILE__))
|
8
|
+
require 'convenient_scopes'
|
9
|
+
|
10
|
+
ActiveRecord::Base.establish_connection(:adapter => "sqlite3", :database => ":memory:")
|
11
|
+
class User < ActiveRecord::Base
|
12
|
+
has_many :comments
|
13
|
+
belongs_to :group
|
14
|
+
end
|
15
|
+
class Group < ActiveRecord::Base
|
16
|
+
has_many :users
|
17
|
+
end
|
18
|
+
class Comment < ActiveRecord::Base
|
19
|
+
belongs_to :user
|
20
|
+
end
|
21
|
+
|
22
|
+
class Test::Unit::TestCase
|
23
|
+
def teardown
|
24
|
+
User.delete_all
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
ActiveRecord::Base.configurations = true
|
29
|
+
ActiveRecord::Schema.verbose = false
|
30
|
+
ActiveRecord::Schema.define(:version => 1) do
|
31
|
+
create_table :users do |t|
|
32
|
+
t.string :pseudo, :first_name, :last_name
|
33
|
+
t.integer :group_id, :age
|
34
|
+
t.datetime :activated_at
|
35
|
+
t.boolean :admin
|
36
|
+
t.timestamps
|
37
|
+
end
|
38
|
+
create_table :groups do |t|
|
39
|
+
t.string :name
|
40
|
+
t.timestamps
|
41
|
+
end
|
42
|
+
create_table :comments do |t|
|
43
|
+
t.string :body
|
44
|
+
t.integer :user_id
|
45
|
+
t.boolean :published
|
46
|
+
t.timestamps
|
47
|
+
end
|
48
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
require 'helper'
|
2
|
+
|
3
|
+
class TestAllAndAnyConditions < Test::Unit::TestCase
|
4
|
+
|
5
|
+
context "convenient_scopes" do
|
6
|
+
|
7
|
+
setup do
|
8
|
+
@bob = User.create :pseudo => 'Bob Larchi'
|
9
|
+
@slim = User.create :pseudo => 'Slim Babine'
|
10
|
+
end
|
11
|
+
|
12
|
+
should "handle conditions scopes suffixed by any" do
|
13
|
+
flunk "not implemented yet"
|
14
|
+
assert_equal [@bob, @slim], User.pseudo_like_any('Bob', 'Slim')
|
15
|
+
end
|
16
|
+
|
17
|
+
end
|
18
|
+
|
19
|
+
end
|
@@ -0,0 +1,53 @@
|
|
1
|
+
require 'helper'
|
2
|
+
|
3
|
+
class TestAssociations < Test::Unit::TestCase
|
4
|
+
|
5
|
+
context "convenient_scopes" do
|
6
|
+
setup do
|
7
|
+
@manager_group = Group.create :name => 'Managers'
|
8
|
+
@bob = User.create :comments => [(Comment.new :body => 'Yo', :published => false, :created_at => 1.week.ago)], :group => @manager_group
|
9
|
+
@dev_group = Group.create :name => 'Developers'
|
10
|
+
@slim = User.create :comments => [(Comment.new :body => 'Bye', :published => false, :created_at => 10.minutes.ago),
|
11
|
+
(Comment.new :body => 'Hello', :published => true, :created_at => 2.days.ago)],
|
12
|
+
:group => @dev_group
|
13
|
+
end
|
14
|
+
|
15
|
+
should "not catch everything" do
|
16
|
+
assert_raise NoMethodError do
|
17
|
+
User.comment_body_is('Yo')
|
18
|
+
end
|
19
|
+
assert_raise NoMethodError do
|
20
|
+
User.comments_synopsis_eq('Yo')
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
should "handle has_many association + attribute conditions" do
|
25
|
+
assert_equal [@bob], User.comments_body_equals('Yo')
|
26
|
+
assert_equal [@slim], User.comments_body_starts_with('He')
|
27
|
+
assert_equal [@bob], User.comments_id_is(@bob.comments.first.id)
|
28
|
+
assert_equal [@slim], User.comments_id_is(@slim.comments.last.id)
|
29
|
+
assert_equal [@bob], User.comments_created_at_before(3.days.ago)
|
30
|
+
end
|
31
|
+
|
32
|
+
should "handle has many association + boolean column" do
|
33
|
+
assert_equal [@slim], User.comments_published
|
34
|
+
end
|
35
|
+
|
36
|
+
should "handle belongs_to association" do
|
37
|
+
assert_equal [@bob], User.group_name_is('Managers')
|
38
|
+
assert_equal [@slim], User.group_name_matches('velo')
|
39
|
+
end
|
40
|
+
|
41
|
+
should "handle two levels of association" do
|
42
|
+
assert_equal [@dev_group], Group.users_comments_published
|
43
|
+
end
|
44
|
+
|
45
|
+
should "be able to leverage a named scope on an association" do
|
46
|
+
Comment.scope :recent, Comment.created_at_after(1.hour.ago).created_at_not_nil
|
47
|
+
assert_equal [@slim], User.comments_recent
|
48
|
+
assert_equal [@dev_group], Group.users_comments_recent
|
49
|
+
end
|
50
|
+
|
51
|
+
end
|
52
|
+
|
53
|
+
end
|
@@ -0,0 +1,70 @@
|
|
1
|
+
require 'helper'
|
2
|
+
|
3
|
+
class TestConditions < Test::Unit::TestCase
|
4
|
+
context "Given two users" do
|
5
|
+
setup do
|
6
|
+
@bob = User.create :pseudo => 'Bob', :first_name => 'Robert', :age => 37,
|
7
|
+
:activated_at => 37.hours.ago, :admin => true
|
8
|
+
@slim = User.create :pseudo => 'Slim', :first_name => 'Angelo', :age => 12,
|
9
|
+
:activated_at => nil, :admin => false
|
10
|
+
end
|
11
|
+
|
12
|
+
should "equals scope" do
|
13
|
+
assert_raise NoMethodError do
|
14
|
+
User.blabla_eq('Bob')
|
15
|
+
end
|
16
|
+
assert_equal [@bob], User.pseudo_eq('Bob')
|
17
|
+
assert_equal [@slim], User.pseudo_is('Slim')
|
18
|
+
assert_equal [@bob], User.first_name_is('Robert')
|
19
|
+
end
|
20
|
+
|
21
|
+
should "equals scope on a relation" do
|
22
|
+
assert_equal [@bob], User.order('age').pseudo_eq('Bob')
|
23
|
+
end
|
24
|
+
|
25
|
+
should "not equals scope" do
|
26
|
+
assert_equal [@bob], User.pseudo_is_not('Slim')
|
27
|
+
assert_equal [@bob], User.first_name_does_not_equal('Angelo')
|
28
|
+
end
|
29
|
+
|
30
|
+
should "less than (or equal)? scope" do
|
31
|
+
assert_equal [@slim], User.age_lt(37)
|
32
|
+
assert_equal [@slim], User.age_less_than_or_equal(12)
|
33
|
+
end
|
34
|
+
|
35
|
+
should "greater than (or equal)? scope" do
|
36
|
+
assert_equal [@bob], User.age_greater_than(12)
|
37
|
+
assert_equal [@bob], User.age_gte(37)
|
38
|
+
assert_equal [@bob], User.activated_at_after(40.hours.ago)
|
39
|
+
end
|
40
|
+
|
41
|
+
should "like scope" do
|
42
|
+
assert_equal [@slim], User.first_name_matches('nge')
|
43
|
+
end
|
44
|
+
|
45
|
+
should "not like scope" do
|
46
|
+
assert_equal [@slim], User.pseudo_not_like('o')
|
47
|
+
end
|
48
|
+
|
49
|
+
should "begins / ends with scope" do
|
50
|
+
assert_equal [@bob], User.first_name_starts_with('Rob')
|
51
|
+
assert_equal [@slim], User.first_name_ends_with('o')
|
52
|
+
end
|
53
|
+
|
54
|
+
should "not begins / ends with scope" do
|
55
|
+
assert_equal [@slim], User.first_name_does_not_start_with('Rob')
|
56
|
+
assert_equal [@bob], User.first_name_doesnt_end_with('o')
|
57
|
+
end
|
58
|
+
|
59
|
+
should "(not)? null scope" do
|
60
|
+
assert_equal [@slim], User.activated_at_null
|
61
|
+
assert_equal [@bob], User.activated_at_not_nil
|
62
|
+
end
|
63
|
+
|
64
|
+
should "boolean columns" do
|
65
|
+
assert_equal [@bob], User.admin
|
66
|
+
assert_equal [@slim], User.not_admin
|
67
|
+
end
|
68
|
+
|
69
|
+
end
|
70
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
require 'helper'
|
2
|
+
|
3
|
+
class TestOrdering < Test::Unit::TestCase
|
4
|
+
|
5
|
+
context "convenient_scopes" do
|
6
|
+
|
7
|
+
setup do
|
8
|
+
@bob = User.create :age => 43
|
9
|
+
@slim = User.create :age => 27
|
10
|
+
@avon = User.create :age => 37
|
11
|
+
@managers = Group.create :users => [@bob, @avon]
|
12
|
+
@developers = Group.create :users => [@slim]
|
13
|
+
end
|
14
|
+
|
15
|
+
should "allow ordering by attributes" do
|
16
|
+
assert_equal [@slim, @avon, @bob], User.ascend_by_age
|
17
|
+
assert_equal [@bob, @avon, @slim], User.descend_by_age
|
18
|
+
end
|
19
|
+
|
20
|
+
should "allow ordering by attributes of an association" do
|
21
|
+
assert_equal [@developers, @managers], Group.ascend_by_users_age.uniq
|
22
|
+
assert_equal [@managers, @developers], Group.descend_by_users_age.uniq
|
23
|
+
end
|
24
|
+
|
25
|
+
end
|
26
|
+
|
27
|
+
end
|
metadata
ADDED
@@ -0,0 +1,116 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: convenient_scopes
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
prerelease: false
|
5
|
+
segments:
|
6
|
+
- 0
|
7
|
+
- 4
|
8
|
+
- 0
|
9
|
+
version: 0.4.0
|
10
|
+
platform: ruby
|
11
|
+
authors:
|
12
|
+
- Ivan Schneider
|
13
|
+
autorequire:
|
14
|
+
bindir: bin
|
15
|
+
cert_chain: []
|
16
|
+
|
17
|
+
date: 2010-07-25 00:00:00 +02:00
|
18
|
+
default_executable:
|
19
|
+
dependencies:
|
20
|
+
- !ruby/object:Gem::Dependency
|
21
|
+
name: activerecord
|
22
|
+
prerelease: false
|
23
|
+
requirement: &id001 !ruby/object:Gem::Requirement
|
24
|
+
requirements:
|
25
|
+
- - ">="
|
26
|
+
- !ruby/object:Gem::Version
|
27
|
+
segments:
|
28
|
+
- 3
|
29
|
+
- 0
|
30
|
+
- 0
|
31
|
+
- beta4
|
32
|
+
version: 3.0.0.beta4
|
33
|
+
type: :runtime
|
34
|
+
version_requirements: *id001
|
35
|
+
- !ruby/object:Gem::Dependency
|
36
|
+
name: shoulda
|
37
|
+
prerelease: false
|
38
|
+
requirement: &id002 !ruby/object:Gem::Requirement
|
39
|
+
requirements:
|
40
|
+
- - ">="
|
41
|
+
- !ruby/object:Gem::Version
|
42
|
+
segments:
|
43
|
+
- 0
|
44
|
+
version: "0"
|
45
|
+
type: :development
|
46
|
+
version_requirements: *id002
|
47
|
+
- !ruby/object:Gem::Dependency
|
48
|
+
name: sqlite3-ruby
|
49
|
+
prerelease: false
|
50
|
+
requirement: &id003 !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - ">="
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
segments:
|
55
|
+
- 0
|
56
|
+
version: "0"
|
57
|
+
type: :development
|
58
|
+
version_requirements: *id003
|
59
|
+
description: Dynamic scopes by convention for ActiveRecord 3
|
60
|
+
email: isc@massivebraingames.com
|
61
|
+
executables: []
|
62
|
+
|
63
|
+
extensions: []
|
64
|
+
|
65
|
+
extra_rdoc_files:
|
66
|
+
- LICENSE
|
67
|
+
- README.rdoc
|
68
|
+
files:
|
69
|
+
- .document
|
70
|
+
- .gitignore
|
71
|
+
- LICENSE
|
72
|
+
- README.rdoc
|
73
|
+
- Rakefile
|
74
|
+
- VERSION
|
75
|
+
- convenient_scopes.gemspec
|
76
|
+
- lib/convenient_scopes.rb
|
77
|
+
- test/helper.rb
|
78
|
+
- test/test_associations.rb
|
79
|
+
- test/test_conditions.rb
|
80
|
+
- test/test_ordering.rb
|
81
|
+
has_rdoc: true
|
82
|
+
homepage: http://github.com/isc/convenient_scopes
|
83
|
+
licenses: []
|
84
|
+
|
85
|
+
post_install_message:
|
86
|
+
rdoc_options:
|
87
|
+
- --charset=UTF-8
|
88
|
+
require_paths:
|
89
|
+
- lib
|
90
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
91
|
+
requirements:
|
92
|
+
- - ">="
|
93
|
+
- !ruby/object:Gem::Version
|
94
|
+
segments:
|
95
|
+
- 0
|
96
|
+
version: "0"
|
97
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
98
|
+
requirements:
|
99
|
+
- - ">="
|
100
|
+
- !ruby/object:Gem::Version
|
101
|
+
segments:
|
102
|
+
- 0
|
103
|
+
version: "0"
|
104
|
+
requirements: []
|
105
|
+
|
106
|
+
rubyforge_project:
|
107
|
+
rubygems_version: 1.3.6
|
108
|
+
signing_key:
|
109
|
+
specification_version: 3
|
110
|
+
summary: Dynamic scopes by convention for ActiveRecord 3
|
111
|
+
test_files:
|
112
|
+
- test/helper.rb
|
113
|
+
- test/test_all_and_any_conditions.rb
|
114
|
+
- test/test_associations.rb
|
115
|
+
- test/test_conditions.rb
|
116
|
+
- test/test_ordering.rb
|