smql 0.0.3 → 0.0.4
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.
- data/VERSION +1 -1
- data/lib/smql_to_ar/condition_types.rb +66 -26
- data/lib/smql_to_ar/query_builder.rb +92 -40
- data/lib/smql_to_ar.rb +26 -12
- metadata +3 -3
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.0.
|
1
|
+
0.0.4
|
@@ -33,15 +33,29 @@ class SmqlToAR
|
|
33
33
|
k.split( '|').collect &:to_sym
|
34
34
|
end
|
35
35
|
|
36
|
+
def conditions &e
|
37
|
+
unless block_given?
|
38
|
+
r = Enumerator.new( self, :conditions)
|
39
|
+
s = self
|
40
|
+
r.define_singleton_method :[] do |k|
|
41
|
+
s.conditions.select {|c| c::Operator === k }
|
42
|
+
end
|
43
|
+
return r
|
44
|
+
end
|
45
|
+
constants.each do |c|
|
46
|
+
next if :Condition == c
|
47
|
+
c = const_get c
|
48
|
+
next if Condition === c
|
49
|
+
yield c
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
36
53
|
# Eine Regel parsen.
|
37
54
|
# Ex: Person, "givenname=", "Peter"
|
38
55
|
def try_parse_it model, colop, val
|
39
56
|
r = nil
|
40
57
|
#p :try_parse => { :model => model, :colop => colop, :value => val }
|
41
|
-
|
42
|
-
next if :Condition == c
|
43
|
-
c = const_get c
|
44
|
-
next if Condition === c
|
58
|
+
conditions.each do |c|
|
45
59
|
raise_unless colop =~ /^(?:\d*:)?(.*?)(\W*)$/, UnexpectedColOpError.new( model, colop, val)
|
46
60
|
col, op = $1, $2
|
47
61
|
col = split_keys( col).collect {|c| Column.new model, c }
|
@@ -81,11 +95,17 @@ class SmqlToAR
|
|
81
95
|
Expected = []
|
82
96
|
Where = nil
|
83
97
|
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
98
|
+
class <<self
|
99
|
+
# Versuche das Objekt zu erkennen. Operator und Expected muessen passen.
|
100
|
+
# Passt das Object, die Klasse instanzieren.
|
101
|
+
def try_parse model, cols, op, val
|
102
|
+
#p :self => name, :try_parse => op, :cols => cols, :with => self::Operator, :value => val, :expected => self::Expected, :model => model.name
|
103
|
+
new model, cols, val if self::Operator === op and self::Expected.any?( &it === val)
|
104
|
+
end
|
105
|
+
|
106
|
+
def inspect
|
107
|
+
"#{self.name}(:operator=>#{self::Operator.inspect}, :expected=>#{self::Expected.inspect}, :where=>#{self::Where.inspect})"
|
108
|
+
end
|
89
109
|
end
|
90
110
|
|
91
111
|
def initialize model, cols, val
|
@@ -97,6 +117,10 @@ class SmqlToAR
|
|
97
117
|
verify
|
98
118
|
end
|
99
119
|
|
120
|
+
def inspect
|
121
|
+
"#<#{self.class.name}:0x#{(self.object_id<<1).to_s 16} model: #{self.class.name}, cols: #{@cols.inspect}, value: #{@value.inspect}>"
|
122
|
+
end
|
123
|
+
|
100
124
|
def verify
|
101
125
|
@cols.each do |col|
|
102
126
|
verify_column col
|
@@ -118,8 +142,8 @@ class SmqlToAR
|
|
118
142
|
end
|
119
143
|
|
120
144
|
# Erstelle alle noetigen Klauseln. builder nimmt diese entgegen,
|
121
|
-
# wobei builder.
|
122
|
-
# mehrere Schluessel bedeuten, dass die Values _alle_ zutreffen muessen, wobei die Schluessel
|
145
|
+
# wobei builder.joins, builder.select, builder.where und builder.wobs von interesse sind.
|
146
|
+
# mehrere Schluessel bedeuten, dass die Values _alle_ zutreffen muessen, wobei die Schluessel geODERt werden.
|
123
147
|
# Ex:
|
124
148
|
# 1) {"givenname=", "Peter"} #=> givenname = 'Peter'
|
125
149
|
# 2) {"givenname=", ["Peter", "Hans"]} #=> ( givenname = 'Peter' OR givenname = 'Hans' )
|
@@ -132,11 +156,11 @@ class SmqlToAR
|
|
132
156
|
@cols.each do |col|
|
133
157
|
col.joins builder, table
|
134
158
|
col = builder.column table+col.path, col.col
|
135
|
-
builder.where
|
159
|
+
builder.where values.keys.collect {|vid| self.class::Where % [ col, vid.to_s ] }
|
136
160
|
end
|
137
161
|
else
|
138
162
|
values.keys.each do |vid|
|
139
|
-
builder.where
|
163
|
+
builder.where @cols.collect {|col|
|
140
164
|
col.joins builder, table
|
141
165
|
col = builder.column table+col.path, col.col
|
142
166
|
self.class::Where % [ col, vid.to_s ]
|
@@ -189,19 +213,26 @@ class SmqlToAR
|
|
189
213
|
|
190
214
|
In = simple_condition NotIn, '|=', '%s IN (%s)', [Array]
|
191
215
|
In2 = simple_condition In, '', nil, [Array]
|
192
|
-
NotEqual = simple_condition Condition,
|
216
|
+
NotEqual = simple_condition Condition, '!=', "%s <> %s", [Array, String, Numeric]
|
217
|
+
NotEqual2 = simple_condition Condition, '<>', "%s <> %s", [Array, String, Numeric]
|
193
218
|
GreaterThanOrEqual = simple_condition Condition, '>=', "%s >= %s", [Array, Numeric]
|
194
219
|
LesserThanOrEqual = simple_condition Condition, '<=', "%s <= %s", [Array, Numeric]
|
220
|
+
|
221
|
+
# Examples:
|
222
|
+
# { 'articles=>' => { id: 1 } }
|
223
|
+
# { 'articles=>' => [ { id: 1 }, { id: 2 } ] }
|
195
224
|
class EqualJoin <Condition
|
196
|
-
Operator = '
|
197
|
-
Expected = [Hash]
|
225
|
+
Operator = '=>'
|
226
|
+
Expected = [Hash, lambda {|x| x.kind_of?( Array) and x.all?( &it.kind_of?( Hash))}]
|
198
227
|
|
199
228
|
def initialize *pars
|
200
229
|
super( *pars)
|
230
|
+
@value = Array.wrap @value
|
201
231
|
cols = {}
|
232
|
+
p self: self, cols: @cols
|
202
233
|
@cols.each do |col|
|
203
234
|
col_model = col.relation
|
204
|
-
cols[col] = [col_model] + ConditionTypes.try_parse( col_model,
|
235
|
+
cols[col] = [col_model] + @value.collect {|val| ConditionTypes.try_parse( col_model, val) }
|
205
236
|
end
|
206
237
|
@cols = cols
|
207
238
|
end
|
@@ -212,11 +243,14 @@ class SmqlToAR
|
|
212
243
|
|
213
244
|
def build builder, table
|
214
245
|
@cols.each do |col, sub|
|
246
|
+
model, *sub = sub
|
215
247
|
t = table + col.path + [col.col]
|
216
|
-
col.joins.each {|j, m| builder.
|
217
|
-
builder.
|
218
|
-
sub
|
248
|
+
col.joins.each {|j, m| builder.joins table+j, m }
|
249
|
+
builder.joins t, model
|
250
|
+
b2 = 1 == sub.length ? builder : Or.new( builder)
|
251
|
+
sub.each {|i| i.collect( &it.build( And.new( b2), t)); p 'or' => b2 }
|
219
252
|
end
|
253
|
+
ap '=>' => builder
|
220
254
|
self
|
221
255
|
end
|
222
256
|
end
|
@@ -250,8 +284,7 @@ class SmqlToAR
|
|
250
284
|
def build builder, table
|
251
285
|
@cols.each do |col, sub|
|
252
286
|
t = table+col.to_a
|
253
|
-
|
254
|
-
builder.sub_join t, col, *sub[0..1]
|
287
|
+
builder.sub_joins t, col, *sub[0..1]
|
255
288
|
sub[2..-1].each &it.build( builder, t)
|
256
289
|
end
|
257
290
|
self
|
@@ -264,8 +297,9 @@ class SmqlToAR
|
|
264
297
|
LesserThan = simple_condition Condition, '<', "%s < %s", [Array, Numeric]
|
265
298
|
NotIlike = simple_condition Condition, '!~', "%s NOT ILIKE %s", [Array, String]
|
266
299
|
Ilike = simple_condition Condition, '~', "%s ILIKE %s", [Array, String]
|
300
|
+
Exists = simple_condition Condition, '', '%s IS NOT NULL', [true]
|
301
|
+
NotExists = simple_condition Condition, '', '%s IS NULL', [false]
|
267
302
|
|
268
|
-
####### No Operator #######
|
269
303
|
Join = simple_condition EqualJoin, '', nil, [Hash]
|
270
304
|
InRange2 = simple_condition InRange, '', nil, [Range]
|
271
305
|
class Select < Condition
|
@@ -300,9 +334,15 @@ class SmqlToAR
|
|
300
334
|
Expected = []
|
301
335
|
attr_reader :model, :func, :args
|
302
336
|
|
303
|
-
|
304
|
-
|
305
|
-
|
337
|
+
class <<self
|
338
|
+
def try_parse model, func, args
|
339
|
+
SmqlToAR.logger.info( { try_parse: [func,args]}.inspect)
|
340
|
+
self.new model, func, args if self::Name === func and self::Expected.any?( &it === args)
|
341
|
+
end
|
342
|
+
|
343
|
+
def inspect
|
344
|
+
"#{self.name}(:name=>#{self::Name}, :expected=>#{self::Expected})"
|
345
|
+
end
|
306
346
|
end
|
307
347
|
|
308
348
|
def initialize model, func, args
|
@@ -29,30 +29,34 @@ class SmqlToAR
|
|
29
29
|
end
|
30
30
|
|
31
31
|
attr_reader :table_alias, :model, :table_model, :base_table, :_where, :_select, :_wobs, :_joins, :prefix, :_vid
|
32
|
-
attr_accessor :logger
|
32
|
+
attr_accessor :logger, :limit, :offset
|
33
33
|
|
34
|
-
def initialize model, prefix = nil
|
34
|
+
def initialize model, prefix = nil
|
35
35
|
@prefix = "smql"
|
36
36
|
@logger = SmqlToAR.logger
|
37
37
|
@table_alias = Hash.new do |h, k|
|
38
|
-
|
39
|
-
h[k] = "#{@prefix},#{
|
38
|
+
j = Array.wrap( k).compact
|
39
|
+
h[k] = h.key?(j) ? h[j] : "#{@prefix},#{j.join(',')}"
|
40
40
|
end
|
41
|
-
@_vid, @_where, @_wobs, @model, @quoter = 0, [], {}, model, model.connection
|
42
|
-
@base_table =
|
41
|
+
@_vid, @_where, @_wobs, @model, @quoter = 0, SmqlToAR::And[], {}, model, model.connection
|
42
|
+
@base_table = [model.table_name.to_sym]
|
43
43
|
@table_alias[ @base_table] = @base_table.first
|
44
44
|
t = quote_table_name @table_alias[ @base_table]
|
45
|
-
@_select, @_joins, @_joined, @_includes, @_order = ["DISTINCT #{t}.*"], "", [], [], []
|
45
|
+
@_select, @_joins, @_joined, @_includes, @_order = ["DISTINCT #{t}.*"], "", [@base_table], [], []
|
46
46
|
@table_model = {@base_table => @model}
|
47
47
|
end
|
48
48
|
|
49
49
|
def vid() Vid.new( @_vid+=1) end
|
50
50
|
|
51
|
+
def inspect
|
52
|
+
"#<#{self.class.name}:#{"0x%x"% (self.object_id<<1)}|#{@prefix}:#{@base_table}:#{@model} vid=#{@_vid} where=#{@_where} wobs=#{@_wobs} select=#{@_select} aliases=#{@_table_alias}>"
|
53
|
+
end
|
54
|
+
|
51
55
|
# Jede via where uebergebene Condition wird geodert und alle zusammen werden geundet.
|
52
56
|
# "Konjunktive Normalform". Allerdings duerfen Conditions auch Komplexe Abfragen enthalten.
|
53
|
-
# Ex: builder.where( 'a = a', 'b = c').where( 'c = d', 'e = e').where( 'x = y').where( '( m = n AND o = p )', 'f = g')
|
57
|
+
# Ex: builder.where( ['a = a', 'b = c']).where( ['c = d', 'e = e']).where( 'x = y').where( ['( m = n AND o = p )', 'f = g'])
|
54
58
|
# #=> WHERE ( a = a OR b = c ) AND ( c = d OR e = e ) AND x = y ( ( m = n AND o = p ) OR f = g )
|
55
|
-
def where
|
59
|
+
def where cond
|
56
60
|
@_where.push cond
|
57
61
|
self
|
58
62
|
end
|
@@ -75,28 +79,24 @@ class SmqlToAR
|
|
75
79
|
end
|
76
80
|
|
77
81
|
def build_join orig, pretable, table, prekey, key
|
78
|
-
" JOIN #{orig} AS #{quote_table_name table} ON #{column pretable, prekey} = #{column table, key} "
|
82
|
+
" LEFT OUTER JOIN #{orig} AS #{quote_table_name table} ON #{column pretable, prekey} = #{column table, key} "
|
79
83
|
end
|
80
84
|
|
81
|
-
def
|
82
|
-
|
83
|
-
|
84
|
-
join_ table, model, "(#{query.build( prefix, base_table).tap{|q| p :sub_join => q }.ar.to_sql})"
|
85
|
+
def sub_joins table, col, model, query
|
86
|
+
prefix, base_table = "#{@prefix}_sub", col.relation.table_name
|
87
|
+
join_ table, model, "(#{query.build( prefix).ar.to_sql})"
|
85
88
|
end
|
86
89
|
|
87
90
|
def join_ table, model, query, pretable = nil
|
88
|
-
pp [:join_, table, model, query]
|
89
91
|
pretable ||= table[0...-1]
|
90
92
|
@table_model[ table] = model
|
91
93
|
premodel = @table_model[ pretable]
|
92
94
|
t = @table_alias[ table]
|
93
95
|
pt = quote_table_name @table_alias[ table[ 0...-1]]
|
94
|
-
pp premodel: premodel, table: table
|
95
96
|
refl = premodel.reflections[table.last]
|
96
97
|
case refl
|
97
98
|
when ActiveRecord::Reflection::ThroughReflection
|
98
99
|
through = refl.through_reflection
|
99
|
-
pp refl: refl
|
100
100
|
throughtable = table[0...-1]+[through.name.to_sym]
|
101
101
|
srctable = throughtable+[refl.source_reflection.name]
|
102
102
|
@table_model[ srctable] = model
|
@@ -120,7 +120,8 @@ class SmqlToAR
|
|
120
120
|
self
|
121
121
|
end
|
122
122
|
|
123
|
-
def
|
123
|
+
def joins table, model
|
124
|
+
table = table.flatten.compact
|
124
125
|
return self if @_joined.include? table # Already joined
|
125
126
|
join_ table, model, quote_table_name( model.table_name)
|
126
127
|
@_joined.push table
|
@@ -140,40 +141,22 @@ class SmqlToAR
|
|
140
141
|
@_order.push "#{column table, col} #{:DESC == o ? :DESC : :ASC}"
|
141
142
|
end
|
142
143
|
|
143
|
-
def limit count
|
144
|
-
@_limit = count
|
145
|
-
end
|
146
|
-
|
147
|
-
def offset count
|
148
|
-
@_offset = count
|
149
|
-
end
|
150
|
-
|
151
|
-
class Dummy
|
152
|
-
def method_missing m, *a, &e
|
153
|
-
#p :dummy => m, :pars => a, :block => e
|
154
|
-
self
|
155
|
-
end
|
156
|
-
end
|
157
|
-
|
158
144
|
def build_ar
|
159
|
-
where_str = @_where.
|
160
|
-
w = Array.wrap w
|
161
|
-
1 == w.length ? w.first : "( #{w.join( ' OR ')} )"
|
162
|
-
end.join ' AND '
|
145
|
+
where_str = @_where.type_correction!.optimize!.tap {|x| p x }.build_where
|
163
146
|
incls = {}
|
164
147
|
@_includes.each do |inc|
|
165
148
|
b = incls
|
166
149
|
inc[1..-1].collect {|rel| b = b[rel] ||= {} }
|
167
150
|
end
|
168
|
-
@logger.
|
151
|
+
@logger.info where: where_str, wobs: @_wobs
|
169
152
|
@model = @model.
|
170
153
|
select( @_select.join( ', ')).
|
171
154
|
joins( @_joins).
|
172
155
|
where( where_str, @_wobs).
|
173
156
|
order( @_order.join( ', ')).
|
174
157
|
includes( incls)
|
175
|
-
@model = @model.limit @
|
176
|
-
@model = @model.offset @
|
158
|
+
@model = @model.limit @limit if @limit
|
159
|
+
@model = @model.offset @offset if @offset
|
177
160
|
@model
|
178
161
|
end
|
179
162
|
|
@@ -193,4 +176,73 @@ class SmqlToAR
|
|
193
176
|
@model
|
194
177
|
end
|
195
178
|
end
|
179
|
+
|
180
|
+
class SubBuilder < Array
|
181
|
+
attr_reader :parent, :_where
|
182
|
+
delegate :wobs, :joins, :includes, :sub_joins, :vid, :quote_column_name, :quoter, :quote_table_name, :column, :to => :parent
|
183
|
+
|
184
|
+
def initialize parent, tmp = false
|
185
|
+
p init: self, parent: parent
|
186
|
+
@parent = parent
|
187
|
+
@parent.where self unless @parend.nil? && tmp
|
188
|
+
end
|
189
|
+
|
190
|
+
def new parent, tmp = false
|
191
|
+
super parent, tmp
|
192
|
+
#return parent if self.class == parent.class
|
193
|
+
#super parent
|
194
|
+
end
|
195
|
+
|
196
|
+
alias where push
|
197
|
+
|
198
|
+
def type_correction!
|
199
|
+
collect! do |sub|
|
200
|
+
if sub.kind_of? Array
|
201
|
+
sub = default[ *sub] unless sub.respond_to?( :type_correction!)
|
202
|
+
sub.type_correction!
|
203
|
+
end
|
204
|
+
sub
|
205
|
+
end
|
206
|
+
self
|
207
|
+
end
|
208
|
+
|
209
|
+
def optimize!
|
210
|
+
p optimize: self
|
211
|
+
ext = []
|
212
|
+
collect! do |sub|
|
213
|
+
sub = sub.optimize! if sub.kind_of? Array
|
214
|
+
if self.class == sub.class
|
215
|
+
ext.push *sub
|
216
|
+
nil
|
217
|
+
elsif sub.blank?
|
218
|
+
nil
|
219
|
+
else
|
220
|
+
sub
|
221
|
+
end
|
222
|
+
end.compact!
|
223
|
+
p optimized: self
|
224
|
+
p ext: ext
|
225
|
+
push *ext
|
226
|
+
self
|
227
|
+
end
|
228
|
+
|
229
|
+
def inspect
|
230
|
+
"#{self.class.name.sub( /.*::/, '')}[ #{collect(&:inspect).join ', '}]"
|
231
|
+
end
|
232
|
+
def default() SmqlToAR::And end
|
233
|
+
def default_new( parent) default.new self, parent, false end
|
234
|
+
end
|
235
|
+
|
236
|
+
class And < SubBuilder
|
237
|
+
def default; SmqlToAR::Or; end
|
238
|
+
def build_where
|
239
|
+
join ' AND '
|
240
|
+
end
|
241
|
+
end
|
242
|
+
|
243
|
+
class Or < SubBuilder
|
244
|
+
def build_where
|
245
|
+
join ' OR '
|
246
|
+
end
|
247
|
+
end
|
196
248
|
end
|
data/lib/smql_to_ar.rb
CHANGED
@@ -107,7 +107,9 @@ class SmqlToAR
|
|
107
107
|
|
108
108
|
# Model der Relation `rel` von `model`
|
109
109
|
def self.model_of model, rel
|
110
|
-
|
110
|
+
rel = rel.to_sym
|
111
|
+
r = model.reflections[ rel].andand.klass
|
112
|
+
r.nil? && :self == rel ? model : r
|
111
113
|
end
|
112
114
|
|
113
115
|
# Eine Spalte in einer Tabelle, relativ zu `Column#model`.
|
@@ -121,7 +123,7 @@ class SmqlToAR
|
|
121
123
|
def initialize model, *col
|
122
124
|
@model = model
|
123
125
|
@last_model = nil
|
124
|
-
*@path, @col = Array.wrap( col).collect( &it.to_s.split( /[.\/]/)).flatten.collect( &:to_sym)
|
126
|
+
*@path, @col = *Array.wrap( col).collect( &it.to_s.split( /[.\/]/)).flatten.collect( &:to_sym).reject( &it==:self)
|
125
127
|
end
|
126
128
|
|
127
129
|
def last_model
|
@@ -131,9 +133,12 @@ class SmqlToAR
|
|
131
133
|
def each
|
132
134
|
model = @model
|
133
135
|
@path.each do |rel|
|
134
|
-
|
135
|
-
|
136
|
-
|
136
|
+
rel = rel.to_sym
|
137
|
+
unless :self == rel
|
138
|
+
model = SmqlToAR.model_of model, rel
|
139
|
+
return false unless model
|
140
|
+
yield rel, model
|
141
|
+
end
|
137
142
|
end
|
138
143
|
model
|
139
144
|
end
|
@@ -158,20 +163,21 @@ class SmqlToAR
|
|
158
163
|
def joins builder = nil, table = nil, &exe
|
159
164
|
pp = []
|
160
165
|
table = Array.wrap table
|
161
|
-
exe ||= builder ? lambda {|j, m| builder.
|
166
|
+
exe ||= builder ? lambda {|j, m| builder.joins table+j, m} : Array.method( :[])
|
162
167
|
collect do |rel, model|
|
163
168
|
pp.push rel
|
164
169
|
exe.call pp, model
|
165
170
|
end
|
166
171
|
end
|
167
|
-
def
|
168
|
-
def
|
169
|
-
def
|
172
|
+
def self?() !@col end
|
173
|
+
def length() @path.length+(self.self? ? 0 : 1) end
|
174
|
+
def size() @path.size+(self.self? ? 0 : 1) end
|
175
|
+
def to_a() @path+(self.self? ? [] : [@col]) end
|
170
176
|
def to_s() to_a.join '.' end
|
171
177
|
def to_sym() to_s.to_sym end
|
172
178
|
def to_json() to_s end
|
173
179
|
def inspect() "#<Column: #{model} #{to_s}>" end
|
174
|
-
def relation() SmqlToAR.model_of last_model, @col end
|
180
|
+
def relation() self.self? ? model : SmqlToAR.model_of( last_model, @col) end
|
175
181
|
def allowed?() ! self.protected? end
|
176
182
|
def child?() @path.empty? and !!relation end
|
177
183
|
end
|
@@ -225,9 +231,9 @@ class SmqlToAR
|
|
225
231
|
self
|
226
232
|
end
|
227
233
|
|
228
|
-
def build prefix = nil
|
234
|
+
def build prefix = nil
|
229
235
|
benchmark 'SMQL build query' do
|
230
|
-
@builder = QueryBuilder.new @model, prefix
|
236
|
+
@builder = QueryBuilder.new @model, prefix
|
231
237
|
table = @builder.base_table
|
232
238
|
@conditions.each &it.build( builder, table)
|
233
239
|
end
|
@@ -252,4 +258,12 @@ class SmqlToAR
|
|
252
258
|
def self.to_ar *params
|
253
259
|
new( *params).to_ar
|
254
260
|
end
|
261
|
+
|
262
|
+
def self.reload_library
|
263
|
+
lib_dir = File.dirname __FILE__
|
264
|
+
fj = lambda {|*a| File.join lib_dir, *a }
|
265
|
+
load fj.call( 'smql_to_ar.rb')
|
266
|
+
load fj.call( 'smql_to_ar', 'condition_types.rb')
|
267
|
+
load fj.call( 'smql_to_ar', 'query_builder.rb')
|
268
|
+
end
|
255
269
|
end
|
metadata
CHANGED
@@ -5,8 +5,8 @@ version: !ruby/object:Gem::Version
|
|
5
5
|
segments:
|
6
6
|
- 0
|
7
7
|
- 0
|
8
|
-
-
|
9
|
-
version: 0.0.
|
8
|
+
- 4
|
9
|
+
version: 0.0.4
|
10
10
|
platform: ruby
|
11
11
|
authors:
|
12
12
|
- Denis Knauf
|
@@ -14,7 +14,7 @@ autorequire:
|
|
14
14
|
bindir: bin
|
15
15
|
cert_chain: []
|
16
16
|
|
17
|
-
date: 2011-
|
17
|
+
date: 2011-10-05 00:00:00 +02:00
|
18
18
|
default_executable:
|
19
19
|
dependencies:
|
20
20
|
- !ruby/object:Gem::Dependency
|