aub-record_filter 0.9.6 → 0.9.7

Sign up to get free protection for your applications and to get access to all the features.
data/.gitignore ADDED
@@ -0,0 +1,9 @@
1
+ coverage
2
+ perf
3
+ pkg
4
+ rdoc
5
+ *.gem
6
+ *.swp
7
+ tmp
8
+ _site
9
+
data/CHANGELOG ADDED
@@ -0,0 +1,207 @@
1
+ = 0.9.7
2
+
3
+ * Fix a bug where explicit joins would not honor different aliases if joining
4
+ the same class twice.
5
+
6
+ = 0.9.6
7
+
8
+ * Build the alias for explicit join tables correctly for multi-word class
9
+ names.
10
+
11
+ * Set params[:readonly] to false by default. Not sure why we need to do that.
12
+
13
+ * If nil is passed as the argument to a comparison operator, don't fail with a
14
+ lack of bind variables, just do what AR does and compare against NULL.
15
+
16
+ * Add ability to order on columns in tables that were explicitly joined.
17
+
18
+ = 0.9.5
19
+
20
+ * Added 'and' and 'or' methods to the DSL::Restriction class so that you can do
21
+ things like with(:expired_at).gt(Time.now).or.is_null
22
+
23
+ = 0.9.4
24
+
25
+ * Stop forcing order to take a real column name and let it accept a string
26
+
27
+ * Added an offset method to the DSL so that we can do offsets separately from
28
+ limits
29
+
30
+ * Some small performance improvements
31
+
32
+ * Added a test to make sure that the IN restriction can take a range
33
+
34
+ * Changed the default rake task to run db:spec:prepare first
35
+
36
+ * Added metric_fu for code quality metrics tests
37
+
38
+ * Refactored a bunch of code to improve the metric numbers
39
+
40
+ = 0.9.3
41
+
42
+ * Fix a bug when using class_name on belongs_to associations without
43
+ foreign_key
44
+
45
+ = 0.9.2
46
+
47
+ * Ruby 1.9 compatability
48
+
49
+ = 0.9.1
50
+
51
+ * Change group_by so that it will not throw an exception for missing column
52
+ names, since we want to be able to group by arbitrary things.
53
+
54
+ = 0.9.0
55
+
56
+ * Added a github pages page with a quick intro.
57
+
58
+ * Add tests for working with default scopes.
59
+
60
+ * de-hackify the default aliases for explicit joins.
61
+
62
+ * Fix a bug where strings wouldn't work as the names of associations in
63
+ implicit joins.
64
+
65
+ * Improve the README
66
+
67
+ * Fix a bug when combining joins across multiple named filters that introduce
68
+ the same join.
69
+
70
+ = 0.8.0
71
+
72
+ * Raise an exception when calling order with something that isn't :asc or
73
+ :desc
74
+
75
+ * Use hanna for spiffy rdocs.
76
+
77
+ * Raise an exception when attempting to add a named filter to a class if there
78
+ is already an existing filter with the same name.
79
+
80
+ * Documentation.
81
+
82
+ * Refactored the custom DSL subclass creation code into a DSLFactory class.
83
+
84
+ * Added a (fairly simple) performance test.
85
+
86
+ * Get source_type option working for has_many.
87
+
88
+ * Correct hard-coded primary key columns.
89
+
90
+ = 0.6.0
91
+
92
+ * 100% test coverage. That's right, 100%.
93
+
94
+ * Added fixes for various options on AR associations.
95
+
96
+ * Support calling named filters from within joins in filters.
97
+
98
+ * Stop using _inheritable_attribute for accessing the named filters and just recurse for
99
+ them.
100
+
101
+ * Change the tests for named filters to use anonymous classes so that we're
102
+ sure we're starting from a blank slate.
103
+
104
+ * Make the API work correctly for anonymous classes.
105
+
106
+ * Correctly handle the case where nil or [] is passed as an argument to the IN
107
+ restriction.
108
+
109
+ * Added is_not_null as a nicer version of is_null.not
110
+
111
+ = 0.2.0
112
+
113
+ * Changed the available join types to inner, left and right.
114
+
115
+ * Fix a bug where we used the wrong type in polymorphic association joins.
116
+
117
+ * Use with_scope when chaining filters, named_filters, and AR associations in
118
+ order to keep the filter data instead of passing the query parameters directly
119
+ and combining them in order to make this work correctly with AR.
120
+
121
+ * Fix a bug when calling .filter in a chain of associations and named filters.
122
+
123
+ * Don't include conditions unless there are actually conditions specified.
124
+
125
+ * Fix a bug where the first and last methods would fail.
126
+
127
+ * Delegate array methods through to the result of the filter.
128
+
129
+ * Add proxy_options to mimic the API of named_scope for getting the options
130
+ that result from a given query.
131
+
132
+ * Support chaining with AR associations... (i.e. Blog.posts.published)
133
+
134
+ * Support has_many and has_one :through
135
+
136
+ = 0.1.4
137
+
138
+ * Join on both the id and type for polymorphic joins.
139
+
140
+ * Fix a bug where we were using the incorrect table names in joins and
141
+ ordering with joins.
142
+
143
+ * Change != to the SQL standard <>.
144
+
145
+ * Fix invalid SQL generated by not_all and not_any.
146
+
147
+ * Detect count/size/length queries and do the appropriate distinct clause for
148
+ those count queries.
149
+
150
+ * Do DISTINCT searches for queries that involve specific types of joins.
151
+
152
+ * Allow passing a join type as the first argument to having.
153
+
154
+ * Restructured the explicit join API
155
+
156
+ * Raise exceptions when doing an explicit join using columns that don't exist.
157
+
158
+ * Allow explicit joins on values: left_join(:class_name, :table_alias, :rcol
159
+ => 'Post'...)
160
+
161
+ * Added a filter_class method to the DSL for getting the class that is being
162
+ filtered.
163
+
164
+ * Added custom join feature: left_join(:table_name, :table_alias, :rcol =>
165
+ :lcol...)
166
+
167
+ * Changed custom exceptions to subclass StandardError and not crash the entire
168
+ app when throwing one (thanks RailsEnvy).
169
+
170
+ = 0.1.3
171
+
172
+ * Fixed a bug in filter.rb when trying to chain to named_scopes or things that
173
+ are otherwise not named_filters.
174
+
175
+ * Made a named_filters accessor for getting the list of filters that apply to
176
+ a particular class.
177
+
178
+ * Added none_of and not_all_of conjunctions.
179
+
180
+ * Changed the between restriction to take either a range, a tuple, or two
181
+ values.
182
+
183
+ * Support multiple joins in one having statement through having(:posts =>
184
+ :comments)
185
+
186
+ * Added a CHANGELOG
187
+
188
+ = 0.1.2
189
+
190
+ * Add LIKE and NOT LIKE restrictions
191
+
192
+ * Replace active record objects with their ids if passed as the value for a
193
+ resriction.
194
+
195
+ = 0.1.1
196
+
197
+ * Add group_by
198
+
199
+ * Raise informative exceptions when columns or associations are not found for
200
+ a given filter
201
+
202
+ * Alias is_null restriction to nil and null
203
+
204
+ * Alias comparison restrictions to gt, lt, lte, gte
205
+
206
+ * Add greater_than_or_equal_to and less_than_or_equal_to restrictions.
207
+
data/VERSION.yml CHANGED
@@ -1,4 +1,4 @@
1
1
  ---
