active_reporting 0.3.0 → 0.4.0
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 +4 -4
- data/.rubocop.yml +3 -2
- data/.travis.yml +1 -0
- data/CHANGELOG.md +14 -4
- data/README.md +39 -3
- data/Rakefile +2 -0
- data/active_reporting.gemspec +7 -6
- data/bin/console +1 -0
- data/lib/active_reporting.rb +4 -2
- data/lib/active_reporting/active_record_adaptor.rb +3 -1
- data/lib/active_reporting/configuration.rb +2 -0
- data/lib/active_reporting/dimension.rb +13 -3
- data/lib/active_reporting/dimension_filter.rb +2 -0
- data/lib/active_reporting/fact_model.rb +6 -2
- data/lib/active_reporting/metric.rb +3 -1
- data/lib/active_reporting/report.rb +2 -0
- data/lib/active_reporting/reporting_dimension.rb +54 -15
- data/lib/active_reporting/version.rb +3 -1
- metadata +19 -19
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA1:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 7a5444ba19be4d20842e16f8e800e45837e133bd
|
|
4
|
+
data.tar.gz: 24b59685e4cd70770a13a8a2925c85d860e782a3
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 1df566a6122ec806f231a116ffe33cf729374fe529ddf18a2763cb2462946414c60bada55a06e7fc036ef3c4fc0002f021d06b1147cb011c7810ce1b517cd82e
|
|
7
|
+
data.tar.gz: 0ec9387af8a5918f3685732b4331377302e373ae56843305991d2c8abc24928c4a19ea79ed7d3bd6b5e979204c2a15cde3806df62a282a8714ac0d6a439fb4e6
|
data/.rubocop.yml
CHANGED
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
AllCops:
|
|
2
2
|
Exclude:
|
|
3
3
|
- test/**/*
|
|
4
|
-
|
|
4
|
+
- Gemfile
|
|
5
|
+
TargetRubyVersion: 2.3
|
|
5
6
|
|
|
6
7
|
Metrics/LineLength:
|
|
7
8
|
Max: 120
|
|
@@ -18,7 +19,7 @@ Style/ClassAndModuleChildren:
|
|
|
18
19
|
Style/Documentation:
|
|
19
20
|
Enabled: false
|
|
20
21
|
|
|
21
|
-
Style/
|
|
22
|
+
Style/Name:
|
|
22
23
|
Enabled: false
|
|
23
24
|
|
|
24
25
|
Style/RaiseArgs:
|
data/.travis.yml
CHANGED
data/CHANGELOG.md
CHANGED
|
@@ -1,9 +1,19 @@
|
|
|
1
|
+
## 0.4.0 (2018-05-02)
|
|
2
|
+
|
|
3
|
+
### Breaking Changes
|
|
4
|
+
|
|
5
|
+
* Gemspec now requires Ruby 2.3 and later to install
|
|
6
|
+
|
|
7
|
+
### Features
|
|
8
|
+
|
|
9
|
+
* Dimension off of `datetime` columns by date parts in PostgreSQL (See README for details) (#10) - *niborg*
|
|
10
|
+
|
|
1
11
|
## 0.3.0 (2018-04-12)
|
|
2
12
|
|
|
3
13
|
### Bug Fixes
|
|
4
14
|
|
|
5
|
-
* Specify rescue from LoadError for ransack (#9) *niborg*
|
|
6
|
-
* Fix ransack fallback logic *germanotm*
|
|
15
|
+
* Specify rescue from LoadError for ransack (#9) - *niborg*
|
|
16
|
+
* Fix ransack fallback logic (#8) - *germanotm*
|
|
7
17
|
|
|
8
18
|
## Misc
|
|
9
19
|
|
|
@@ -20,11 +30,11 @@
|
|
|
20
30
|
|
|
21
31
|
### Bug Fixes
|
|
22
32
|
|
|
23
|
-
* `metric` lives on fact model and not metric (#3) - *
|
|
33
|
+
* `metric` lives on fact model and not metric (#3) - *wheeyls*
|
|
24
34
|
|
|
25
35
|
### Misc
|
|
26
36
|
|
|
27
|
-
* Readme corrections and updates (#2) - *
|
|
37
|
+
* Readme corrections and updates (#2) - *wheeyls*
|
|
28
38
|
|
|
29
39
|
## 0.1.1 (2017-04-22)
|
|
30
40
|
|
data/README.md
CHANGED
|
@@ -219,6 +219,24 @@ class PhoneFactModel < ActiveReporting::FactModel
|
|
|
219
219
|
end
|
|
220
220
|
```
|
|
221
221
|
|
|
222
|
+
### Implicit hierarchies with datetime columns (PostgreSQL support only)
|
|
223
|
+
|
|
224
|
+
The fastest approach to group by certain date metrics is to create so-called "date dimensions". For
|
|
225
|
+
those Postgres users that are restricted from organizing their data in this way, Postgres provides
|
|
226
|
+
a way to group by `datetime` column data on the fly using the `date_trunc` function.
|
|
227
|
+
|
|
228
|
+
To use, declare a datetime dimension on a fact model as normal:
|
|
229
|
+
|
|
230
|
+
```ruby
|
|
231
|
+
class UserFactModel < ActiveReporting::FactModel
|
|
232
|
+
dimension :created_at
|
|
233
|
+
end
|
|
234
|
+
```
|
|
235
|
+
|
|
236
|
+
When creating a metric, ActiveReporting will recognize implicit hierarchies for this dimension. The hierarchies correspond to the [values](https://www.postgresql.org/docs/8.1/static/functions-datetime.html#FUNCTIONS-DATETIME-TRUNC) supported by PostgreSQL. (See example under the metric section, below.)
|
|
237
|
+
|
|
238
|
+
*NOTE*: PRs welcomed to support this functionality in other databases.
|
|
239
|
+
|
|
222
240
|
## Configuring Dimension Filters
|
|
223
241
|
|
|
224
242
|
A dimension filter provides filtering for a report. In SQL-land, this is the `WHERE` clause.
|
|
@@ -275,6 +293,20 @@ my_metric = ActiveReporting::Metric.new(
|
|
|
275
293
|
|
|
276
294
|
`order_by_dimension` - Allows you to set the ordering of the results based on a dimension label. (Examples: `{author: :desc}`, `{sales_ref: :asc}`)
|
|
277
295
|
|
|
296
|
+
For those using Postgres, you can take advantage of implicit hierarchies in `datetime` columns, as mentioned above:
|
|
297
|
+
|
|
298
|
+
```ruby
|
|
299
|
+
class UserFactModel < ActiveReporting::FactModel
|
|
300
|
+
dimension :created_at
|
|
301
|
+
end
|
|
302
|
+
|
|
303
|
+
my_metric = ActiveReporting::Metric.new(
|
|
304
|
+
:my_total,
|
|
305
|
+
fact_model: UserFactModel,
|
|
306
|
+
dimensions: [{ created_at: :quarter } ]
|
|
307
|
+
)
|
|
308
|
+
```
|
|
309
|
+
|
|
278
310
|
## ActiveReporting::Report
|
|
279
311
|
|
|
280
312
|
A `Report` takes an `ActiveReporting::Metric` and ties everything together. It is responsible for building and executing the query to generate a result. The result is an simple array of hashing.
|
|
@@ -283,7 +315,7 @@ A `Report` takes an `ActiveReporting::Metric` and ties everything together. It i
|
|
|
283
315
|
metric = ActiveReporting::Metric.new(
|
|
284
316
|
:order_count,
|
|
285
317
|
fact_model: OrderFactModel,
|
|
286
|
-
|
|
318
|
+
dimensions: [:sales_rep],
|
|
287
319
|
dimension_filter: {months_ago: 1}
|
|
288
320
|
)
|
|
289
321
|
|
|
@@ -306,7 +338,7 @@ A `Report` may also take additional arguments to merge with the `Metric`'s infor
|
|
|
306
338
|
metric = ActiveReporting::Metric.new(
|
|
307
339
|
:order_count,
|
|
308
340
|
fact_model: OrderFactModel,
|
|
309
|
-
|
|
341
|
+
dimensions: [:sales_rep],
|
|
310
342
|
dimension_filter: {months_ago: 1}
|
|
311
343
|
)
|
|
312
344
|
|
|
@@ -335,6 +367,11 @@ After checking out the repo, run `bin/setup` to install dependencies. Then, run
|
|
|
335
367
|
|
|
336
368
|
To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and tags, and push the `.gem` file to [rubygems.org](https://rubygems.org).
|
|
337
369
|
|
|
370
|
+
## Testing
|
|
371
|
+
|
|
372
|
+
You can run the test suite using `rake test`. To test against a particular database, you'll need to set the
|
|
373
|
+
appropriate `DB` environment variable, e.g. `DB=pg rake test`.
|
|
374
|
+
|
|
338
375
|
## Contributing
|
|
339
376
|
|
|
340
377
|
Bug reports and pull requests are welcome on GitHub at https://github.com/[USERNAME]/active_reporting. This project is intended to be a safe, welcoming space for collaboration, and contributors are expected to adhere to the [Contributor Covenant](http://contributor-covenant.org) code of conduct.
|
|
@@ -343,4 +380,3 @@ Bug reports and pull requests are welcome on GitHub at https://github.com/[USERN
|
|
|
343
380
|
## License
|
|
344
381
|
|
|
345
382
|
The gem is available as open source under the terms of the [MIT License](http://opensource.org/licenses/MIT).
|
|
346
|
-
|
data/Rakefile
CHANGED
data/active_reporting.gemspec
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
|
-
#
|
|
2
|
-
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
lib = File.expand_path('lib', __dir__)
|
|
3
4
|
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
|
4
5
|
require 'active_reporting/version'
|
|
5
6
|
|
|
@@ -21,16 +22,16 @@ Gem::Specification.new do |spec|
|
|
|
21
22
|
spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
|
|
22
23
|
spec.require_paths = ['lib']
|
|
23
24
|
|
|
24
|
-
spec.required_ruby_version = '>= 2.
|
|
25
|
+
spec.required_ruby_version = '>= 2.3'
|
|
25
26
|
|
|
26
27
|
spec.add_dependency 'activerecord', '>= 4.2.0'
|
|
27
28
|
spec.add_dependency 'activesupport', '>= 4.2.0'
|
|
28
29
|
|
|
29
30
|
spec.add_development_dependency 'bundler'
|
|
30
|
-
spec.add_development_dependency 'rake', '~> 10.0'
|
|
31
31
|
spec.add_development_dependency 'minitest', '~> 5.0'
|
|
32
|
+
spec.add_development_dependency 'mysql2'
|
|
33
|
+
spec.add_development_dependency 'pg'
|
|
34
|
+
spec.add_development_dependency 'rake', '~> 10.0'
|
|
32
35
|
spec.add_development_dependency 'ransack'
|
|
33
36
|
spec.add_development_dependency 'sqlite3'
|
|
34
|
-
spec.add_development_dependency 'pg'
|
|
35
|
-
spec.add_development_dependency 'mysql2'
|
|
36
37
|
end
|
data/bin/console
CHANGED
data/lib/active_reporting.rb
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
1
3
|
require 'active_record'
|
|
2
4
|
require 'active_reporting/active_record_adaptor'
|
|
3
5
|
require 'active_reporting/configuration'
|
|
@@ -23,8 +25,8 @@ module ActiveReporting
|
|
|
23
25
|
klass = Configuration.metric_lookup_class
|
|
24
26
|
unless defined?(klass.constantize)
|
|
25
27
|
raise BadMetricLookupClass,
|
|
26
|
-
|
|
27
|
-
|
|
28
|
+
"#{klass} not defined. Please define a class responsible for looking up a metric by name." \
|
|
29
|
+
' You may define your own class and set it with `ActiveReporting::Configuration.metric_lookup_class=`.'
|
|
28
30
|
end
|
|
29
31
|
unless klass.constantize.respond_to?(:lookup)
|
|
30
32
|
raise BadMetricLookupClass, "#{klass} needs to define a class method called 'lookup'"
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
1
3
|
module ActiveReporting
|
|
2
4
|
# This is included into every class that inherits from ActiveRecord::Base
|
|
3
5
|
module ActiveRecordAdaptor
|
|
@@ -13,7 +15,7 @@ module ActiveReporting
|
|
|
13
15
|
const_name.constantize
|
|
14
16
|
rescue NameError
|
|
15
17
|
const = Object.const_set(const_name, Class.new(ActiveReporting::FactModel))
|
|
16
|
-
const.model= self
|
|
18
|
+
const.model = self
|
|
17
19
|
const
|
|
18
20
|
end
|
|
19
21
|
end
|
|
@@ -1,5 +1,8 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
1
3
|
module ActiveReporting
|
|
2
4
|
class Dimension
|
|
5
|
+
TYPES = { degenerate: :degenerate, standard: :standard }.freeze
|
|
3
6
|
attr_reader :name
|
|
4
7
|
|
|
5
8
|
# @param model [ActiveRecord::Base]
|
|
@@ -19,14 +22,21 @@ module ActiveReporting
|
|
|
19
22
|
# @return [Symbol]
|
|
20
23
|
def type
|
|
21
24
|
@type ||= if model.column_names.include?(@name)
|
|
22
|
-
:degenerate
|
|
25
|
+
TYPES[:degenerate]
|
|
23
26
|
elsif association
|
|
24
|
-
:standard
|
|
27
|
+
TYPES[:standard]
|
|
25
28
|
else
|
|
26
29
|
raise UnknownDimension, "Dimension '#{@name}' not found on fact model '#{@fact_model}'"
|
|
27
30
|
end
|
|
28
31
|
end
|
|
29
32
|
|
|
33
|
+
# Whether the dimension is a datetime column
|
|
34
|
+
#
|
|
35
|
+
# @return [Boolean]
|
|
36
|
+
def datetime?
|
|
37
|
+
@datetime ||= type == TYPES[:degenerate] && model.column_for_attribute(@name).type == :datetime
|
|
38
|
+
end
|
|
39
|
+
|
|
30
40
|
# Tells if the dimension is hierarchical
|
|
31
41
|
#
|
|
32
42
|
# @return [Boolean]
|
|
@@ -53,7 +63,7 @@ module ActiveReporting
|
|
|
53
63
|
#
|
|
54
64
|
# @return [ActiveRecord::Reflection]
|
|
55
65
|
def association
|
|
56
|
-
@
|
|
66
|
+
@association ||= model.reflect_on_association(@name)
|
|
57
67
|
end
|
|
58
68
|
end
|
|
59
69
|
end
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
1
3
|
module ActiveReporting
|
|
2
4
|
class FactModel
|
|
3
5
|
class << self
|
|
@@ -109,7 +111,7 @@ module ActiveReporting
|
|
|
109
111
|
# @param body [Lambda]
|
|
110
112
|
def self.dimension_label_callback(column, body)
|
|
111
113
|
@dimension_label_callbacks ||= {}
|
|
112
|
-
raise ArgumentError,
|
|
114
|
+
raise ArgumentError, 'Dimension label callback body must be a callable object' unless body.respond_to?(:call)
|
|
113
115
|
@dimension_label_callbacks[column.to_sym] = body
|
|
114
116
|
end
|
|
115
117
|
|
|
@@ -143,7 +145,9 @@ module ActiveReporting
|
|
|
143
145
|
# Invoke this method to make all dimension filters fallback to use ransack
|
|
144
146
|
# if they are not defined as scopes on the model
|
|
145
147
|
def self.use_ransack_for_unknown_dimension_filters
|
|
146
|
-
|
|
148
|
+
unless Configuration.ransack_available
|
|
149
|
+
raise RansackNotAvailable, 'Ransack not available. Please include it in your Gemfile.'
|
|
150
|
+
end
|
|
147
151
|
@ransack_fallback = true
|
|
148
152
|
end
|
|
149
153
|
|
|
@@ -1,20 +1,27 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
1
3
|
require 'forwardable'
|
|
2
4
|
module ActiveReporting
|
|
3
5
|
class ReportingDimension
|
|
4
6
|
extend Forwardable
|
|
5
|
-
|
|
7
|
+
SUPPORTED_DBS = %w[PostgreSQL PostGIS].freeze
|
|
8
|
+
# Values for the Postgres `date_trunc` method.
|
|
9
|
+
# See https://www.postgresql.org/docs/10/static/functions-datetime.html#FUNCTIONS-DATETIME-TRUNC
|
|
10
|
+
DATETIME_HIERARCHIES = %i[microseconds milliseconds second minute hour day week month quarter year decade
|
|
11
|
+
century millennium].freeze
|
|
12
|
+
def_delegators :@dimension, :name, :type, :klass, :association, :model, :hierarchical?, :datetime?
|
|
6
13
|
|
|
7
14
|
def self.build_from_dimensions(fact_model, dimensions)
|
|
8
15
|
Array(dimensions).map do |dim|
|
|
9
16
|
dimension_name, label = dim.is_a?(Hash) ? Array(dim).flatten : [dim, nil]
|
|
10
17
|
found_dimension = fact_model.dimensions[dimension_name.to_sym]
|
|
11
|
-
if found_dimension.nil?
|
|
12
|
-
raise UnknownDimension, "Dimension '#{dim}' not found on fact model '#{fact_model}'"
|
|
13
|
-
end
|
|
18
|
+
raise UnknownDimension, "Dimension '#{dim}' not found on fact model '#{fact_model}'" if found_dimension.nil?
|
|
14
19
|
new(found_dimension, label: label)
|
|
15
20
|
end
|
|
16
21
|
end
|
|
17
22
|
|
|
23
|
+
# @param dimension [ActiveReporting::Dimension]
|
|
24
|
+
# @option label [Symbol] Hierarchical dimension to be used as a label
|
|
18
25
|
def initialize(dimension, label: nil)
|
|
19
26
|
@dimension = dimension
|
|
20
27
|
determine_label(label)
|
|
@@ -31,7 +38,7 @@ module ActiveReporting
|
|
|
31
38
|
#
|
|
32
39
|
# @return [Array]
|
|
33
40
|
def select_statement(with_identifier: true)
|
|
34
|
-
return [
|
|
41
|
+
return [degenerate_select_fragment] if type == Dimension::TYPES[:degenerate]
|
|
35
42
|
|
|
36
43
|
ss = ["#{label_fragment} AS #{name}"]
|
|
37
44
|
ss << "#{identifier_fragment} AS #{name}_identifier" if with_identifier
|
|
@@ -42,7 +49,7 @@ module ActiveReporting
|
|
|
42
49
|
#
|
|
43
50
|
# @return [Array]
|
|
44
51
|
def group_by_statement(with_identifier: true)
|
|
45
|
-
return [degenerate_fragment] if type == :degenerate
|
|
52
|
+
return [degenerate_fragment] if type == Dimension::TYPES[:degenerate]
|
|
46
53
|
|
|
47
54
|
group = [label_fragment]
|
|
48
55
|
group << identifier_fragment if with_identifier
|
|
@@ -54,8 +61,8 @@ module ActiveReporting
|
|
|
54
61
|
# @return [String]
|
|
55
62
|
def order_by_statement(direction:)
|
|
56
63
|
direction = direction.to_s.upcase
|
|
57
|
-
raise "Ording direction should be 'asc' or 'desc'" unless %w
|
|
58
|
-
return "#{degenerate_fragment} #{direction}" if type == :degenerate
|
|
64
|
+
raise "Ording direction should be 'asc' or 'desc'" unless %w[ASC DESC].include?(direction)
|
|
65
|
+
return "#{degenerate_fragment} #{direction}" if type == Dimension::TYPES[:degenerate]
|
|
59
66
|
"#{label_fragment} #{direction}"
|
|
60
67
|
end
|
|
61
68
|
|
|
@@ -69,21 +76,53 @@ module ActiveReporting
|
|
|
69
76
|
private ####################################################################
|
|
70
77
|
|
|
71
78
|
def determine_label(label)
|
|
72
|
-
@label =
|
|
73
|
-
|
|
79
|
+
@label = if label.present? && validate_hierarchical_label(label)
|
|
80
|
+
label.to_sym
|
|
81
|
+
else
|
|
82
|
+
dimension_fact_model.dimension_label || Configuration.default_dimension_label
|
|
83
|
+
end
|
|
74
84
|
end
|
|
75
85
|
|
|
76
86
|
def validate_hierarchical_label(hierarchical_label)
|
|
77
|
-
if
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
87
|
+
if datetime?
|
|
88
|
+
validate_supported_database_for_datetime_hierarchies
|
|
89
|
+
validate_against_datetime_hierarchies(hierarchical_label)
|
|
90
|
+
else
|
|
91
|
+
validate_dimension_is_hierachical(hierarchical_label)
|
|
92
|
+
validate_against_fact_model_properties(hierarchical_label)
|
|
82
93
|
end
|
|
83
94
|
true
|
|
84
95
|
end
|
|
85
96
|
|
|
97
|
+
def validate_dimension_is_hierachical(hierarchical_label)
|
|
98
|
+
return if hierarchical?
|
|
99
|
+
raise InvalidDimensionLabel, "#{name} must be hierarchical to use label #{hierarchical_label}"
|
|
100
|
+
end
|
|
101
|
+
|
|
102
|
+
def validate_supported_database_for_datetime_hierarchies
|
|
103
|
+
return if SUPPORTED_DBS.include?(model.connection.adapter_name)
|
|
104
|
+
raise InvalidDimensionLabel,
|
|
105
|
+
"Cannot utilize datetime grouping for #{name}; " \
|
|
106
|
+
"database #{model.connection.adapter_name} is not supported"
|
|
107
|
+
end
|
|
108
|
+
|
|
109
|
+
def validate_against_datetime_hierarchies(hierarchical_label)
|
|
110
|
+
return if DATETIME_HIERARCHIES.include?(hierarchical_label.to_sym)
|
|
111
|
+
raise InvalidDimensionLabel, "#{hierarchical_label} is not a valid datetime grouping label in #{name}"
|
|
112
|
+
end
|
|
113
|
+
|
|
114
|
+
def validate_against_fact_model_properties(hierarchical_label)
|
|
115
|
+
return if dimension_fact_model.hierarchical_levels.include?(hierarchical_label.to_sym)
|
|
116
|
+
raise InvalidDimensionLabel, "#{hierarchical_label} is not a hierarchical label in #{name}"
|
|
117
|
+
end
|
|
118
|
+
|
|
86
119
|
def degenerate_fragment
|
|
120
|
+
return "#{name}_#{@label}" if datetime?
|
|
121
|
+
"#{model.quoted_table_name}.#{name}"
|
|
122
|
+
end
|
|
123
|
+
|
|
124
|
+
def degenerate_select_fragment
|
|
125
|
+
return "DATE_TRUNC('#{@label}', #{model.quoted_table_name}.#{name}) AS #{name}_#{@label}" if datetime?
|
|
87
126
|
"#{model.quoted_table_name}.#{name}"
|
|
88
127
|
end
|
|
89
128
|
|
metadata
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: active_reporting
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.
|
|
4
|
+
version: 0.4.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Tony Drake
|
|
8
8
|
autorequire:
|
|
9
9
|
bindir: exe
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date: 2018-
|
|
11
|
+
date: 2018-05-03 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: activerecord
|
|
@@ -53,35 +53,35 @@ dependencies:
|
|
|
53
53
|
- !ruby/object:Gem::Version
|
|
54
54
|
version: '0'
|
|
55
55
|
- !ruby/object:Gem::Dependency
|
|
56
|
-
name:
|
|
56
|
+
name: minitest
|
|
57
57
|
requirement: !ruby/object:Gem::Requirement
|
|
58
58
|
requirements:
|
|
59
59
|
- - "~>"
|
|
60
60
|
- !ruby/object:Gem::Version
|
|
61
|
-
version: '
|
|
61
|
+
version: '5.0'
|
|
62
62
|
type: :development
|
|
63
63
|
prerelease: false
|
|
64
64
|
version_requirements: !ruby/object:Gem::Requirement
|
|
65
65
|
requirements:
|
|
66
66
|
- - "~>"
|
|
67
67
|
- !ruby/object:Gem::Version
|
|
68
|
-
version: '
|
|
68
|
+
version: '5.0'
|
|
69
69
|
- !ruby/object:Gem::Dependency
|
|
70
|
-
name:
|
|
70
|
+
name: mysql2
|
|
71
71
|
requirement: !ruby/object:Gem::Requirement
|
|
72
72
|
requirements:
|
|
73
|
-
- - "
|
|
73
|
+
- - ">="
|
|
74
74
|
- !ruby/object:Gem::Version
|
|
75
|
-
version: '
|
|
75
|
+
version: '0'
|
|
76
76
|
type: :development
|
|
77
77
|
prerelease: false
|
|
78
78
|
version_requirements: !ruby/object:Gem::Requirement
|
|
79
79
|
requirements:
|
|
80
|
-
- - "
|
|
80
|
+
- - ">="
|
|
81
81
|
- !ruby/object:Gem::Version
|
|
82
|
-
version: '
|
|
82
|
+
version: '0'
|
|
83
83
|
- !ruby/object:Gem::Dependency
|
|
84
|
-
name:
|
|
84
|
+
name: pg
|
|
85
85
|
requirement: !ruby/object:Gem::Requirement
|
|
86
86
|
requirements:
|
|
87
87
|
- - ">="
|
|
@@ -95,21 +95,21 @@ dependencies:
|
|
|
95
95
|
- !ruby/object:Gem::Version
|
|
96
96
|
version: '0'
|
|
97
97
|
- !ruby/object:Gem::Dependency
|
|
98
|
-
name:
|
|
98
|
+
name: rake
|
|
99
99
|
requirement: !ruby/object:Gem::Requirement
|
|
100
100
|
requirements:
|
|
101
|
-
- - "
|
|
101
|
+
- - "~>"
|
|
102
102
|
- !ruby/object:Gem::Version
|
|
103
|
-
version: '0'
|
|
103
|
+
version: '10.0'
|
|
104
104
|
type: :development
|
|
105
105
|
prerelease: false
|
|
106
106
|
version_requirements: !ruby/object:Gem::Requirement
|
|
107
107
|
requirements:
|
|
108
|
-
- - "
|
|
108
|
+
- - "~>"
|
|
109
109
|
- !ruby/object:Gem::Version
|
|
110
|
-
version: '0'
|
|
110
|
+
version: '10.0'
|
|
111
111
|
- !ruby/object:Gem::Dependency
|
|
112
|
-
name:
|
|
112
|
+
name: ransack
|
|
113
113
|
requirement: !ruby/object:Gem::Requirement
|
|
114
114
|
requirements:
|
|
115
115
|
- - ">="
|
|
@@ -123,7 +123,7 @@ dependencies:
|
|
|
123
123
|
- !ruby/object:Gem::Version
|
|
124
124
|
version: '0'
|
|
125
125
|
- !ruby/object:Gem::Dependency
|
|
126
|
-
name:
|
|
126
|
+
name: sqlite3
|
|
127
127
|
requirement: !ruby/object:Gem::Requirement
|
|
128
128
|
requirements:
|
|
129
129
|
- - ">="
|
|
@@ -178,7 +178,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
|
178
178
|
requirements:
|
|
179
179
|
- - ">="
|
|
180
180
|
- !ruby/object:Gem::Version
|
|
181
|
-
version: '2.
|
|
181
|
+
version: '2.3'
|
|
182
182
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
183
183
|
requirements:
|
|
184
184
|
- - ">="
|