chewy 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/.gitignore +1 -1
- data/.travis.yml +5 -1
- data/CHANGELOG.md +21 -1
- data/README.md +12 -60
- data/chewy.gemspec +1 -1
- data/gemfiles/Gemfile.rails-3.2 +14 -0
- data/gemfiles/Gemfile.rails-4.0 +14 -0
- data/lib/chewy.rb +5 -0
- data/lib/chewy/fields/base.rb +2 -2
- data/lib/chewy/fields/root.rb +33 -0
- data/lib/chewy/index/actions.rb +6 -1
- data/lib/chewy/index/search.rb +1 -1
- data/lib/chewy/query.rb +30 -2
- data/lib/chewy/query/criteria.rb +10 -3
- data/lib/chewy/query/nodes/range.rb +2 -2
- data/lib/chewy/query/nodes/script.rb +1 -1
- data/lib/chewy/rspec/update_index.rb +95 -4
- data/lib/chewy/type/adapter/active_record.rb +16 -2
- data/lib/chewy/type/import.rb +6 -1
- data/lib/chewy/type/mapping.rb +129 -6
- data/lib/chewy/type/observe.rb +4 -2
- data/lib/chewy/version.rb +1 -1
- data/spec/chewy/fields/root_spec.rb +38 -0
- data/spec/chewy/index/actions_spec.rb +2 -2
- data/spec/chewy/query/criteria_spec.rb +11 -0
- data/spec/chewy/query/loading_spec.rb +2 -2
- data/spec/chewy/query/pagination_spec.rb +3 -2
- data/spec/chewy/query_spec.rb +72 -2
- data/spec/chewy/rspec/update_index_spec.rb +26 -0
- data/spec/chewy/type/adapter/active_record_spec.rb +86 -26
- data/spec/chewy/type/import_spec.rb +4 -4
- data/spec/spec_helper.rb +8 -1
- metadata +7 -5
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 6bfe79b7a76d86426e6b1f67389d386e85ee33bc
|
4
|
+
data.tar.gz: 65102eba1137183f68dc167ef1c91f77abae9758
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 6b366d1a609fdd330e46e5f4937187e3fdbc697c65869927deb578d7bb58ea170c3e4fcb6bf3a178fba0a29fe8c5c560e3229314da70b2b180ee19eed9084b9c
|
7
|
+
data.tar.gz: 7e76c1cc833e2884b1c48d3c1dbb197a8bae08a90b099ea87aea5ffb36249a51f08ca37bb1f575f3b6786551c3897b9cb4e443764cc46bd86904e096ad4f3126
|
data/.gitignore
CHANGED
data/.travis.yml
CHANGED
@@ -4,7 +4,11 @@ rvm:
|
|
4
4
|
- 2.0.0
|
5
5
|
- 2.1.0
|
6
6
|
# - rbx
|
7
|
+
gemfile:
|
8
|
+
- Gemfile
|
9
|
+
- gemfiles/Gemfile.rails-3.2
|
10
|
+
- gemfiles/Gemfile.rails-4.0
|
7
11
|
before_install:
|
8
12
|
- curl -# https://download.elasticsearch.org/elasticsearch/elasticsearch/elasticsearch-1.0.1.tar.gz | tar xz -C /tmp
|
9
13
|
before_script:
|
10
|
-
- TEST_CLUSTER_COMMAND="/tmp/elasticsearch-1.0.1/bin/elasticsearch" rake elasticsearch:start
|
14
|
+
- TEST_CLUSTER_COMMAND="/tmp/elasticsearch-1.0.1/bin/elasticsearch" rake elasticsearch:start
|
data/CHANGELOG.md
CHANGED
@@ -1,5 +1,23 @@
|
|
1
1
|
# master
|
2
2
|
|
3
|
+
# Version 0.4.0
|
4
|
+
|
5
|
+
* Changed `update_index` matcher behavior. Now it compare array attributes position-independantly.
|
6
|
+
|
7
|
+
* Search aggregations API support (@arion).
|
8
|
+
|
9
|
+
* Chewy::Query#facets called without params performs the request and returns facets.
|
10
|
+
|
11
|
+
* Added `Type.template` dsl method for root objects dynamic templates definition. See [mapping.rb](lib/chewy/type/mapping.rb) for more details.
|
12
|
+
|
13
|
+
* ActiveRecord adapter custom `primary_key` support (@matthee).
|
14
|
+
|
15
|
+
* Urgent update now clears association cache in ActiveRecord to ensure latest changes are imported.
|
16
|
+
|
17
|
+
* `import` now creates index before performing.
|
18
|
+
|
19
|
+
* `Chewy.configuration[:wait_for_status]` option. Can be set to `red`, `yellow` or `green`. If set - chewy will wait for cluster status before creating, deleting index and import. Useful for specs.
|
20
|
+
|
3
21
|
# Version 0.3.0
|
4
22
|
|
5
23
|
* Added `Chewy.configuration[:index]` config to setup common indexes options.
|
@@ -16,7 +34,9 @@
|
|
16
34
|
|
17
35
|
# Version 0.2.2
|
18
36
|
|
19
|
-
*
|
37
|
+
* Support for `none` scope (@undr).
|
38
|
+
|
39
|
+
* Auto-resolved analyzers and analyzers repository (@webgago):
|
20
40
|
|
21
41
|
```ruby
|
22
42
|
# Setting up analyzers repository:
|
data/README.md
CHANGED
@@ -7,9 +7,11 @@ Chewy is ODM and wrapper for official elasticsearch client (https://github.com/e
|
|
7
7
|
|
8
8
|
## Why chewy?
|
9
9
|
|
10
|
-
* Index classes are independant from ORM/ODM models.
|
11
10
|
|
12
|
-
|
11
|
+
|
12
|
+
* Multi-model indexes.
|
13
|
+
|
14
|
+
Index classes are independant from ORM/ODM models. Now implementing, e.g. cross-model autocomplete is much easier. You can just define index and work with it in object-oriented style. You can define several types for index - one per indexed model.
|
13
15
|
|
14
16
|
* Every index is observable by all the related models.
|
15
17
|
|
@@ -127,7 +129,9 @@ Chewy.logger = Logger.new
|
|
127
129
|
}
|
128
130
|
|
129
131
|
define_type User.active.includes(:country, :badges, :projects) do
|
130
|
-
root
|
132
|
+
root date_detection: false do
|
133
|
+
template 'about_translations.*', type: 'string', analyzer: 'stantard'
|
134
|
+
|
131
135
|
field :first_name, :last_name
|
132
136
|
field :email, analyzer: 'email'
|
133
137
|
field :country, value: ->(user) { user.country.name }
|
@@ -148,6 +152,8 @@ Chewy.logger = Logger.new
|
|
148
152
|
Index settings - http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/indices-update-settings.html
|
149
153
|
Root object settings - http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/mapping-root-object-type.html
|
150
154
|
|
155
|
+
See [mapping.rb](lib/chewy/type/mapping.rb) for more details.
|
156
|
+
|
151
157
|
5. Add model observing code
|
152
158
|
|
153
159
|
```ruby
|
@@ -217,10 +223,10 @@ UsersIndex.import user: User.where('rating > 100') # import only active users to
|
|
217
223
|
UsersIndex.reset! # purges index and imports default data for all types
|
218
224
|
```
|
219
225
|
|
220
|
-
See [actions.rb](lib/chewy/index/actions.rb) for more details.
|
221
|
-
|
222
226
|
Also if passed user is #destroyed? or specified id is not existing in the database, import will perform `delete` index for this it
|
223
227
|
|
228
|
+
See [actions.rb](lib/chewy/index/actions.rb) for more details.
|
229
|
+
|
224
230
|
### Observing strategies
|
225
231
|
|
226
232
|
There are 3 strategies for index updating: do not update index at all, update right after save and cummulative update. The first is by default.
|
@@ -678,69 +684,15 @@ rake chewy:update[users] # updates UsersIndex
|
|
678
684
|
### Rspec integration
|
679
685
|
|
680
686
|
Just add `require 'chewy/rspec'` to your spec_helper.rb and you will get additional features:
|
681
|
-
|
682
|
-
#### `update_index` matcher
|
683
|
-
|
684
|
-
```ruby
|
685
|
-
# just update index expectation. Used type class as argument.
|
686
|
-
specify { expect { user.save! }.to update_index(UsersIndex.user) }
|
687
|
-
# expect do not update target index. Type for `update_index` might be specified via string also
|
688
|
-
specify { expect { user.name = 'Duke' }.not_to update_index('users#user') }
|
689
|
-
# expecting update specified objects
|
690
|
-
specify { expect { user.save! }.to update_index(UsersIndex.user).and_reindex(user) }
|
691
|
-
# you can specify even id
|
692
|
-
specify { expect { user.save! }.to update_index(UsersIndex.user).and_reindex(42) }
|
693
|
-
# expected multiple objects to be reindexed
|
694
|
-
specify { expect { [user1, user2].map(&:save!) }
|
695
|
-
.to update_index(UsersIndex.user).and_reindex(user1, user2) }
|
696
|
-
specify { expect { [user1, user2].map(&:save!) }
|
697
|
-
.to update_index(UsersIndex.user).and_reindex(user1).and_reindex(user2) }
|
698
|
-
# expect object to be reindexed exact twice
|
699
|
-
specify { expect { 2.times { user.save! } }
|
700
|
-
.to update_index(UsersIndex.user).and_reindex(user, times: 2) }
|
701
|
-
# expect object in index to be updated with specified fields
|
702
|
-
specify { expect { user.update_attributes!(name: 'Duke') }
|
703
|
-
.to update_index(UsersIndex.user).and_reindex(user, with: {name: 'Duke'}) }
|
704
|
-
# combination of previous two
|
705
|
-
specify { expect { 2.times { user.update_attributes!(name: 'Duke') } }
|
706
|
-
.to update_index(UsersIndex.user).and_reindex(user, times: 2, with: {name: 'Duke'}) }
|
707
|
-
# for every object
|
708
|
-
specify { expect { 2.times { [user1, user2].map { |u| u.update_attributes!(name: 'Duke') } } }
|
709
|
-
.to update_index(UsersIndex.user).and_reindex(user1, user2, times: 2, with: {name: 'Duke'}) }
|
710
|
-
# for every object splitted
|
711
|
-
specify { expect { 2.times { [user1, user2].map { |u| u.update_attributes!(name: "Duke#{u.id}") } } }
|
712
|
-
.to update_index(UsersIndex.user)
|
713
|
-
.and_reindex(user1, with: {name: 'Duke42'}) }
|
714
|
-
.and_reindex(user2, times: 1, with: {name: 'Duke43'}) }
|
715
|
-
# object deletion same abilities as `and_reindex`, except `:with` option
|
716
|
-
specify { expect { user.destroy! }.to update_index(UsersIndex.user).and_delete(user) }
|
717
|
-
# double deletion, whatever it means
|
718
|
-
specify { expect { 2.times { user.destroy! } }.to update_index(UsersIndex.user).and_delete(user, times: 2) }
|
719
|
-
# alltogether
|
720
|
-
specify { expect { user1.destroy!; user2.save! } }
|
721
|
-
.to update_index(UsersIndex.user).and_reindex(user2).and_delete(user1)
|
722
|
-
```
|
723
|
-
|
724
|
-
```ruby
|
725
|
-
# strictly specifing updated and deleted records
|
726
|
-
specify { expect { [user1, user2].map(&:save!) }
|
727
|
-
.to update_index(UsersIndex.user).and_reindex(user1, user2).only }
|
728
|
-
specify { expect { [user1, user2].map(&:destroy!) }
|
729
|
-
.to update_index(UsersIndex.user).and_delete(user1, user2).only }
|
730
|
-
# this will fail
|
731
|
-
specify { expect { [user1, user2].map(&:save!) }
|
732
|
-
.to update_index(UsersIndex.user).and_reindex(user1).only }
|
733
|
-
```
|
687
|
+
See [update_index.rb](lib/chewy/rspec/update_index.rb) for more details.
|
734
688
|
|
735
689
|
## TODO a.k.a coming soon:
|
736
690
|
|
737
|
-
* Dynamic templates additional DSL
|
738
691
|
* Typecasting support
|
739
692
|
* Advanced (simplyfied) query DSL: `UsersIndex.query { email == 'my@gmail.com' }` will produce term query
|
740
693
|
* update_all support
|
741
694
|
* Other than ActiveRecord ORMs support (Mongoid)
|
742
695
|
* Maybe, closer ORM/ODM integration, creating index classes implicitly
|
743
|
-
* Better facets support
|
744
696
|
|
745
697
|
## Contributing
|
746
698
|
|
data/chewy.gemspec
CHANGED
@@ -0,0 +1,14 @@
|
|
1
|
+
source 'https://rubygems.org'
|
2
|
+
|
3
|
+
gemspec path: '../'
|
4
|
+
|
5
|
+
gem 'activerecord', '~> 3.2.0'
|
6
|
+
gem 'activesupport', '~> 3.2.0'
|
7
|
+
|
8
|
+
group :test do
|
9
|
+
gem 'guard'
|
10
|
+
gem 'guard-rspec'
|
11
|
+
gem 'rb-inotify', require: false
|
12
|
+
gem 'rb-fsevent', require: false
|
13
|
+
gem 'rb-fchange', require: false
|
14
|
+
end
|
@@ -0,0 +1,14 @@
|
|
1
|
+
source 'https://rubygems.org'
|
2
|
+
|
3
|
+
gemspec path: '../'
|
4
|
+
|
5
|
+
gem 'activerecord', '~> 4.0.0'
|
6
|
+
gem 'activesupport', '~> 4.0.0'
|
7
|
+
|
8
|
+
group :test do
|
9
|
+
gem 'guard'
|
10
|
+
gem 'guard-rspec'
|
11
|
+
gem 'rb-inotify', require: false
|
12
|
+
gem 'rb-fsevent', require: false
|
13
|
+
gem 'rb-fchange', require: false
|
14
|
+
end
|
data/lib/chewy.rb
CHANGED
@@ -1,6 +1,7 @@
|
|
1
1
|
require 'active_support/concern'
|
2
2
|
require 'active_support/core_ext'
|
3
3
|
require 'active_support/json'
|
4
|
+
require 'i18n/core_ext/hash'
|
4
5
|
require 'singleton'
|
5
6
|
|
6
7
|
require 'elasticsearch'
|
@@ -38,6 +39,10 @@ module Chewy
|
|
38
39
|
end
|
39
40
|
end
|
40
41
|
|
42
|
+
def self.wait_for_status
|
43
|
+
client.cluster.health wait_for_status: Chewy.configuration[:wait_for_status] if Chewy.configuration[:wait_for_status].present?
|
44
|
+
end
|
45
|
+
|
41
46
|
def self.config
|
42
47
|
Chewy::Config.instance
|
43
48
|
end
|
data/lib/chewy/fields/base.rb
CHANGED
@@ -40,10 +40,10 @@ module Chewy
|
|
40
40
|
subfields = nested.any? ? {
|
41
41
|
(multi_field? ? :fields : :properties) => nested.values.map(&:mappings_hash).inject(:merge)
|
42
42
|
} : {}
|
43
|
-
{name => options.merge(subfields)}
|
43
|
+
{name => options.deep_symbolize_keys.merge(subfields)}
|
44
44
|
end
|
45
45
|
|
46
|
-
|
46
|
+
private
|
47
47
|
|
48
48
|
def nested_compose(value)
|
49
49
|
nested.values.map { |field| field.compose(value) }.inject(:merge)
|
data/lib/chewy/fields/root.rb
CHANGED
@@ -1,9 +1,42 @@
|
|
1
1
|
module Chewy
|
2
2
|
module Fields
|
3
3
|
class Root < Chewy::Fields::Base
|
4
|
+
attr_reader :dynamic_templates
|
5
|
+
|
4
6
|
def initialize(name, options = {})
|
5
7
|
options.reverse_merge!(value: ->(_){_})
|
6
8
|
super(name, options)
|
9
|
+
@dynamic_templates = []
|
10
|
+
end
|
11
|
+
|
12
|
+
def mappings_hash
|
13
|
+
mappings = super
|
14
|
+
if dynamic_templates.any?
|
15
|
+
mappings[name][:dynamic_templates] ||= []
|
16
|
+
mappings[name][:dynamic_templates].concat dynamic_templates
|
17
|
+
end
|
18
|
+
mappings
|
19
|
+
end
|
20
|
+
|
21
|
+
def dynamic_template *args
|
22
|
+
options = args.extract_options!.deep_symbolize_keys
|
23
|
+
if args.first
|
24
|
+
template_name = :"template_#{dynamic_templates.count.next}"
|
25
|
+
template = {template_name => {mapping: options}}
|
26
|
+
|
27
|
+
template[template_name][:match_mapping_type] = args.second.to_s if args.second.present?
|
28
|
+
|
29
|
+
regexp = args.first.is_a?(Regexp)
|
30
|
+
template[template_name][:match_pattern] = 'regexp' if regexp
|
31
|
+
|
32
|
+
match = regexp ? args.first.source : args.first
|
33
|
+
path = match.include?(regexp ? '\.' : '.')
|
34
|
+
|
35
|
+
template[template_name][path ? :path_match : :match] = match
|
36
|
+
@dynamic_templates.push(template)
|
37
|
+
else
|
38
|
+
@dynamic_templates.push(options)
|
39
|
+
end
|
7
40
|
end
|
8
41
|
end
|
9
42
|
end
|
data/lib/chewy/index/actions.rb
CHANGED
@@ -55,6 +55,9 @@ module Chewy
|
|
55
55
|
def create! *args
|
56
56
|
options = args.extract_options!.reverse_merge!(alias: true)
|
57
57
|
name = build_index_name(suffix: args.first)
|
58
|
+
|
59
|
+
Chewy.wait_for_status
|
60
|
+
|
58
61
|
result = client.indices.create(index: name, body: index_params)
|
59
62
|
result &&= client.indices.put_alias(index: name, name: index_name) if options[:alias] && name != index_name
|
60
63
|
result
|
@@ -84,6 +87,8 @@ module Chewy
|
|
84
87
|
# UsersIndex.delete '01-2014' # deletes `users_01-2014` index
|
85
88
|
#
|
86
89
|
def delete! suffix = nil
|
90
|
+
Chewy.wait_for_status
|
91
|
+
|
87
92
|
client.indices.delete index: build_index_name(suffix: suffix)
|
88
93
|
end
|
89
94
|
|
@@ -126,7 +131,7 @@ module Chewy
|
|
126
131
|
[:import, :import!].each do |method|
|
127
132
|
class_eval <<-METHOD, __FILE__, __LINE__ + 1
|
128
133
|
def #{method} options = {}
|
129
|
-
objects = options.
|
134
|
+
objects = options.reject { |k, v| !type_names.map(&:to_sym).include?(k) }
|
130
135
|
types.map do |type|
|
131
136
|
args = [objects[type.type_name.to_sym], options.dup].reject(&:blank?)
|
132
137
|
type.#{method} *args
|
data/lib/chewy/index/search.rb
CHANGED
@@ -4,7 +4,7 @@ module Chewy
|
|
4
4
|
extend ActiveSupport::Concern
|
5
5
|
|
6
6
|
included do
|
7
|
-
singleton_class.delegate :explain, :limit, :offset, :facets, :query,
|
7
|
+
singleton_class.delegate :explain, :limit, :offset, :facets, :aggregations, :query,
|
8
8
|
:filter, :order, :reorder, :only, :types, :none, to: :all
|
9
9
|
end
|
10
10
|
|
data/lib/chewy/query.rb
CHANGED
@@ -242,9 +242,37 @@ module Chewy
|
|
242
242
|
# facets: {tags: {terms: {field: 'tags'}}, ages: {terms: {field: 'age'}}}
|
243
243
|
# }}
|
244
244
|
#
|
245
|
-
|
246
|
-
|
245
|
+
# If called parameterless - returns result facets from ES performing request.
|
246
|
+
# Returns empty hash if no facets was requested or resulted.
|
247
|
+
#
|
248
|
+
def facets params = nil
|
249
|
+
if params
|
250
|
+
chain { criteria.update_facets params }
|
251
|
+
else
|
252
|
+
_response['facets'] || {}
|
253
|
+
end
|
254
|
+
end
|
255
|
+
|
256
|
+
# Sets elasticsearch <tt>aggregations</tt> search request param
|
257
|
+
#
|
258
|
+
# UsersIndex.filter{ name == 'Johny' }.aggregations(category_id: {terms: {field: 'category_ids'}})
|
259
|
+
# # => {body: {
|
260
|
+
# query: {...},
|
261
|
+
# aggregations: {
|
262
|
+
# terms: {
|
263
|
+
# field: 'category_ids'
|
264
|
+
# }
|
265
|
+
# }
|
266
|
+
# }}
|
267
|
+
#
|
268
|
+
def aggregations params = nil
|
269
|
+
if params
|
270
|
+
chain { criteria.update_aggregations params }
|
271
|
+
else
|
272
|
+
_response['aggregations'] || {}
|
273
|
+
end
|
247
274
|
end
|
275
|
+
alias :aggs :aggregations
|
248
276
|
|
249
277
|
# Marks the criteria as having zero records. This scope always returns empty array
|
250
278
|
# without touching the elasticsearch server.
|
data/lib/chewy/query/criteria.rb
CHANGED
@@ -4,7 +4,9 @@ module Chewy
|
|
4
4
|
class Query
|
5
5
|
class Criteria
|
6
6
|
include Compose
|
7
|
-
|
7
|
+
ARRAY_STORAGES = [:queries, :filters, :sort, :fields, :types]
|
8
|
+
HASH_STORAGES = [:options, :facets, :aggregations]
|
9
|
+
STORAGES = ARRAY_STORAGES + HASH_STORAGES
|
8
10
|
|
9
11
|
def initialize options = {}
|
10
12
|
@options = options.merge(query_mode: Chewy.query_mode, filter_mode: Chewy.filter_mode)
|
@@ -14,7 +16,7 @@ module Chewy
|
|
14
16
|
other.is_a?(self.class) && storages == other.storages
|
15
17
|
end
|
16
18
|
|
17
|
-
{
|
19
|
+
{ ARRAY_STORAGES => '[]', HASH_STORAGES => '{}' }.each do |storages, default|
|
18
20
|
storages.each do |storage|
|
19
21
|
class_eval <<-METHODS, __FILE__, __LINE__ + 1
|
20
22
|
def #{storage}
|
@@ -42,6 +44,10 @@ module Chewy
|
|
42
44
|
facets.merge!(modifer)
|
43
45
|
end
|
44
46
|
|
47
|
+
def update_aggregations(modifer)
|
48
|
+
aggregations.merge!(modifer)
|
49
|
+
end
|
50
|
+
|
45
51
|
def update_queries(modifer)
|
46
52
|
@queries = queries + Array.wrap(modifer).reject(&:blank?)
|
47
53
|
end
|
@@ -81,6 +87,7 @@ module Chewy
|
|
81
87
|
def request_body
|
82
88
|
body = (_composed_query(_request_query, _request_filter) || {}).tap do |body|
|
83
89
|
body.merge!(facets: facets) if facets?
|
90
|
+
body.merge!(aggregations: aggregations) if aggregations?
|
84
91
|
body.merge!(sort: sort) if sort?
|
85
92
|
body.merge!(_source: fields) if fields?
|
86
93
|
end
|
@@ -105,7 +112,7 @@ module Chewy
|
|
105
112
|
end
|
106
113
|
|
107
114
|
def _request_options
|
108
|
-
options.slice(:size, :from, :explain)
|
115
|
+
options.slice(:size, :from, :explain, :aggregations)
|
109
116
|
end
|
110
117
|
|
111
118
|
def _request_query
|
@@ -12,8 +12,8 @@ module Chewy
|
|
12
12
|
def initialize name, *args
|
13
13
|
@name = name.to_s
|
14
14
|
@options = args.extract_options!
|
15
|
-
@range = @options.
|
16
|
-
@bounds = @options.
|
15
|
+
@range = @options.reject { |k, v| ![:gt, :lt].include?(k) }
|
16
|
+
@bounds = @options.reject { |k, v| ![:left_closed, :right_closed].include?(k) }
|
17
17
|
execution = EXECUTION[args.first.to_sym] if args.first
|
18
18
|
@options[:execution] = execution if execution
|
19
19
|
end
|