2
2
  :major: 0
3
3
  :minor: 9
4
- :patch: 6
4
+ :patch: 7
data/config/roodi.yml ADDED
@@ -0,0 +1,14 @@
1
+ AssignmentInConditionalCheck: { }
2
+ CaseMissingElseCheck: { }
3
+ ClassLineCountCheck: { line_count: 300 }
4
+ ClassNameCheck: { pattern: !ruby/regexp /^[A-Z][a-zA-Z0-9]*$/ }
5
+ CyclomaticComplexityBlockCheck: { complexity: 4 }
6
+ CyclomaticComplexityMethodCheck: { complexity: 8 }
7
+ EmptyRescueBodyCheck: { }
8
+ ForLoopCheck: { }
9
+ MethodLineCountCheck: { line_count: 20 }
10
+ MethodNameCheck: { pattern: !ruby/regexp /^[_a-z<>=\[\]|+-\/\*`]+[_a-z0-9_<>=~@\[\]]*[=!\?]?$/ }
11
+ ModuleLineCountCheck: { line_count: 300 }
12
+ ModuleNameCheck: { pattern: !ruby/regexp /^[A-Z][a-zA-Z0-9]*$/ }
13
+ ParameterNumberCheck: { parameter_count: 5 }
14
+
@@ -48,21 +48,29 @@ module RecordFilter
48
48
  end
49
49
 
50
50
  def join_class(clazz, join_type, table_alias, conditions)
51
- @joins_cache[clazz] ||=
51
+ use_alias = table_alias || alias_for_class(clazz)
52
+ @joins_cache[use_alias] ||=
52
53
  begin
53
- join_table = Table.new(clazz, table_alias || alias_for_class(clazz))
54
+ join_table = Table.new(clazz, use_alias)
54
55
  @joins << (join = Join.new(self, join_table, conditions, join_type))
55
56
  join
56
57
  end
57
58
  end
58
59
 
59
- def find_join(join_key)
60
- @joins_cache[join_key]
60
+ def join_key_for(key)
61
+ case key
62
+ when Class then alias_for_class(key)
63
+ when String, Symbol then key
64
+ end
65
+ end
66
+
67
+ def find_join(key)
68
+ @joins_cache[join_key_for(key)]
61
69
  end
62
70
 
63
- def find_join!(join_key)
64
- join = find_join(join_key)
65
- raise InvalidJoinException.new("The join #{join_key} was not found.") unless join
71
+ def find_join!(key)
72
+ join = find_join(key)
73
+ raise InvalidJoinException.new("The join #{key} was not found.") unless join
66
74
  join
67
75
  end
68
76
 
@@ -0,0 +1,97 @@
1
+ # -*- encoding: utf-8 -*-
2
+
3
+ Gem::Specification.new do |s|
4
+ s.name = %q{record_filter}
5
+ s.version = "0.9.7"
6
+
7
+ s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
8
+ s.authors = ["Aubrey Holland", "Mat Brown"]
9
+ s.date = %q{2009-06-03}
10
+ s.description = %q{RecordFilter is a Pure-ruby criteria API for building complex queries in ActiveRecord. It supports queries that are built on the fly as well as named filters that can be added to objects and chained to create complex queries. It also gets rid of the nasty hard-coded SQL that shows up in most ActiveRecord code with a clean API that makes queries simple and intuitive to build.}
11
+ s.email = %q{aubreyholland@gmail.com}
12
+ s.extra_rdoc_files = [
13
+ "README.rdoc"
14
+ ]
15
+ s.files = [
16
+ ".gitignore",
17
+ "CHANGELOG",
18
+ "README.rdoc",
19
+ "Rakefile",
20
+ "VERSION.yml",
21
+ "config/roodi.yml",
22
+ "lib/record_filter.rb",
23
+ "lib/record_filter/active_record.rb",
24
+ "lib/record_filter/column_parser.rb",
25
+ "lib/record_filter/conjunctions.rb",
26
+ "lib/record_filter/dsl.rb",
27
+ "lib/record_filter/dsl/class_join.rb",
28
+ "lib/record_filter/dsl/conjunction.rb",
29
+ "lib/record_filter/dsl/conjunction_dsl.rb",
30
+ "lib/record_filter/dsl/dsl.rb",
31
+ "lib/record_filter/dsl/dsl_factory.rb",
32
+ "lib/record_filter/dsl/group_by.rb",
33
+ "lib/record_filter/dsl/join.rb",
34
+ "lib/record_filter/dsl/join_condition.rb",
35
+ "lib/record_filter/dsl/join_dsl.rb",
36
+ "lib/record_filter/dsl/limit.rb",
37
+ "lib/record_filter/dsl/named_filter.rb",
38
+ "lib/record_filter/dsl/order.rb",
39
+ "lib/record_filter/dsl/restriction.rb",
40
+ "lib/record_filter/filter.rb",
41
+ "lib/record_filter/group_by.rb",
42
+ "lib/record_filter/join.rb",
43
+ "lib/record_filter/order.rb",
44
+ "lib/record_filter/query.rb",
45
+ "lib/record_filter/restriction_factory.rb",
46
+ "lib/record_filter/restrictions.rb",
47
+ "lib/record_filter/table.rb",
48
+ "record_filter.gemspec",
49
+ "script/console",
50
+ "spec/active_record_spec.rb",
51
+ "spec/exception_spec.rb",
52
+ "spec/explicit_join_spec.rb",
53
+ "spec/implicit_join_spec.rb",
54
+ "spec/limits_and_ordering_spec.rb",
55
+ "spec/models.rb",
56
+ "spec/named_filter_spec.rb",
57
+ "spec/proxying_spec.rb",
58
+ "spec/restrictions_spec.rb",
59
+ "spec/select_spec.rb",
60
+ "spec/spec_helper.rb",
61
+ "spec/test.db",
62
+ "tasks/db.rake",
63
+ "tasks/rcov.rake",
64
+ "tasks/spec.rake",
65
+ "test/performance_test.rb",
66
+ "test/test.db"
67
+ ]
68
+ s.homepage = %q{http://github.com/aub/record_filter/tree/master}
69
+ s.rdoc_options = ["--charset=UTF-8"]
70
+ s.require_paths = ["lib"]
71
+ s.rubygems_version = %q{1.3.3}
72
+ s.summary = %q{An ActiveRecord query API for replacing SQL with awesome}
73
+ s.test_files = [
74
+ "spec/active_record_spec.rb",
75
+ "spec/exception_spec.rb",
76
+ "spec/explicit_join_spec.rb",
77
+ "spec/implicit_join_spec.rb",
78
+ "spec/limits_and_ordering_spec.rb",
79
+ "spec/models.rb",
80
+ "spec/named_filter_spec.rb",
81
+ "spec/proxying_spec.rb",
82
+ "spec/restrictions_spec.rb",
83
+ "spec/select_spec.rb",
84
+ "spec/spec_helper.rb",
85
+ "test/performance_test.rb"
86
+ ]
87
+
88
+ if s.respond_to? :specification_version then
89
+ current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
90
+ s.specification_version = 3
91
+
92
+ if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then
93
+ else
94
+ end
95
+ else
96
+ end
97
+ end
data/script/console ADDED
@@ -0,0 +1,8 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require File.join(File.dirname(__FILE__), '..', 'spec', 'spec_helper')
4
+
5
+ require 'logger'
6
+ ActiveRecord::Base.logger = Logger.new(STDOUT)
7
+
8
+ IRB.start
@@ -104,4 +104,29 @@ describe 'explicit joins' do
104
104
  @blog.last_find[:joins].should == [%q(INNER JOIN "ads" AS blogs__ads ON "blogs".id = blogs__ads.blog_id), %q(LEFT OUTER JOIN "posts" AS blogs__post ON "blogs".id = blogs__post.blog_id), %q(INNER JOIN "comments" AS blogs__post__comment ON blogs__post.id = blogs__post__comment.post_id AND (blogs__post__comment.offensive = 't'))]
105
105
  end
106
106
  end
107
+
108
+ describe 'using the same join multiple times' do
109
+ before do
110
+ @blog = Class.new(Blog)
111
+ @blog.named_filter(:things) do
112
+ join(Post, :inner, 'blogs_posts_1') do
113
+ on(:id => :blog_id)
114
+ with(:title, 'ack')
115
+ end
116
+ join(Post, :inner, 'blogs_posts_2') do
117
+ on(:id => :blog_id)
118
+ with(:title, 'hmm')
119
+ end
120
+ end
121
+ @blog.things.inspect
122
+ end
123
+
124
+ it 'should create the correct join' do
125
+ @blog.last_find[:joins].should == [%q(INNER JOIN "posts" AS blogs_posts_1 ON "blogs".id = blogs_posts_1.blog_id), %q(INNER JOIN "posts" AS blogs_posts_2 ON "blogs".id = blogs_posts_2.blog_id)]
126
+ end
127
+
128
+ it 'should create the correct conditions' do
129
+ @blog.last_find[:conditions].should == [%q((blogs_posts_1.title = ?) AND (blogs_posts_2.title = ?)), 'ack', 'hmm']
130
+ end
131
+ end
107
132
  end
data/spec/test.db CHANGED
Binary file
data/tasks/db.rake ADDED
@@ -0,0 +1,106 @@
1
+ namespace :db do
2
+ namespace :spec do
3
+ desc 'drop database and recreate from test schema'
4
+ task :prepare do
5
+ require File.join(File.dirname(__FILE__), '..', 'spec', 'spec_helper')
6
+
7
+ db_file = File.join(File.dirname(__FILE__), '..', 'spec', 'test.db')
8
+
9
+ FileUtils.rm(db_file) if File.exists?(db_file)
10
+
11
+ ActiveRecord::Schema.define do
12
+
13
+ create_table :ads do |t|
14
+ t.integer :blog_id
15
+ t.string :content
16
+ end
17
+
18
+ create_table :articles do |t|
19
+ t.string :contents
20
+ t.timestamps
21
+ end
22
+
23
+ create_table :assets do |t|
24
+ t.timestamps
25
+ t.string :format
26
+ end
27
+
28
+ create_table :asset_attachments do |t|
29
+ t.integer :to_id
30
+ t.string :to_type
31
+ t.integer :from_id
32
+ end
33
+
34
+ create_table :authors do |t|
35
+ t.references :post
36
+ t.string :nickname
37
+ t.references :user
38
+ end
39
+
40
+ create_table :blogs do |t|
41
+ t.string :name
42
+ t.boolean :published
43
+ t.integer :special_id
44
+ t.timestamps
45
+ end
46
+
47
+ create_table :comments do |t|
48
+ t.references :post
49
+ t.references :user
50
+ t.string :contents
51
+ t.boolean :offensive
52
+ t.timestamps
53
+ end
54
+
55
+ create_table :features do |t|
56
+ t.references :blog
57
+ t.integer :featurable_id
58
+ t.string :featurable_type
59
+ t.integer :priority
60
+ end
61
+
62
+ create_table :news_stories do |t|
63
+ t.references :blog
64
+ t.string :permalink
65
+ t.text :contents
66
+ end
67
+
68
+ create_table :photos do |t|
69
+ t.integer :post_id
70
+ t.string :path
71
+ t.string :format
72
+ end
73
+
74
+ create_table :posts do |t|
75
+ t.integer :blog_id
76
+ t.integer :special_blog_id
77
+ t.string :permalink
78
+ t.timestamp :created_at
79
+ t.boolean :published
80
+ t.string :content
81
+ t.string :title
82
+ end
83
+
84
+ create_table :posts_tags, :id => false do |t|
85
+ t.integer :post_id
86
+ t.integer :tag_id
87
+ end
88
+
89
+ create_table :reviews do |t|
90
+ t.integer :reviewable_id
91
+ t.string :reviewable_type
92
+ t.integer :stars_count
93
+ end
94
+
95
+ create_table :tags do |t|
96
+ t.string :name
97
+ end
98
+
99
+ create_table :users do |t|
100
+ t.string :first_name
101
+ t.string :last_name
102
+ end
103
+ end
104
+ end
105
+ end
106
+ end
data/tasks/rcov.rake ADDED
@@ -0,0 +1,9 @@
1
+ require 'spec/rake/spectask'
2
+
3
+ desc 'run specs with rcov'
4
+ Spec::Rake::SpecTask.new('rcov') do |t|
5
+ t.spec_files = FileList['spec/**/*_spec.rb']
6
+ t.rcov = true
7
+ t.rcov_dir = File.join('coverage', 'all')
8
+ t.rcov_opts.concat(['--exclude', 'spec', '--sort', 'coverage', '--only-uncovered'])
9
+ end
data/tasks/spec.rake ADDED
@@ -0,0 +1,10 @@
1
+ gem 'rspec', '~>1.1'
2
+
3
+ require 'spec'
4
+ require 'spec/rake/spectask'
5
+
6
+ desc 'run specs'
7
+ Spec::Rake::SpecTask.new('spec') do |t|
8
+ t.spec_files = FileList[File.join(File.dirname(__FILE__), '..', 'spec', '**', '*_spec.rb')]
9
+ t.spec_opts = ['--color']
10
+ end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: aub-record_filter
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.9.6
4
+ version: 0.9.7
5
5
  platform: ruby
6
6
  authors:
7
7
  - Aubrey Holland
@@ -10,7 +10,7 @@ autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
12
 
13
- date: 2009-05-13 00:00:00 -07:00
13
+ date: 2009-06-03 00:00:00 -07:00
14
14
  default_executable:
15
15
  dependencies: []
16
16
 
@@ -23,9 +23,12 @@ extensions: []
23
23
  extra_rdoc_files:
24
24
  - README.rdoc
25
25
  files:
26
+ - .gitignore
27
+ - CHANGELOG
26
28
  - README.rdoc
27
29
  - Rakefile
28
30
  - VERSION.yml
31
+ - config/roodi.yml
29
32
  - lib/record_filter.rb
30
33
  - lib/record_filter/active_record.rb
31
34
  - lib/record_filter/column_parser.rb
@@ -52,6 +55,8 @@ files:
52
55
  - lib/record_filter/restriction_factory.rb
53
56
  - lib/record_filter/restrictions.rb
54
57
  - lib/record_filter/table.rb
58
+ - record_filter.gemspec
59
+ - script/console
55
60
  - spec/active_record_spec.rb
56
61
  - spec/exception_spec.rb
57
62
  - spec/explicit_join_spec.rb
@@ -64,9 +69,12 @@ files:
64
69
  - spec/select_spec.rb
65
70
  - spec/spec_helper.rb
66
71
  - spec/test.db
72
+ - tasks/db.rake
73
+ - tasks/rcov.rake
74
+ - tasks/spec.rake
67
75
  - test/performance_test.rb
68
76
  - test/test.db
69
- has_rdoc: true
77
+ has_rdoc: false
70
78
  homepage: http://github.com/aub/record_filter/tree/master
71
79
  post_install_message:
72
80
  rdoc_options: