squeel 0.9.5 → 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
data/.travis.yml CHANGED
@@ -1,10 +1,13 @@
1
1
  rvm:
2
2
  - 1.8.7
3
- - 1.9.2
4
3
  - 1.9.3
5
- - ree
6
- - rbx
7
- - ruby-head
4
+ # TODO: Re-enable when updates to Rubinius on
5
+ # Travis stop randomly breaking specs that
6
+ # pass on MRI. :(
7
+ # - rbx-18mode
8
+ # - rbx-19mode
8
9
 
9
10
  env:
10
11
  - RAILS=3-2-stable
12
+ - RAILS=3-1-stable AREL=2-2-stable
13
+ - RAILS=3-0-stable AREL=2-0-stable
data/Gemfile CHANGED
@@ -34,4 +34,4 @@ else
34
34
  gem 'activemodel'
35
35
  gem 'activerecord'
36
36
  end
37
- end
37
+ end
data/README.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # Squeel [![Build Status](https://secure.travis-ci.org/ernie/squeel.png)](http://travis-ci.org/ernie/squeel)
2
2
 
3
- Squeel lets you write your ActiveRecord queries with with fewer strings, and more Ruby,
3
+ Squeel lets you write your ActiveRecord queries with fewer strings, and more Ruby,
4
4
  by making the ARel awesomeness that lies beneath ActiveRecord more accessible.
5
5
 
6
6
  Squeel lets you rewrite...
@@ -21,20 +21,13 @@ In your Gemfile:
21
21
  gem "squeel" # Last officially released gem
22
22
  # gem "squeel", :git => "git://github.com/ernie/squeel.git" # Track git repo
23
23
 
24
- In an initializer:
24
+ Then bundle as usual.
25
25
 
26
- Squeel.configure do |config|
27
- # To load hash extensions (to allow for AND (&), OR (|), and NOT (-) against
28
- # hashes of conditions)
29
- config.load_core_extensions :hash
30
-
31
- # To load symbol extensions (for a subset of the old MetaWhere functionality,
32
- # via ARel predicate methods on Symbols: :name.matches, etc)
33
- # config.load_core_extensions :symbol
26
+ If you'd like to customize Squeel's functionality by enabling core
27
+ extensions for hashes or symbols, or aliasing some predicates, you can
28
+ create a sample initializer with:
34
29
 
35
- # To load both hash and symbol extensions
36
- # config.load_core_extensions :hash, :symbol
37
- end
30
+ rails g squeel:initializer
38
31
 
39
32
  ## The Squeel Query DSL
40
33
 
@@ -443,4 +436,4 @@ To support the project in other ways:
443
436
 
444
437
  ## Copyright
445
438
 
446
- Copyright © 2011 [Ernie Miller](http://twitter.com/erniemiller)
439
+ Copyright © 2011 [Ernie Miller](http://twitter.com/erniemiller)
data/Rakefile CHANGED
@@ -1,4 +1,4 @@
1
- require 'bundler'
1
+ require 'bundler/setup'
2
2
  require 'rspec/core/rake_task'
3
3
 
4
4
  Bundler::GemHelper.install_tasks
@@ -16,4 +16,4 @@ task :console do
16
16
  require 'console'
17
17
  ARGV.clear
18
18
  IRB.start
19
- end
19
+ end
@@ -0,0 +1,15 @@
1
+ module Squeel
2
+ module Generators
3
+ class InitializerGenerator < ::Rails::Generators::Base
4
+
5
+ source_root File.expand_path("../../templates", __FILE__)
6
+
7
+ desc 'Creates a sample Squeel initializer.'
8
+
9
+ def copy_initializer
10
+ copy_file 'squeel.rb', 'config/initializers/squeel.rb'
11
+ end
12
+
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,24 @@
1
+ Squeel.configure do |config|
2
+ # To load hash extensions (to allow for AND (&), OR (|), and NOT (-) against
3
+ # hashes of conditions):
4
+ #
5
+ # config.load_core_extensions :hash
6
+
7
+ # To load symbol extensions (for a subset of the old MetaWhere functionality,
8
+ # via ARel predicate methods on Symbols: :name.matches, etc):
9
+ #
10
+ # NOTE: Not recommended. Learn the new DSL. Use it. Love it.
11
+ #
12
+ # config.load_core_extensions :symbol
13
+
14
+ # To load both hash and symbol extensions:
15
+ #
16
+ # config.load_core_extensions :hash, :symbol
17
+
18
+ # Alias an existing predicate to a new name. Use the non-grouped
19
+ # name -- the any/all variants will also be created. For example,
20
+ # to alias the standard "lt" predicate to "less_than", and gain
21
+ # "less_than_any" and "less_than_all" as well:
22
+ #
23
+ # config.alias_predicate :less_than, :lt
24
+ end
@@ -106,6 +106,35 @@ module Squeel
106
106
  arel
107
107
  end
108
108
 
109
+ # So, building a select for a count query in ActiveRecord is
110
+ # pretty heavily dependent on select_values containing strings.
111
+ # I'd initially expected that I could just hack together a fix
112
+ # to select_for_count and everything would fall in line, but
113
+ # unfortunately, pretty much everything from that point on
114
+ # in ActiveRecord::Calculations#perform_calculation expects
115
+ # the column to be a string, or at worst, a symbol.
116
+ #
117
+ # In the long term, I would like to refactor the code in
118
+ # Rails core, but for now, I'm going to settle for this hack
119
+ # that tries really hard to coerce things to a string.
120
+ def select_for_count
121
+ visited_values = attribute_visitor.accept(select_values.uniq)
122
+ if visited_values.size == 1
123
+ select = visited_values.first
124
+
125
+ str_select = case select
126
+ when String
127
+ select
128
+ when Symbol
129
+ select.to_s
130
+ else
131
+ select.to_sql if select.respond_to?(:to_sql)
132
+ end
133
+
134
+ str_select if str_select && str_select !~ /[,*]/
135
+ end
136
+ end
137
+
109
138
  def build_join_dependency(relation, joins)
110
139
  association_joins = []
111
140
 
@@ -336,4 +365,4 @@ module Squeel
336
365
  end
337
366
  end
338
367
  end
339
- end
368
+ end
@@ -117,6 +117,35 @@ module Squeel
117
117
  end
118
118
  end
119
119
 
120
+ # So, building a select for a count query in ActiveRecord is
121
+ # pretty heavily dependent on select_values containing strings.
122
+ # I'd initially expected that I could just hack together a fix
123
+ # to select_for_count and everything would fall in line, but
124
+ # unfortunately, pretty much everything from that point on
125
+ # in ActiveRecord::Calculations#perform_calculation expects
126
+ # the column to be a string, or at worst, a symbol.
127
+ #
128
+ # In the long term, I would like to refactor the code in
129
+ # Rails core, but for now, I'm going to settle for this hack
130
+ # that tries really hard to coerce things to a string.
131
+ def select_for_count
132
+ visited_values = attribute_visitor.accept(select_values.uniq)
133
+ if visited_values.size == 1
134
+ select = visited_values.first
135
+
136
+ str_select = case select
137
+ when String
138
+ select
139
+ when Symbol
140
+ select.to_s
141
+ else
142
+ select.to_sql if select.respond_to?(:to_sql)
143
+ end
144
+
145
+ str_select if str_select && str_select !~ /[,*]/
146
+ end
147
+ end
148
+
120
149
  def build_join_dependency(manager, joins)
121
150
  buckets = joins.group_by do |join|
122
151
  case join
@@ -344,7 +373,7 @@ module Squeel
344
373
  end
345
374
 
346
375
  def where_values_hash_with_squeel
347
- equalities = find_equality_predicates(predicate_visitor.accept(@where_values))
376
+ equalities = find_equality_predicates(predicate_visitor.accept(with_default_scope.where_values))
348
377
 
349
378
  Hash[equalities.map { |where| [where.left.name, where.right] }]
350
379
  end
@@ -352,4 +381,4 @@ module Squeel
352
381
  end
353
382
  end
354
383
  end
355
- end
384
+ end
@@ -6,6 +6,7 @@ module Squeel
6
6
  class Function
7
7
 
8
8
  include PredicateMethods
9
+ include PredicateOperators
9
10
  include Operators
10
11
 
11
12
  alias :== :eq
@@ -63,4 +64,4 @@ module Squeel
63
64
 
64
65
  end
65
66
  end
66
- end
67
+ end
@@ -1,3 +1,5 @@
1
+ require 'active_support/core_ext/module'
2
+
1
3
  module Squeel
2
4
  module Nodes
3
5
  # A node representing a joined association
@@ -83,4 +85,4 @@ module Squeel
83
85
 
84
86
  end
85
87
  end
86
- end
88
+ end
@@ -1,5 +1,6 @@
1
1
  require 'squeel/nodes/operators'
2
2
  require 'squeel/nodes/predicate_operators'
3
+ require 'active_support/core_ext/module'
3
4
 
4
5
  module Squeel
5
6
  module Nodes
@@ -204,4 +205,4 @@ module Squeel
204
205
 
205
206
  end
206
207
  end
207
- end
208
+ end
@@ -1,3 +1,3 @@
1
1
  module Squeel
2
- VERSION = "0.9.5"
2
+ VERSION = "1.0.0"
3
3
  end
@@ -108,6 +108,13 @@ module Squeel
108
108
  arel.to_sql.should match /"people"."name" LIKE '%bob%'/
109
109
  end
110
110
 
111
+ it 'handles multiple wheres using a keypath' do
112
+ relation = Person.joins{articles}.where{articles.title == 'Hello'}.
113
+ where{articles.body == 'World'}
114
+ arel = relation.build_arel
115
+ arel.to_sql.should match /articles/
116
+ end
117
+
111
118
  it 'maps wheres inside a hash to their appropriate association table' do
112
119
  relation = Person.joins({
113
120
  :children => {
@@ -394,6 +401,10 @@ module Squeel
394
401
  aric.last_article_id.should eq Article.where(:person_id => 1).last.id
395
402
  end
396
403
 
404
+ it "doesn't break #count if non-strings are used" do
405
+ Article.select{distinct(title)}.count.should eq 51
406
+ end
407
+
397
408
  end
398
409
 
399
410
  describe '#group' do
@@ -477,7 +488,7 @@ module Squeel
477
488
  relation = Person.joins(:authored_article_comments)
478
489
  relation.first.authored_article_comments.first.should eq Comment.first
479
490
  end
480
-
491
+
481
492
  it 'creates a unique join when joining a table used in a has_many :through association' do
482
493
  Person.first.authored_article_comments.joins(:article).first.should eq Comment.first
483
494
  end
@@ -597,6 +608,10 @@ module Squeel
597
608
  @person.name.should eq 'bob'
598
609
  end
599
610
 
611
+ it "maintains activerecord default scope functionality" do
612
+ PersonNamedBill.new.name.should eq 'Bill'
613
+ end
614
+
600
615
  it 'uses the last supplied equality predicate in where_values when creating new records' do
601
616
  @person = Person.where(:name => 'bob', :parent_id => 3).where(:name => 'joe').new
602
617
  @person.parent_id.should eq 3
@@ -674,7 +689,9 @@ module Squeel
674
689
 
675
690
  queries.should have(2).queries
676
691
 
677
- queries.last.should match /IN \(1, ?34, ?67, ?100\)/
692
+ matched_ids = queries.last.match(/IN \(([^)]*)/).captures.first
693
+ matched_ids = matched_ids.split(/,\s*/).map(&:to_i)
694
+ matched_ids.should =~ [1, 34, 67, 100]
678
695
  end
679
696
 
680
697
  end
@@ -682,4 +699,4 @@ module Squeel
682
699
  end
683
700
  end
684
701
  end
685
- end
702
+ end
@@ -4,7 +4,7 @@ module Squeel
4
4
  module Nodes
5
5
  describe Function do
6
6
  before do
7
- @f = :function.func(1,2,3)
7
+ @f = Function.new(:function, [1, 2, 3])
8
8
  end
9
9
 
10
10
  Squeel::Constants::PREDICATES.each do |method_name|
@@ -132,6 +132,27 @@ module Squeel
132
132
  predicate.value.should eq 1
133
133
  end
134
134
 
135
+ it 'can be ORed with another node' do
136
+ right = Predicate.new :name, :eq, 'Bob'
137
+ combined = @f | right
138
+ combined.should be_a Nodes::Or
139
+ combined.left.should eq @f
140
+ combined.right.should eq right
141
+ end
142
+
143
+ it 'can be ANDed with another node' do
144
+ right = Predicate.new :name, :eq, 'Bob'
145
+ combined = @f & right
146
+ combined.should be_a Nodes::And
147
+ combined.children.should eq [@f, right]
148
+ end
149
+
150
+ it 'can be negated' do
151
+ negated = -@f
152
+ negated.should be_a Nodes::Not
153
+ negated.expr.should eq @f
154
+ end
155
+
135
156
  describe '#as' do
136
157
 
137
158
  it 'aliases the function' do
@@ -148,4 +169,4 @@ module Squeel
148
169
 
149
170
  end
150
171
  end
151
- end
172
+ end
@@ -132,6 +132,27 @@ module Squeel
132
132
  predicate.value.should eq 1
133
133
  end
134
134
 
135
+ it 'can be ORed with another node' do
136
+ right = Predicate.new :name, :eq, 'Bob'
137
+ combined = @o | right
138
+ combined.should be_a Nodes::Or
139
+ combined.left.should eq @o
140
+ combined.right.should eq right
141
+ end
142
+
143
+ it 'can be ANDed with another node' do
144
+ right = Predicate.new :name, :eq, 'Bob'
145
+ combined = @o & right
146
+ combined.should be_a Nodes::And
147
+ combined.children.should eq [@o, right]
148
+ end
149
+
150
+ it 'can be negated' do
151
+ negated = -@o
152
+ negated.should be_a Nodes::Not
153
+ negated.expr.should eq @o
154
+ end
155
+
135
156
  describe '#as' do
136
157
 
137
158
  it 'aliases the function' do
@@ -148,4 +169,4 @@ module Squeel
148
169
 
149
170
  end
150
171
  end
151
- end
172
+ end
@@ -33,6 +33,11 @@ class PersonWithNamePrimaryKey < ActiveRecord::Base
33
33
  set_table_name 'people'
34
34
  end
35
35
 
36
+ class PersonNamedBill < ActiveRecord::Base
37
+ self.table_name = 'people'
38
+ default_scope where(:name => 'Bill')
39
+ end
40
+
36
41
  class Message < ActiveRecord::Base
37
42
  belongs_to :author, :class_name => 'Person'
38
43
  belongs_to :recipient, :class_name => 'Person'
@@ -141,4 +146,4 @@ module Schema
141
146
  Comment.make(:body => 'Last post!', :article => Article.first, :person => Article.first.commenters.first)
142
147
 
143
148
  end
144
- end
149
+ end
data/squeel.gemspec CHANGED
@@ -7,8 +7,8 @@ Gem::Specification.new do |s|
7
7
  s.version = Squeel::VERSION
8
8
  s.platform = Gem::Platform::RUBY
9
9
  s.authors = ["Ernie Miller"]
10
- s.email = ["ernie@metautonomo.us"]
11
- s.homepage = "http://metautonomo.us/projects/squeel"
10
+ s.email = ["ernie@erniemiller.org"]
11
+ s.homepage = "http://erniemiller.org/projects/squeel"
12
12
  s.summary = %q{ActiveRecord 3, improved.}
13
13
  s.description = %q{
14
14
  Squeel unlocks the power of ARel in your Rails 3 application with
@@ -16,15 +16,6 @@ Gem::Specification.new do |s|
16
16
  functions provided by your RDBMS, and more, all without writing
17
17
  SQL strings.
18
18
  }
19
- s.post_install_message = %q{
20
- *** Thanks for installing Squeel! ***
21
- Be sure to check out http://metautonomo.us/projects/squeel/ for a
22
- walkthrough of Squeel's features, and click the donate link if
23
- you're feeling especially appreciative. It'd help me justify this
24
- "open source" stuff to my lovely wife. :)
25
-
26
- }
27
-
28
19
  s.rubyforge_project = "squeel"
29
20
 
30
21
  s.add_dependency 'activerecord', '~> 3.0'
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: squeel
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.9.5
4
+ version: 1.0.0
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,11 +9,12 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2012-01-23 00:00:00.000000000 Z
12
+ date: 2012-04-22 00:00:00.000000000 -04:00
13
+ default_executable:
13
14
  dependencies:
14
15
  - !ruby/object:Gem::Dependency
15
16
  name: activerecord
16
- requirement: &70289249898780 !ruby/object:Gem::Requirement
17
+ requirement: &70321134916300 !ruby/object:Gem::Requirement
17
18
  none: false
18
19
  requirements:
19
20
  - - ~>
@@ -21,10 +22,10 @@ dependencies:
21
22
  version: '3.0'
22
23
  type: :runtime
23
24
  prerelease: false
24
- version_requirements: *70289249898780
25
+ version_requirements: *70321134916300
25
26
  - !ruby/object:Gem::Dependency
26
27
  name: activesupport
27
- requirement: &70289249898020 !ruby/object:Gem::Requirement
28
+ requirement: &70321134915080 !ruby/object:Gem::Requirement
28
29
  none: false
29
30
  requirements:
30
31
  - - ~>
@@ -32,10 +33,10 @@ dependencies:
32
33
  version: '3.0'
33
34
  type: :runtime
34
35
  prerelease: false
35
- version_requirements: *70289249898020
36
+ version_requirements: *70321134915080
36
37
  - !ruby/object:Gem::Dependency
37
38
  name: polyamorous
38
- requirement: &70289249897260 !ruby/object:Gem::Requirement
39
+ requirement: &70321134914020 !ruby/object:Gem::Requirement
39
40
  none: false
40
41
  requirements:
41
42
  - - ~>
@@ -43,10 +44,10 @@ dependencies:
43
44
  version: 0.5.0
44
45
  type: :runtime
45
46
  prerelease: false
46
- version_requirements: *70289249897260
47
+ version_requirements: *70321134914020
47
48
  - !ruby/object:Gem::Dependency
48
49
  name: rspec
49
- requirement: &70289249896240 !ruby/object:Gem::Requirement
50
+ requirement: &70321134911960 !ruby/object:Gem::Requirement
50
51
  none: false
51
52
  requirements:
52
53
  - - ~>
@@ -54,10 +55,10 @@ dependencies:
54
55
  version: 2.6.0
55
56
  type: :development
56
57
  prerelease: false
57
- version_requirements: *70289249896240
58
+ version_requirements: *70321134911960
58
59
  - !ruby/object:Gem::Dependency
59
60
  name: machinist
60
- requirement: &70289249894040 !ruby/object:Gem::Requirement
61
+ requirement: &70321134928680 !ruby/object:Gem::Requirement
61
62
  none: false
62
63
  requirements:
63
64
  - - ~>
@@ -65,10 +66,10 @@ dependencies:
65
66
  version: 1.0.6
66
67
  type: :development
67
68
  prerelease: false
68
- version_requirements: *70289249894040
69
+ version_requirements: *70321134928680
69
70
  - !ruby/object:Gem::Dependency
70
71
  name: faker
71
- requirement: &70289249893140 !ruby/object:Gem::Requirement
72
+ requirement: &70321134927360 !ruby/object:Gem::Requirement
72
73
  none: false
73
74
  requirements:
74
75
  - - ~>
@@ -76,10 +77,10 @@ dependencies:
76
77
  version: 0.9.5
77
78
  type: :development
78
79
  prerelease: false
79
- version_requirements: *70289249893140
80
+ version_requirements: *70321134927360
80
81
  - !ruby/object:Gem::Dependency
81
82
  name: sqlite3
82
- requirement: &70289249892520 !ruby/object:Gem::Requirement
83
+ requirement: &70321134925640 !ruby/object:Gem::Requirement
83
84
  none: false
84
85
  requirements:
85
86
  - - ~>
@@ -87,13 +88,13 @@ dependencies:
87
88
  version: 1.3.3
88
89
  type: :development
89
90
  prerelease: false
90
- version_requirements: *70289249892520
91
+ version_requirements: *70321134925640
91
92
  description: ! "\n Squeel unlocks the power of ARel in your Rails 3 application
92
93
  with\n a handy block-based syntax. You can write subqueries, access named\n
93
94
  \ functions provided by your RDBMS, and more, all without writing\n SQL
94
95
  strings.\n "
95
96
  email:
96
- - ernie@metautonomo.us
97
+ - ernie@erniemiller.org
97
98
  executables: []
98
99
  extensions: []
99
100
  extra_rdoc_files: []
@@ -105,6 +106,8 @@ files:
105
106
  - LICENSE
106
107
  - README.md
107
108
  - Rakefile
109
+ - lib/generators/squeel/initializer_generator.rb
110
+ - lib/generators/templates/squeel.rb
108
111
  - lib/squeel.rb
109
112
  - lib/squeel/adapters/active_record.rb
110
113
  - lib/squeel/adapters/active_record/3.0/association_preload_extensions.rb
@@ -183,22 +186,10 @@ files:
183
186
  - spec/squeel/visitors/symbol_visitor_spec.rb
184
187
  - spec/support/schema.rb
185
188
  - squeel.gemspec
186
- homepage: http://metautonomo.us/projects/squeel
189
+ has_rdoc: true
190
+ homepage: http://erniemiller.org/projects/squeel
187
191
  licenses: []
188
- post_install_message: ! '
189
-
190
- *** Thanks for installing Squeel! ***
191
-
192
- Be sure to check out http://metautonomo.us/projects/squeel/ for a
193
-
194
- walkthrough of Squeel''s features, and click the donate link if
195
-
196
- you''re feeling especially appreciative. It''d help me justify this
197
-
198
- "open source" stuff to my lovely wife. :)
199
-
200
-
201
- '
192
+ post_install_message:
202
193
  rdoc_options: []
203
194
  require_paths:
204
195
  - lib
@@ -208,15 +199,21 @@ required_ruby_version: !ruby/object:Gem::Requirement
208
199
  - - ! '>='
209
200
  - !ruby/object:Gem::Version
210
201
  version: '0'
202
+ segments:
203
+ - 0
204
+ hash: -1688941417700106629
211
205
  required_rubygems_version: !ruby/object:Gem::Requirement
212
206
  none: false
213
207
  requirements:
214
208
  - - ! '>='
215
209
  - !ruby/object:Gem::Version
216
210
  version: '0'
211
+ segments:
212
+ - 0
213
+ hash: -1688941417700106629
217
214
  requirements: []
218
215
  rubyforge_project: squeel
219
- rubygems_version: 1.8.10
216
+ rubygems_version: 1.3.9.4
220
217
  signing_key:
221
218
  specification_version: 3
222
219
  summary: ActiveRecord 3, improved.