flounder 0.9.4 → 0.9.5

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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: a2a4bab6f9430ad7169aafe13673bb79debf2d1a
4
- data.tar.gz: ddaa62449b7848ba338f79e48c22eab8d95da823
3
+ metadata.gz: 5e50bc0d92b9351ee20f0dbf9ca3881acf3c58a7
4
+ data.tar.gz: 45da1bd52d62d5fd874f45788564d068e1c47e3a
5
5
  SHA512:
6
- metadata.gz: ef55ee6011bb3a31c99161529775800e347691a93b39b685eb6561c7ad0364a2f1b37d03e8c4236dd99e32d63cfd656900aed69404ffe2143e846dafaac34f91
7
- data.tar.gz: c86cfee4eb453d63af98b23da4a5faeaad3292a3023b983631c159c53ad7bb7037eacd3cc2a8c341b73e0144f79db3166d9377eea5ac0bf10b1f34182f93fad4
6
+ metadata.gz: 87dfe61309ca308686f916ad8475649210720162d660426a6dbaf43dde7e23d8be1c3bc4ce893a901a3623157bc8a2127ff4a52b1f97b9f1f04e5748f5e9bce4
7
+ data.tar.gz: 067d2ef4f6e7adc18e4a1c9a4ef1b5c11ce0bcc00d7ad95648776cccbbcfaf0835e2f995dfa9aec8a633aa2d1cec2cec6354194bcc552ae0400d66da4cbd37a9
data/HISTORY CHANGED
@@ -16,4 +16,9 @@
16
16
  + DELETE FROM - entity#delete
17
17
 
18
18
  0.9.4
19
- + nested transactions
19
+ + nested transactions
20
+
21
+ 0.9.5
22
+ + subquery support
23
+ + localized where as in where(entity, :field => value)
24
+
Binary file
data/flounder.gemspec CHANGED
@@ -2,7 +2,7 @@
2
2
 
3
3
  Gem::Specification.new do |s|
4
4
  s.name = "flounder"
5
- s.version = '0.9.4'
5
+ s.version = '0.9.5'
6
6
  s.summary = "Flounder is a way to write SQL simply in Ruby. It deals with everything BUT object relational mapping. "
7
7
  s.email = "kaspar.schiess@technologyastronauts.ch"
8
8
  s.homepage = "https://bitbucket.org/technologyastronauts/oss_flounder"
@@ -31,12 +31,22 @@ module Flounder::Query
31
31
  # query.where(:id.noteq => 1) # ... WHERE id != 1
32
32
  #
33
33
  def where *conditions
34
+ conditions = conditions.dup
35
+
36
+ resolve_entity = entity
37
+
38
+ # is the first argument an entity? if yes, interpret field names relative
39
+ # to that entity.
40
+ if conditions.size > 1 && conditions.first.kind_of?(Flounder::Entity)
41
+ resolve_entity = conditions.shift
42
+ end
43
+
34
44
  # is this a hash? extract the first element
35
45
  if conditions.size == 1 && conditions.first.kind_of?(Hash)
36
46
  conditions = conditions.first
37
47
 
38
48
  conditions.each do |k, v|
39
- manager.where(transform_tuple(k, v))
49
+ manager.where(transform_tuple(resolve_entity, k, v))
40
50
  end
41
51
  return self
42
52
  end
@@ -125,21 +135,31 @@ module Flounder::Query
125
135
  # * #where
126
136
  # * #on
127
137
  #
128
- def transform_tuple field, value
138
+ def transform_tuple entity, field, value
129
139
  if value.kind_of? Flounder::Field
130
140
  value = value.arel_field
131
141
  end
132
142
 
143
+ if defined?(DataMapper) &&
144
+ defined?(DataMapper::Query::Operator) &&
145
+ field.kind_of?(DataMapper::Query::Operator)
146
+
147
+ # interop: datamapper hijacks some of our operators, let's reverse this
148
+ field = Flounder::SymbolExtensions::Modifier.new(
149
+ field.target, field.operator)
150
+ end
151
+
133
152
  case field
134
153
  # covers: :field_a => ...
135
154
  when Symbol
136
- join_and_condition_part(entity[field].arel_field, value)
155
+ join_and_condition_part(entity, entity[field].arel_field, value)
137
156
  # covers: entity[:field] => ...
138
157
  when Flounder::Field
139
- join_and_condition_part(field.arel_field, value)
158
+ join_and_condition_part(entity, field.arel_field, value)
140
159
  # covers: :field_a.noteq => ...
141
160
  when Flounder::SymbolExtensions::Modifier
142
161
  join_and_condition_part(
162
+ entity,
143
163
  field.to_arel_field(entity),
144
164
  value,
145
165
  field.kind)
@@ -147,8 +167,11 @@ module Flounder::Query
147
167
  fail "Could not transform condition part. (#{field.inspect}, #{value.inspect})"
