agnostic_backend 0.9.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (55) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +1 -0
  3. data/.rspec +1 -0
  4. data/.ruby-gemset +1 -0
  5. data/.ruby-version +1 -0
  6. data/.travis.yml +7 -0
  7. data/CODE_OF_CONDUCT.md +13 -0
  8. data/Gemfile +4 -0
  9. data/Gemfile.lock +52 -0
  10. data/LICENSE.txt +21 -0
  11. data/README.md +345 -0
  12. data/Rakefile +6 -0
  13. data/agnostic_backend.gemspec +34 -0
  14. data/bin/console +14 -0
  15. data/bin/setup +7 -0
  16. data/doc/indexable.md +292 -0
  17. data/doc/queryable.md +0 -0
  18. data/lib/agnostic_backend/cloudsearch/index.rb +99 -0
  19. data/lib/agnostic_backend/cloudsearch/index_field.rb +103 -0
  20. data/lib/agnostic_backend/cloudsearch/indexer.rb +84 -0
  21. data/lib/agnostic_backend/cloudsearch/remote_index_field.rb +32 -0
  22. data/lib/agnostic_backend/index.rb +24 -0
  23. data/lib/agnostic_backend/indexable/config.rb +24 -0
  24. data/lib/agnostic_backend/indexable/content_manager.rb +51 -0
  25. data/lib/agnostic_backend/indexable/field.rb +26 -0
  26. data/lib/agnostic_backend/indexable/field_type.rb +48 -0
  27. data/lib/agnostic_backend/indexable/indexable.rb +125 -0
  28. data/lib/agnostic_backend/indexer.rb +48 -0
  29. data/lib/agnostic_backend/queryable/attribute.rb +22 -0
  30. data/lib/agnostic_backend/queryable/cloudsearch/executor.rb +100 -0
  31. data/lib/agnostic_backend/queryable/cloudsearch/query.rb +29 -0
  32. data/lib/agnostic_backend/queryable/cloudsearch/query_builder.rb +13 -0
  33. data/lib/agnostic_backend/queryable/cloudsearch/result_set.rb +27 -0
  34. data/lib/agnostic_backend/queryable/cloudsearch/visitor.rb +127 -0
  35. data/lib/agnostic_backend/queryable/criteria/binary.rb +47 -0
  36. data/lib/agnostic_backend/queryable/criteria/criterion.rb +13 -0
  37. data/lib/agnostic_backend/queryable/criteria/ternary.rb +36 -0
  38. data/lib/agnostic_backend/queryable/criteria_builder.rb +83 -0
  39. data/lib/agnostic_backend/queryable/executor.rb +43 -0
  40. data/lib/agnostic_backend/queryable/expressions/expression.rb +65 -0
  41. data/lib/agnostic_backend/queryable/operations/n_ary.rb +18 -0
  42. data/lib/agnostic_backend/queryable/operations/operation.rb +13 -0
  43. data/lib/agnostic_backend/queryable/operations/unary.rb +35 -0
  44. data/lib/agnostic_backend/queryable/query.rb +27 -0
  45. data/lib/agnostic_backend/queryable/query_builder.rb +98 -0
  46. data/lib/agnostic_backend/queryable/result_set.rb +42 -0
  47. data/lib/agnostic_backend/queryable/tree_node.rb +48 -0
  48. data/lib/agnostic_backend/queryable/validator.rb +174 -0
  49. data/lib/agnostic_backend/queryable/value.rb +26 -0
  50. data/lib/agnostic_backend/queryable/visitor.rb +124 -0
  51. data/lib/agnostic_backend/rspec/matchers.rb +69 -0
  52. data/lib/agnostic_backend/utilities.rb +207 -0
  53. data/lib/agnostic_backend/version.rb +3 -0
  54. data/lib/agnostic_backend.rb +49 -0
  55. metadata +199 -0
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 0a440a493f9b88844868a71e1489132fd0a10b6e
4
+ data.tar.gz: fd232d6923c079f24c1990e0204ed1adf30e9a84
5
+ SHA512:
6
+ metadata.gz: 099b38168efcd57ef5f79709ac8268c63e021858b99dae704114c073950f2bf7d4087ff6cdca857461e0f1701cf4e8f47ce09a17da297da57cbf251ea3916b52
7
+ data.tar.gz: 2f0bf677241595b6059a54ad61d97f60784700f1d77f5c1cbbbcbbfd9e901fb8988361c6edc0ac52fd07e40b9c79c530f21cb445f117b14e56b91e6eddeeae93
data/.gitignore ADDED
@@ -0,0 +1 @@
1
+ coverage
data/.rspec ADDED
@@ -0,0 +1 @@
1
+ --color
data/.ruby-gemset ADDED
@@ -0,0 +1 @@
1
+ agnostic_backend
data/.ruby-version ADDED
@@ -0,0 +1 @@
1
+ ruby-2.1.5
data/.travis.yml ADDED
@@ -0,0 +1,7 @@
1
+ language: ruby
2
+ rvm:
3
+ - 2.1.5
4
+ script: bundle exec rspec spec
5
+ branches:
6
+ only:
7
+ - master
@@ -0,0 +1,13 @@
1
+ # Contributor Code of Conduct
2
+
3
+ As contributors and maintainers of this project, we pledge to respect all people who contribute through reporting issues, posting feature requests, updating documentation, submitting pull requests or patches, and other activities.
4
+
5
+ We are committed to making participation in this project a harassment-free experience for everyone, regardless of level of experience, gender, gender identity and expression, sexual orientation, disability, personal appearance, body size, race, ethnicity, age, or religion.
6
+
7
+ Examples of unacceptable behavior by participants include the use of sexual language or imagery, derogatory comments or personal attacks, trolling, public or private harassment, insults, or other unprofessional conduct.
8
+
9
+ Project maintainers have the right and responsibility to remove, edit, or reject comments, commits, code, wiki edits, issues, and other contributions that are not aligned to this Code of Conduct. Project maintainers who do not follow the Code of Conduct may be removed from the project team.
10
+
11
+ Instances of abusive, harassing, or otherwise unacceptable behavior may be reported by opening an issue or contacting one or more of the project maintainers.
12
+
13
+ This Code of Conduct is adapted from the [Contributor Covenant](http://contributor-covenant.org), version 1.0.0, available at [http://contributor-covenant.org/version/1/0/0/](http://contributor-covenant.org/version/1/0/0/)
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in agnostic_backend.gemspec
4
+ gemspec
data/Gemfile.lock ADDED
@@ -0,0 +1,52 @@
1
+ PATH
2
+ remote: .
3
+ specs:
4
+ agnostic_backend (0.9.0)
5
+ activesupport (>= 3.2.22)
6
+ aws-sdk (~> 2)
7
+
8
+ GEM
9
+ remote: https://rubygems.org/
10
+ specs:
11
+ activesupport (3.2.22)
12
+ i18n (~> 0.6, >= 0.6.4)
13
+ multi_json (~> 1.0)
14
+ aws-sdk (2.2.14)
15
+ aws-sdk-resources (= 2.2.14)
16
+ aws-sdk-core (2.2.14)
17
+ jmespath (~> 1.0)
18
+ aws-sdk-resources (2.2.14)
19
+ aws-sdk-core (= 2.2.14)
20
+ diff-lcs (1.2.5)
21
+ docile (1.1.5)
22
+ i18n (0.7.0)
23
+ jmespath (1.1.3)
24
+ multi_json (1.11.2)
25
+ rake (10.4.2)
26
+ rspec (2.14.1)
27
+ rspec-core (~> 2.14.0)
28
+ rspec-expectations (~> 2.14.0)
29
+ rspec-mocks (~> 2.14.0)
30
+ rspec-core (2.14.8)
31
+ rspec-expectations (2.14.5)
32
+ diff-lcs (>= 1.1.3, < 2.0)
33
+ rspec-mocks (2.14.6)
34
+ simplecov (0.9.1)
35
+ docile (~> 1.1.0)
36
+ multi_json (~> 1.0)
37
+ simplecov-html (~> 0.8.0)
38
+ simplecov-html (0.8.0)
39
+
40
+ PLATFORMS
41
+ ruby
42
+
43
+ DEPENDENCIES
44
+ agnostic_backend!
45
+ bundler
46
+ rake
47
+ rspec
48
+ simplecov
49
+ simplecov-html
50
+
51
+ BUNDLED WITH
52
+ 1.11.2
data/LICENSE.txt ADDED
@@ -0,0 +1,21 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2015 Iasonas Gavriilidis
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in
13
+ all copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21
+ THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,345 @@
1
+ [![Travis Build Status](https://travis-ci.org/e-travel/agnostic_backend.svg?branch=master)](https://travis-ci.org/e-travel/agnostic_backend)
2
+ [![Code Climate](https://codeclimate.com/github/e-travel/agnostic_backend/badges/gpa.svg)](https://codeclimate.com/github/e-travel/agnostic_backend)
3
+
4
+ # Agnostic Backend
5
+
6
+ `agnostic_backend` is a gem that provides indexing and searching
7
+ capabililities to Ruby objects by supplying two modules: `Indexable`
8
+ and `Queryable`. `Indexable` provides indexing functionality by
9
+ specifying a way to define which attributes of an object should be
10
+ included in a document to be indexed to a remote backend
11
+ store. `Queryable` provides search and retrieval functionality by
12
+ specifying a generic query language that seamlessly maps to specific
13
+ backend languages.
14
+
15
+ In addition to these two modules, `agnostic_backend` supplies
16
+ additional classes (`Indexer` and `Index`) to support the
17
+ configuration and functionality of remote backends (such as
18
+ elasticsearch, AWS Cloudsearch etc.).
19
+
20
+ Although the motivation and use case for the gem relates to
21
+ `ActiveRecord` models, no assumption is made as to the classes to
22
+ which `Indexable` and `Queryable` can be included. The objective is to
23
+ maximize the flexibility of clients with respect to the use cases they
24
+ need to address.
25
+
26
+ ## Installation
27
+
28
+ Add this line to your application's Gemfile:
29
+
30
+ ```ruby
31
+ gem 'agnostic_backend'
32
+ ```
33
+
34
+ And then execute:
35
+
36
+ $ bundle install
37
+
38
+ Or install it yourself as:
39
+
40
+ $ gem install agnostic_backend
41
+
42
+ ## Requirements
43
+
44
+ `agnostic_backend` requires a ruby version `>=2.1.0` due to the use of
45
+ mandatory keyword arguments in method definitions. Check the `Gemfile`
46
+ for more info on dependencies.
47
+
48
+ ## Usage
49
+
50
+ For the purposes of this document, we will focus on `ActiveRecord`
51
+ examples. Let's assume we have two AR models, `Task` and `Workflow`,
52
+ connected using an one-to-many relationship (i.e. a `Workflow` has
53
+ many `Task`s) as follows:
54
+
55
+ ```ruby
56
+ class Task < ActiveRecord::Base
57
+ include AgnosticBackend::Indexable
58
+
59
+ belongs_to :workflow, class_name: 'Workflow'
60
+ end
61
+
62
+ class Workflow < ActiveRecord::Base
63
+ include AgnosticBackend::Indexable
64
+
65
+ has_many :tasks, class_name: 'Task'
66
+ end
67
+ ```
68
+
69
+ Let's assume also that we have a remote store to which we would like
70
+ to index documents related to `Task`s and from which we would like to
71
+ retrieve these documents by performing queries based on the document
72
+ fields.
73
+
74
+ ### Indexable
75
+
76
+ In order to index individual tasks, we need to specify three things:
77
+
78
+ - what should the document contain (we'll use
79
+ `Indexable::ClassMethods#define_index_fields`)
80
+ - who should be notified when the object needs to be indexed (we'll
81
+ use `Indexable::ClassMethods#define_index_notifier`)
82
+ - when should the above notification(s) occur (we'll use `ActiveRecord`'s
83
+ `after_commit` callback)
84
+
85
+ Let's see that in action:
86
+
87
+ ```ruby
88
+ class Task < ActiveRecord::Base
89
+ # let's make our class Indexable
90
+ include AgnosticBackend::Indexable
91
+
92
+ belongs_to :workflow, class_name: 'Workflow'
93
+
94
+ # define what should the document contain
95
+ define_index_fields do
96
+ integer :id
97
+ date :last_assigned_at, value: :assigned_at, label: 'Last Assigned At'
98
+ string :type, value: proc { task_category.name }, label: 'Task Type'
99
+ struct :workflow, from: Workflow
100
+ end
101
+
102
+ # define who should be notified when this object needs to be indexed
103
+ define_index_notifier { self }
104
+
105
+ # define when should the above notifications occur
106
+ # we'll use Indexable's trigger_index_notification instance method
107
+ after_commit :trigger_index_notification
108
+ end
109
+
110
+ class Workflow < ActiveRecord::Base
111
+ # let's make our class Indexable
112
+ include AgnosticBackend::Indexable
113
+
114
+ has_many :tasks, class_name: 'Task'
115
+
116
+ # define what should the document contain and who is the owner
117
+ # Note that the contents are part of the document
118
+ # created by a `Task` instance
119
+ define_index_fields(owner: Task) do
120
+ integer :id
121
+ date :creation_date, value: :created_at, label: 'Creation Date'
122
+ end
123
+
124
+ # define who should be notified when this object needs to be indexed
125
+ define_index_notifier(target: Task) { tasks }
126
+
127
+ # define when should the above notifications occur
128
+ # we'll use Indexable's trigger_index_notification instance method
129
+ after_commit :trigger_index_notification
130
+ end
131
+ ```
132
+
133
+ The above definitions achieve the following things:
134
+
135
+ - when a task is created/updated, a document is generated and sent to
136
+ the remote backend for indexing
137
+ - this document includes a section `workflow` that contains the
138
+ associated `Worflow`'s document (see `struct` entry in `Task`'s
139
+ `define_index_fields`)
140
+ - when a workflow is created/updated, all its associated tasks are
141
+ notified in order to index themselves (see `define_index_notifiers`
142
+ in both classes)
143
+
144
+ Now that we've defined our models and configured their indexing, let's
145
+ play a bit more:
146
+
147
+ ```ruby
148
+ # First, let's configure our remote backend
149
+ # we'll use AWS Cloudsearch as an example
150
+ AgnosticBackend::Indexable::Config.configure_index(
151
+ Task,
152
+ AgnosticBackend::Cloudsearch::Index,
153
+ region: "the_region",
154
+ domain_name: "the_domain_name",
155
+ document_endpoint: "the_document_endpoint",
156
+ search_endpoint: "the_search_endpoint",
157
+ access_key_id: "the_access_key_id",
158
+ secret_access_key: "the_secret_access_key"
159
+ )
160
+
161
+ # Let's create a Workflow and persist it
162
+ > workflow = Workflow.create(...)
163
+ # Let's add a couple of tasks
164
+ > 2.times { workflow << Task.create(...) }
165
+
166
+ # at this point, our two tasks have already been indexed
167
+ # due to the after_commit callbacks
168
+
169
+ # let's grab the first task
170
+ > task = workflow.tasks.first
171
+
172
+ # let's generate and inspect a document for this task
173
+ > task.generate_document
174
+ {:id => 10,
175
+ :last_assigned_at => '2015-12-30T12:34:55',
176
+ :type => 'SomeTask',
177
+ # includes the workflow contents
178
+ # through the struct relationship in Task's define_index_fields
179
+ :workflow => {
180
+ :id => 4,
181
+ :creation_date => '2015-12-30T12:34:53'
182
+ }
183
+ }
184
+
185
+ # we can index it again (synchronously)
186
+ > task.put_to_index
187
+
188
+ # the following achieves the same thing by default
189
+ # but Indexable's method can be overriden in order
190
+ # to implement custom functionality (e.g. asynchronous indexing)
191
+ > task.index_object
192
+
193
+ # hey, we can get the document schema too!
194
+ > Task.schema
195
+ {:id => :integer,
196
+ :last_assigned_at => :date,
197
+ :type => :string,
198
+ :workflow => {
199
+ :id => :integer,
200
+ :creation_date => :date
201
+ }
202
+ }
203
+
204
+ # and any custom property that we supplied in define_index_fields
205
+ # in this case :label
206
+ > Task.schema {|field_type| field_type.get_option(:label)}
207
+ {:id => nil,
208
+ :last_assigned_at => "Last Assigned At",
209
+ :type => "Task Type",
210
+ :workflow => {
211
+ :id => nil,
212
+ :creation_date => "Creation Date"
213
+ }
214
+ }
215
+ ```
216
+
217
+ More information about the use of `Indexable` can be found in
218
+ [this document](src/master/doc/indexable.md).
219
+
220
+ ### Queryable
221
+
222
+ Queries are built and executed against a remote backend. Assuming the
223
+ same `Task` class as before:
224
+
225
+ ```ruby
226
+ > query_builder = Task.query_builder
227
+ > criteria_builder = query_builder.criteria_builder
228
+
229
+ # Let's build the query:
230
+ # last_assigned_at < '2015-10-10' OR type = 'FirstTask'
231
+ > criteria = criteria_builder.or(
232
+ criteria_builder.lt('last_assigned_at', '2015-10-10T00:00:00Z'),
233
+ criteria_builder.eq('type', 'FirstTask'))
234
+
235
+ # Setup the where clause
236
+ > query_builder.where(criteria)
237
+
238
+ # Let's put some more constraints
239
+ > query_builder.order('id', :asc)
240
+ > query_builder.limit(10)
241
+
242
+ # compile the query
243
+ > query = query_builder.build
244
+
245
+ # and run it!
246
+ results = query.execute
247
+
248
+ # results is a Queryable::ResultSet instance that gives
249
+ # access to the backend results; these follow the document's schema
250
+ > results.map {|result| result['workflow']['creation_date'] }
251
+ ```
252
+
253
+ For more information about `Queryable` check out
254
+ [this document](src/master/doc/queryable.md).
255
+
256
+
257
+ ### Backends
258
+
259
+ Currently, the gem includes one concrete backend implementation that
260
+ talks to [AWS Cloudsearch](https://aws.amazon.com/cloudsearch/). New
261
+ backends can be implemented by subclassing `AgnosticBackend::Index`
262
+ and `AgnosticBackend::Indexer` (more on that later).
263
+
264
+ #### The Index
265
+
266
+ `AgnosticBackend::Index` is responsible for representing a particular
267
+ repo (aka index/table) in a remote backend for a specific model. This
268
+ implies that `Index` is responsible for any communications that occur
269
+ between the client and the backend, as well as any
270
+ initialization/configuration (credentials etc.) tasks. `Index` is also
271
+ the context in which a query is built and executed.
272
+
273
+ `AgnosticBackend::Indexable` exposes the `Config` class in order to
274
+ facilitate the initialization/configuration of an index at
275
+ runtime. For example, the initialization/configuration of the
276
+ Cloudsearch index that corresponds to the indexing of `Task`s can be
277
+ achieved by:
278
+
279
+ ```ruby
280
+ AgnosticBackend::Indexable::Config.configure_index(
281
+ Task, # the class whose instances are indexed
282
+ AgnosticBackend::Cloudsearch::Index, # the concrete Index class
283
+ # and various parameters related to the specific backend (Cloudsearch)
284
+ region: 'the_region',
285
+ domain_name: 'the_domain_name',
286
+ document_endpoint: 'the_document_endpoint',
287
+ search_endpoint: 'the_search_endpoint',
288
+ access_key_id: 'the_access_key_id',
289
+ secret_access_key: 'the_secret_access_key'
290
+ )
291
+ ```
292
+
293
+ The remote index's name should follow the convention used by
294
+ `Indexable` (see `Indexable::ClassMethods#index_name`) according to
295
+ which the remote index name is automatically determined given the
296
+ including class's name convention.
297
+
298
+ #### The Indexer
299
+
300
+ `AgnosticBackend::Indexer` is responsible for document handling,
301
+ i.e. publishing documents to and deleting documents from the remote
302
+ backend. These processes are broken down into discrete steps,
303
+ including pre-processing, transformations, and conversions to other
304
+ formats (xml, json). This is reflected in the default implementation
305
+ of `Indexer#put` (that sends a document to the remote backend) which
306
+ actually does (among other things):
307
+
308
+ ```ruby
309
+ publish(transform(prepare(document)))
310
+ ```
311
+
312
+ For example, a remote backend may not support the indexing of
313
+ documents with `nil` values. As part of the pre-processing step
314
+ (`#prepare`), the implementor of a specific backend might choose to
315
+ exclude `nil` values from the document before forwarding it down the
316
+ chain.
317
+
318
+ ## Development
319
+
320
+ After checking out the repo, run `bundle exec bin/setup` or `bundle
321
+ install` to install dependencies. Then, run `bundle exec rake spec` or
322
+ `bundle exec rspec spec` to run the tests. This will also generate a
323
+ test coverage report in `coverage/index.html` for inspection. You can
324
+ also run `bin/console` for an interactive prompt that will allow you
325
+ to experiment.
326
+
327
+ To install this gem onto your local machine, run `bundle exec rake
328
+ install`. To release a new version, update the version number in
329
+ `version.rb`, and then run `bundle exec rake release`, which will
330
+ create a git tag for the version, push git commits and tags, and push
331
+ the `.gem` file to [rubygems.org](https://rubygems.org).
332
+
333
+ ## Contributing
334
+
335
+ Bug reports and pull requests are welcome on GitHub at
336
+ https://github.com/e-travel/agnostic_backend. This project is intended
337
+ to be a safe, welcoming space for collaboration, and contributors are
338
+ expected to adhere to the
339
+ [Contributor Covenant](http://contributor-covenant.org) code of conduct.
340
+
341
+
342
+ ## License
343
+
344
+ The gem is available as open source under the terms of the
345
+ [MIT License](http://opensource.org/licenses/MIT).
data/Rakefile ADDED
@@ -0,0 +1,6 @@
1
+ require "bundler/gem_tasks"
2
+ require "rspec/core/rake_task"
3
+
4
+ RSpec::Core::RakeTask.new(:spec)
5
+
6
+ task :default => :spec
@@ -0,0 +1,34 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'agnostic_backend/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = "agnostic_backend"
8
+ spec.version = AgnosticBackend::VERSION
9
+ spec.authors = ["Iasonas Gavriilidis",
10
+ "Laertis Pappas",
11
+ "Kyriakos Kentzoglanakis"]
12
+ spec.email = ["i.gavriilidis@pamediakopes.gr",
13
+ "l.pappas@pamediakopes.gr",
14
+ "k.kentzoglanakis@pamediakopes.gr"]
15
+
16
+ spec.summary = %q{A gem to index/query ruby objects to/from remote backends}
17
+ spec.homepage = "https://github.com/e-travel/agnostic_backend"
18
+ spec.license = "MIT"
19
+
20
+ spec.files = `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
21
+ spec.bindir = "exe"
22
+ spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
23
+ spec.require_paths = ["lib"]
24
+ spec.required_ruby_version = '>= 2.1.0' # for mandatory method keyword arguments
25
+
26
+ spec.add_runtime_dependency "activesupport", ">= 3.2.22"
27
+ spec.add_runtime_dependency "aws-sdk", "~> 2"
28
+
29
+ spec.add_development_dependency "bundler"
30
+ spec.add_development_dependency "rake"
31
+ spec.add_development_dependency "rspec"
32
+ spec.add_development_dependency "simplecov"
33
+ spec.add_development_dependency "simplecov-html"
34
+ end
data/bin/console ADDED
@@ -0,0 +1,14 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require "bundler/setup"
4
+ require "agnostic_backend"
5
+
6
+ # You can add fixtures and/or initialization code here to make experimenting
7
+ # with your gem easier. You can also use a different console, if you like.
8
+
9
+ # (If you use this, don't forget to add pry to your Gemfile!)
10
+ # require "pry"
11
+ # Pry.start
12
+
13
+ require "irb"
14
+ IRB.start
data/bin/setup ADDED
@@ -0,0 +1,7 @@
1
+ #!/bin/bash
2
+ set -euo pipefail
3
+ IFS=$'\n\t'
4
+
5
+ bundle install
6
+
7
+ # Do any other automated setup that you need to do here