flounder 0.9.4 → 0.9.5
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/HISTORY +6 -1
- data/flounder-0.9.4.gem +0 -0
- data/flounder.gemspec +1 -1
- data/lib/flounder/query/base.rb +28 -5
- data/lib/flounder/query/select.rb +7 -3
- data/lib/flounder.rb +5 -0
- data/qed/applique/ae.rb +1 -1
- data/qed/index.md +7 -0
- data/qed/selects.md +20 -0
- metadata +3 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 5e50bc0d92b9351ee20f0dbf9ca3881acf3c58a7
|
4
|
+
data.tar.gz: 45da1bd52d62d5fd874f45788564d068e1c47e3a
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 87dfe61309ca308686f916ad8475649210720162d660426a6dbaf43dde7e23d8be1c3bc4ce893a901a3623157bc8a2127ff4a52b1f97b9f1f04e5748f5e9bce4
|
7
|
+
data.tar.gz: 067d2ef4f6e7adc18e4a1c9a4ef1b5c11ce0bcc00d7ad95648776cccbbcfaf0835e2f995dfa9aec8a633aa2d1cec2cec6354194bcc552ae0400d66da4cbd37a9
|
data/HISTORY
CHANGED
data/flounder-0.9.4.gem
ADDED
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.
|
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"
|
data/lib/flounder/query/base.rb
CHANGED
@@ -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?
|
137
|
-
|
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
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
|
+
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-
|
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
|