148
168
  end
149
169
  end
150
- def join_and_condition_part arel_field, value, kind=:eq
170
+ def join_and_condition_part entity, arel_field, value, kind=:eq
151
171
  case value
172
+ # covers subselects
173
+ when Flounder::Query::Base
174
+ arel_field.send(kind, value.manager)
152
175
  # covers :field_a => :field_b
153
176
  when Symbol
154
177
  value_field = entity[value].arel_field
@@ -66,7 +66,7 @@ module Flounder::Query
66
66
  def on join_conditions
67
67
  join_conditions.each do |k, v|
68
68
  manager.on(
69
- transform_tuple(k, join_field(v)))
69
+ transform_tuple(entity, k, join_field(v)))
70
70
  end
71
71
  self
72
72
  end
@@ -102,6 +102,10 @@ module Flounder::Query
102
102
  self
103
103
  end
104
104
 
105
+ def limit n
106
+ manager.take n
107
+ end
108
+
105
109
  alias all kick
106
110
 
107
111
  def each &block
@@ -133,8 +137,8 @@ module Flounder::Query
133
137
  # or respects field values passed in.
134
138
  #
135
139
  def join_field name
136
- return name if name.kind_of? Flounder::Field
137
- @last_join[name]
140
+ return @last_join[name] if name.kind_of?(Symbol)
141
+ name
138
142
  end
139
143
 
140
144
  # Maps an array of field references to Flounder::Field objects. A field
data/lib/flounder.rb CHANGED
@@ -31,6 +31,11 @@ module_function
31
31
  def domain connection, &block
32
32
  Domain.new(connection).tap { |d| yield d if block_given? }
33
33
  end
34
+
35
+ def literal str
36
+ Arel::Nodes::SqlLiteral.new(str)
37
+ end
38
+ module_function :literal
34
39
  end
35
40
 
36
41
  Symbol.send(:include, Flounder::SymbolExtensions)
data/qed/applique/ae.rb CHANGED
@@ -2,6 +2,6 @@ require 'ae'
2
2
 
3
3
  def generates_sql(expected)
4
4
  -> (given) {
5
- given.to_sql.gsub(/^SELECT.*FROM/, 'SELECT [fields] FROM').assert == expected
5
+ given.to_sql.gsub(/^SELECT.*?FROM/, 'SELECT [fields] FROM').assert == expected
6
6
  }
7
7
  end
data/qed/index.md CHANGED
@@ -63,6 +63,13 @@ Fields can be used fully qualified by going through the entity.
63
63
  assert generates_sql("SELECT [fields] FROM \"users\" WHERE \"users\".\"user_id\" = \"users\".\"approver_id\"")
64
64
  ~~~
65
65
 
66
+ By default, symbols are interpreted as field names in the entity that you start your query with. But you can localize your `#where` clause to any other entity.
67
+
68
+ ~~~ruby
69
+ users.where(posts, :id => 1).
70
+ assert generates_sql("SELECT [fields] FROM \"users\" WHERE \"posts\".\"id\" = 1")
71
+ ~~~
72
+
66
73
  # Some JOINs
67
74
 
68
75
  Here are some non-crazy joins that also work.
data/qed/selects.md CHANGED
@@ -44,3 +44,23 @@ You can treat the entities and the queries like an array.
44
44
  query = entity.where(:id => :id)
45
45
  query.size.assert == entity.size
46
46
  ~~~
47
+
48
+ # Subqueries
49
+
50
+ Sometimes you have to say it with a subquery. For example, you might want to look at the latest post for each author in the database.
51
+
52
+ ~~~ruby
53
+ last_post = posts.
54
+ project(:id).
55
+ order_by(:id.desc). # for lack of timestamps, not as a best practice
56
+ where(:approver_id => domain[:users][:id]).limit(1)
57
+
58
+ query = domain[:users].
59
+ join(posts).on(:id => :user_id, posts[:id] => last_post)
60
+
61
+ query.assert generates_sql(%Q(SELECT [fields] FROM "users" INNER JOIN "posts" ON "posts"."id" = (SELECT "posts"."id" FROM "posts" WHERE "posts"."approver_id" = "users"."id" ORDER BY "posts"."id" DESC LIMIT 1)))
62
+
63
+ row = query.first
64
+ row.post.id.assert == 1
65
+ ~~~
66
+
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: flounder
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.9.4
4
+ version: 0.9.5
5
5
  platform: ruby
6
6
  authors:
7
7
  - Kaspar Schiess
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2014-08-14 00:00:00.000000000 Z
12
+ date: 2014-08-20 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: arel
@@ -92,6 +92,7 @@ files:
92
92
  - HISTORY
93
93
  - LICENSE
94
94
  - README
95
+ - flounder-0.9.4.gem
95
96
  - flounder.gemspec
96
97
  - lib/flounder.rb
97
98
  - lib/flounder/connection.rb