appfuel 0.2.5 → 0.2.6

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.
Files changed (38) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +8 -0
  3. data/appfuel.gemspec +1 -1
  4. data/lib/appfuel/application/app_container.rb +0 -1
  5. data/lib/appfuel/application/dispatcher.rb +32 -0
  6. data/lib/appfuel/application/root.rb +4 -4
  7. data/lib/appfuel/application.rb +2 -1
  8. data/lib/appfuel/domain/domain_name_parser.rb +9 -5
  9. data/lib/appfuel/domain.rb +0 -7
  10. data/lib/appfuel/handler/base.rb +8 -14
  11. data/lib/appfuel/storage/db/mapper.rb +31 -35
  12. data/lib/appfuel/storage/db/repository.rb +53 -121
  13. data/lib/appfuel/storage/repository/base.rb +246 -0
  14. data/lib/appfuel/storage/repository/criteria.rb +317 -0
  15. data/lib/appfuel/{domain → storage/repository}/expr.rb +1 -1
  16. data/lib/appfuel/storage/repository/expr_conjunction.rb +41 -0
  17. data/lib/appfuel/{domain → storage/repository}/expr_parser.rb +10 -22
  18. data/lib/appfuel/{domain → storage/repository}/expr_transform.rb +7 -7
  19. data/lib/appfuel/{repository → storage/repository}/mapper.rb +8 -3
  20. data/lib/appfuel/storage/repository/order_expr.rb +51 -0
  21. data/lib/appfuel/storage/repository/runner.rb +62 -0
  22. data/lib/appfuel/storage/repository/search_parser.rb +50 -0
  23. data/lib/appfuel/storage/repository/search_transform.rb +58 -0
  24. data/lib/appfuel/{domain/criteria_settings.rb → storage/repository/settings.rb} +20 -5
  25. data/lib/appfuel/{repository.rb → storage/repository.rb} +13 -0
  26. data/lib/appfuel/storage.rb +1 -0
  27. data/lib/appfuel/version.rb +1 -1
  28. data/lib/appfuel.rb +0 -2
  29. metadata +21 -19
  30. data/lib/appfuel/domain/base_criteria.rb +0 -171
  31. data/lib/appfuel/domain/exists_criteria.rb +0 -57
  32. data/lib/appfuel/domain/expr_conjunction.rb +0 -27
  33. data/lib/appfuel/domain/search_criteria.rb +0 -137
  34. data/lib/appfuel/repository/base.rb +0 -86
  35. data/lib/appfuel/repository_runner.rb +0 -60
  36. /data/lib/appfuel/{repository → storage/repository}/initializer.rb +0 -0
  37. /data/lib/appfuel/{repository → storage/repository}/mapping_dsl.rb +0 -0
  38. /data/lib/appfuel/{repository → storage/repository}/mapping_entry.rb +0 -0
@@ -1,7 +1,5 @@
1
- require 'parslet'
2
-
3
1
  module Appfuel
4
- module Domain
2
+ module Repository
5
3
  # A PEG (Parser Expression Grammer) transformer for our domain language.
6
4
  #
7
5
  class ExprTransform < Parslet::Transform
@@ -41,13 +39,15 @@ module Appfuel
41
39
  end
42
40
 
43
41
  def self.build_conjunction_node(data)
44
- if data.key?(:root)
42
+ if data.is_a?(Expr) || data.is_a?(ExprConjunction)
43
+ node = data
44
+ elsif data.key?(:root)
45
45
  node = data[:root]
46
46
  elsif data.key?(:domain_expr)
47
- node = data[:domain_expr]
47
+ node = data[:domain_expr]
48
48
  elsif data.key?(:and) || data.key?(:or)
49
- op = right.key?(:and) ? 'and' : 'or'
50
- node = build_conjunction(op, data)
49
+ op = data.key?(:and) ? :and : :or
50
+ node = build_conjunction(op, data[op])
51
51
  end
52
52
  node
53
53
  end
@@ -138,13 +138,14 @@ module Appfuel
138
138
  app_container[key]
139
139
  end
140
140
 
141
- def to_entity_hash(domain_name, data)
141
+ def to_entity_hash(domain_name, storage)
142
142
  entity_attrs = {}
143
+ storage_data = storage_hash(storage)
143
144
  each_entity_attr(domain_name) do |entry|
144
145
  attr_name = entry.storage_attr
145
146
  domain_attr = entry.domain_attr
146
- next unless data.key?(attr_name)
147
- update_entity_hash(domain_attr, data[attr_name], entity_attrs)
147
+ next unless storage_data.key?(attr_name)
148
+ update_entity_hash(domain_attr, storage_data[attr_name], entity_attrs)
148
149
  end
149
150
 
150
151
  entity_attrs
@@ -221,6 +222,10 @@ module Appfuel
221
222
  target
222
223
  end
223
224
 
225
+ def expr_conjunction?(value)
226
+ value.instance_of?(ExprConjunction)
227
+ end
228
+
224
229
  private
225
230
  def validate_domain(entity_name)
226
231
  unless entity?(entity_name)
@@ -0,0 +1,51 @@
1
+ module Appfuel
2
+ module Repository
3
+ class OrderExpr < Expr
4
+
5
+ def self.build(data)
6
+ return [data] if data.instance_of?(self)
7
+ data = [data] if data.is_a?(String)
8
+ unless data.respond_to?(:each)
9
+ fail "order must be a string or implement :each"
10
+ end
11
+
12
+ results = []
13
+ data.each do |item|
14
+ item = parse_order_string(item) if item.is_a?(String)
15
+ if item.instance_of?(self)
16
+ results << item
17
+ next
18
+ end
19
+
20
+ if !item.is_a?(Hash)
21
+ fail "order array must be a list of strings or hashes"
22
+ end
23
+ domain_attr, dir = item.first
24
+ results << self.new(domain_attr, dir)
25
+ end
26
+ results
27
+ end
28
+
29
+ def initialize(domain_attr, op = nil)
30
+ op ||= 'asc'
31
+
32
+ super(domain_attr, op, nil)
33
+ @op = @op.downcase
34
+ unless ['asc', 'desc'].include?(@op)
35
+ fail "order direction must be either asc or desc"
36
+ end
37
+ end
38
+
39
+ def to_s
40
+ "#{attr_list.join('.')} #{op}"
41
+ end
42
+
43
+ private
44
+ def self.parse_order_string(str)
45
+ str, dir = str.split(' ')
46
+ dir = 'asc' if dir.nil?
47
+ {str => dir.downcase}
48
+ end
49
+ end
50
+ end
51
+ end
@@ -0,0 +1,62 @@
1
+ module Appfuel
2
+ # Used in the validation system by custom predicates to ask the question if
3
+ # an entity exists in the database
4
+ module Repository
5
+ class Runner
6
+ attr_reader :repo_namespace, :criteria_class
7
+
8
+ # The call relies on the fact that we can build a criteria find the
9
+ # correct repo and call the exists? interface on that repo. The identity
10
+ # of any given repo requires its namespace + its class name.
11
+ #
12
+ # @param namespace [String] fully qualified namespace string fro repos
13
+ # @param criteria_class [Class] class used to represent the criteria
14
+ # @returns [ExistsInDbRunner]
15
+ def initialize(namespace, criteria_class)
16
+ @repo_namespace = namespace
17
+ @criteria_class = criteria_class
18
+ end
19
+
20
+ def create_criteria(entity_key, opts = {})
21
+ criteria_class.new(entity_key, opts)
22
+ end
23
+
24
+ def query(criteria)
25
+ load_repo(criteria).query(criteria)
26
+ end
27
+
28
+ # @param entity_key [String] the type identifier for an entity
29
+ # @param opts [Hash] one attr => value pair is required
30
+ # repo => name is optional
31
+ #
32
+ # @return [Bool]
33
+ def exists?(entity_key, opts = {})
34
+ fail "opts must be a hash" unless opts.is_a?(Hash)
35
+
36
+ criteria_opts = {}
37
+ if opts.key?(:repo)
38
+ criteria_opts[:repo] = opts.delete(:repo)
39
+ end
40
+ fail "opts hash must have one attr => value pair" if opts.empty?
41
+
42
+ property, value = opts.first
43
+ criteria = create_criteria(entity_key, criteria_opts)
44
+ criteria.exists(property, value)
45
+
46
+ load_repo(criteria).exists?(criteria)
47
+ end
48
+
49
+
50
+ private
51
+
52
+ def load_repo(criteria)
53
+ klass = "#{repo_namespace}::#{criteria.repo_name}"
54
+ unless Kernel.const_defined?(klass)
55
+ fail "RepositoryRunner: failed - repo #{klass} not defined"
56
+ end
57
+
58
+ Kernel.const_get(klass).new
59
+ end
60
+ end
61
+ end
62
+ end
@@ -0,0 +1,50 @@
1
+ module Appfuel
2
+ module Repository
3
+ class SearchParser < ExprParser
4
+ rule(:filter_identifier) { stri('filter') }
5
+ rule(:order_identifier) { stri('order') }
6
+ rule(:limit_identifier) { stri('limit') }
7
+
8
+ rule(:order_dir) do
9
+ (stri('asc') | stri('desc')).as(:order_dir)
10
+ end
11
+
12
+ rule(:domain_name) do
13
+ attr_label.as(:feature) >> str('.') >> attr_label.as(:basename)
14
+ end
15
+
16
+ rule(:limit_expr) do
17
+ (
18
+ limit_identifier >> space >> space? >> integer.as(:value)
19
+ ).as(:limit)
20
+ end
21
+
22
+ rule(:order_expr) do
23
+ (
24
+ (domain_attr >> space >> order_dir) | domain_attr
25
+ ).as(:order_expr)
26
+ end
27
+
28
+ # order id
29
+ # order id asc
30
+ # order foo.id asc
31
+ # order foo.id, code desc, foo.bar.id asc
32
+ rule(:order_by) do
33
+ (
34
+ order_identifier >> space >> space? >>
35
+ (order_expr >> (comma >> order_expr).repeat).maybe
36
+ ).as(:order)
37
+ end
38
+
39
+ rule(:search) do
40
+ (
41
+ domain_name.as(:domain) >> space >> space? >>
42
+ filter_identifier >> space >> space? >>
43
+ or_operation.as(:filters) >> order_by.maybe >> space? >> limit_expr.maybe
44
+ ).as(:search)
45
+ end
46
+
47
+ root(:search)
48
+ end
49
+ end
50
+ end
@@ -0,0 +1,58 @@
1
+ module Appfuel
2
+ module Repository
3
+ class SearchTransform < ExprTransform
4
+
5
+
6
+ rule(order_dir: simple(:n)) {
7
+ value = n.to_s.downcase
8
+ value == 'desc' ? 'desc' : 'asc'
9
+ }
10
+
11
+ rule(order_expr: subtree(:expr)) do |dict|
12
+ expr = dict[:expr]
13
+ domain_attr = expr[:domain_attr]
14
+ order_dir = expr[:order_dir] || 'asc'
15
+ OrderExpr.new(domain_attr, order_dir)
16
+ end
17
+
18
+ rule(attr_label: simple(:n)) { n.to_s }
19
+
20
+ rule(domain_attr: simple(:n)) {
21
+ list = n.is_a?(Array) ? n : [n]
22
+ {domain_attr: list}
23
+ }
24
+
25
+ rule(domain_expr: subtree(:domain_expr)) do |dict|
26
+ data = dict[:domain_expr]
27
+ domain_attr = data[:domain_attr]
28
+ op = data[:op]
29
+ value = data[:value]
30
+ Expr.new(domain_attr, op, value)
31
+ end
32
+
33
+ rule(search: subtree(:search)) do |dict|
34
+ search = dict[:search]
35
+ domain = search[:domain]
36
+ filters = search[:filters]
37
+ orders = search[:order]
38
+ limit = search[:limit]
39
+
40
+ if filters.is_a?(Hash) && filters.key?(:root)
41
+ filters = filters[:root]
42
+ end
43
+ result = {}
44
+ result[:domain] = "#{domain[:feature]}.#{domain[:basename]}"
45
+ result[:filters] = filters
46
+ unless limit.nil?
47
+ result[:limit] = limit[:value]
48
+ end
49
+
50
+ unless orders.nil?
51
+ orders = orders.is_a?(Array) ? orders : [orders]
52
+ result[:order] = orders
53
+ end
54
+ {search: Criteria.build(result)}
55
+ end
56
+ end
57
+ end
58
+ end
@@ -1,6 +1,5 @@
1
1
  module Appfuel
2
- module Domain
3
-
2
+ module Repository
4
3
  # The Criteria represents the interface between the repositories and actions
5
4
  # or commands. The allow you to find entities in the application storage (
6
5
  # a database) without knowledge of that storage system. The criteria will
@@ -19,7 +18,7 @@ module Appfuel
19
18
  # transform
20
19
  # search_name
21
20
  #
22
- class CriteriaSettings
21
+ class Settings
23
22
  DEFAULT_PAGE = 1
24
23
  DEFAULT_PER_PAGE = 20
25
24
 
@@ -29,8 +28,8 @@ module Appfuel
29
28
  # @param opts [Hash] options for initializing criteria
30
29
  # @return [Criteria]
31
30
  def initialize(settings = {})
32
- @parser = settings[:expr_parser] || ExprParser.new
33
- @transform = settings[:expr_transform] || ExprTransform.new
31
+ @parser = settings[:parser] || SearchParser.new
32
+ @transform = settings[:transform] || SearchTransform.new
34
33
 
35
34
 
36
35
  empty_dataset_is_valid!
@@ -55,10 +54,22 @@ module Appfuel
55
54
  all
56
55
  end
57
56
 
57
+ manual_query(settings[:manual_query]) if settings.key?(:manual_query)
58
+
58
59
  page(settings[:page] || DEFAULT_PAGE)
59
60
  per_page(settings[:per_page] || DEFAULT_PER_PAGE)
60
61
  end
61
62
 
63
+ def manual_query?
64
+ !manual_query.nil?
65
+ end
66
+
67
+ def manual_query(value = nil)
68
+ return @manual_query if value.nil?
69
+ @manual_query = value
70
+ self
71
+ end
72
+
62
73
  def disable_pagination?
63
74
  @disable_pagination
64
75
  end
@@ -85,6 +96,10 @@ module Appfuel
85
96
  self
86
97
  end
87
98
 
99
+ def single?
100
+ first? || last?
101
+ end
102
+
88
103
  def all?
89
104
  @all
90
105
  end
@@ -1,8 +1,21 @@
1
+ require 'parslet'
2
+ require 'parslet/convenience'
3
+
1
4
  require_relative 'repository/base'
2
5
  require_relative 'repository/mapping_entry'
3
6
  require_relative 'repository/mapping_dsl'
4
7
  require_relative 'repository/mapper'
5
8
  require_relative 'repository/initializer'
9
+ require_relative 'repository/runner'
10
+ require_relative 'repository/expr'
11
+ require_relative 'repository/expr_conjunction'
12
+ require_relative 'repository/order_expr'
13
+ require_relative 'repository/criteria'
14
+ require_relative 'repository/expr_parser'
15
+ require_relative 'repository/search_parser'
16
+ require_relative 'repository/expr_transform'
17
+ require_relative 'repository/search_transform'
18
+ require_relative 'repository/settings'
6
19
 
7
20
  module Appfuel
8
21
  module Repository
@@ -1,3 +1,4 @@
1
+ require_relative 'storage/repository'
1
2
  require_relative 'storage/file'
2
3
  require_relative 'storage/memory'
3
4
  require_relative 'storage/db'
@@ -1,3 +1,3 @@
1
1
  module Appfuel
2
- VERSION = "0.2.5"
2
+ VERSION = "0.2.6"
3
3
  end
data/lib/appfuel.rb CHANGED
@@ -197,8 +197,6 @@ end
197
197
  # Domain Entities
198
198
  require "appfuel/domain"
199
199
  require "appfuel/presenter"
200
- require "appfuel/repository"
201
- require "appfuel/repository_runner"
202
200
  require "appfuel/storage"
203
201
  require "appfuel/handler"
204
202
 
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: appfuel
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.5
4
+ version: 0.2.6
5
5
  platform: ruby
6
6
  authors:
7
7
  - Robert Scott-Buccleuch
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2017-05-25 00:00:00.000000000 Z
11
+ date: 2017-06-06 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activerecord
@@ -16,14 +16,14 @@ dependencies:
16
16
  requirements:
17
17
  - - "~>"
18
18
  - !ruby/object:Gem::Version
19
- version: 5.0.2
19
+ version: 5.1.0
20
20
  type: :runtime
21
21
  prerelease: false
22
22
  version_requirements: !ruby/object:Gem::Requirement
23
23
  requirements:
24
24
  - - "~>"
25
25
  - !ruby/object:Gem::Version
26
- version: 5.0.2
26
+ version: 5.1.0
27
27
  - !ruby/object:Gem::Dependency
28
28
  name: dry-types
29
29
  requirement: !ruby/object:Gem::Requirement
@@ -259,6 +259,7 @@ files:
259
259
  - lib/appfuel/application.rb
260
260
  - lib/appfuel/application/app_container.rb
261
261
  - lib/appfuel/application/container_class_registration.rb
262
+ - lib/appfuel/application/dispatcher.rb
262
263
  - lib/appfuel/application/root.rb
263
264
  - lib/appfuel/cli_msg_request.rb
264
265
  - lib/appfuel/configuration.rb
@@ -267,19 +268,11 @@ files:
267
268
  - lib/appfuel/configuration/populate.rb
268
269
  - lib/appfuel/configuration/search.rb
269
270
  - lib/appfuel/domain.rb
270
- - lib/appfuel/domain/base_criteria.rb
271
271
  - lib/appfuel/domain/criteria_builder.rb
272
- - lib/appfuel/domain/criteria_settings.rb
273
272
  - lib/appfuel/domain/domain_name_parser.rb
274
273
  - lib/appfuel/domain/dsl.rb
275
274
  - lib/appfuel/domain/entity.rb
276
275
  - lib/appfuel/domain/entity_collection.rb
277
- - lib/appfuel/domain/exists_criteria.rb
278
- - lib/appfuel/domain/expr.rb
279
- - lib/appfuel/domain/expr_conjunction.rb
280
- - lib/appfuel/domain/expr_parser.rb
281
- - lib/appfuel/domain/expr_transform.rb
282
- - lib/appfuel/domain/search_criteria.rb
283
276
  - lib/appfuel/domain/value_object.rb
284
277
  - lib/appfuel/errors.rb
285
278
  - lib/appfuel/feature.rb
@@ -297,13 +290,6 @@ files:
297
290
  - lib/appfuel/predicates.rb
298
291
  - lib/appfuel/presenter.rb
299
292
  - lib/appfuel/presenter/base.rb
300
- - lib/appfuel/repository.rb
301
- - lib/appfuel/repository/base.rb
302
- - lib/appfuel/repository/initializer.rb
303
- - lib/appfuel/repository/mapper.rb
304
- - lib/appfuel/repository/mapping_dsl.rb
305
- - lib/appfuel/repository/mapping_entry.rb
306
- - lib/appfuel/repository_runner.rb
307
293
  - lib/appfuel/request.rb
308
294
  - lib/appfuel/response.rb
309
295
  - lib/appfuel/response_handler.rb
@@ -323,6 +309,22 @@ files:
323
309
  - lib/appfuel/storage/memory.rb
324
310
  - lib/appfuel/storage/memory/mapper.rb
325
311
  - lib/appfuel/storage/memory/repository.rb
312
+ - lib/appfuel/storage/repository.rb
313
+ - lib/appfuel/storage/repository/base.rb
314
+ - lib/appfuel/storage/repository/criteria.rb
315
+ - lib/appfuel/storage/repository/expr.rb
316
+ - lib/appfuel/storage/repository/expr_conjunction.rb
317
+ - lib/appfuel/storage/repository/expr_parser.rb
318
+ - lib/appfuel/storage/repository/expr_transform.rb
319
+ - lib/appfuel/storage/repository/initializer.rb
320
+ - lib/appfuel/storage/repository/mapper.rb
321
+ - lib/appfuel/storage/repository/mapping_dsl.rb
322
+ - lib/appfuel/storage/repository/mapping_entry.rb
323
+ - lib/appfuel/storage/repository/order_expr.rb
324
+ - lib/appfuel/storage/repository/runner.rb
325
+ - lib/appfuel/storage/repository/search_parser.rb
326
+ - lib/appfuel/storage/repository/search_transform.rb
327
+ - lib/appfuel/storage/repository/settings.rb
326
328
  - lib/appfuel/types.rb
327
329
  - lib/appfuel/validation.rb
328
330
  - lib/appfuel/validation/validator.rb
@@ -1,171 +0,0 @@
1
- module Appfuel
2
- module Domain
3
-
4
- # The Criteria represents the interface between the repositories and actions
5
- # or commands. The allow you to find entities in the application storage (
6
- # a database) without knowledge of that storage system. The criteria will
7
- # always refer to its queries in the domain language for which the repo is
8
- # responsible for mapping that query to its persistence layer.
9
- #
10
- # global.user
11
- # memberships.user
12
- #
13
- # exist: 'foo.bar exists id = 6'
14
- # search: 'foo.bar filter id = 6 and bar = "foo" order id asc limit 6'
15
- #
16
- # search:
17
- # domain: 'foo.bar',
18
- #
19
- # filters: 'id = 6 or id = 8 and id = 9'
20
- # filters: [
21
- # 'id = 6',
22
- # {or: 'id = 8'}
23
- # {and: id = 9'}
24
- # ]
25
- #
26
- # order: 'foo.bar.id asc'
27
- # order: 'foo.bar.id'
28
- # order: [
29
- # 'foo.bar.id',
30
- # {desc: 'foo.bar.id'},
31
- # {asc: 'foo.bar.id'}
32
- # ]
33
- # limit: 1
34
- #
35
- # settings:
36
- # page: 1
37
- # per_page: 2
38
- # disable_pagination
39
- # first
40
- # all
41
- # last
42
- # error_on_empty
43
- # parser
44
- # transform
45
- #
46
- # exists:
47
- # domain:
48
- # expr:
49
- #
50
- #
51
- class BaseCriteria
52
- include DomainNameParser
53
-
54
-
55
- attr_reader :domain_basename, :domain_name, :feature, :settings, :filters
56
-
57
- # Parse out the domain into feature, domain, determine the name of the
58
- # repo this criteria is for and initailize basic settings.
59
- # global.user
60
- #
61
- # membership.user
62
- # foo.id filter name like "foo" order foo.bar.id asc limit 2
63
- # foo.id exists foo.id = 5
64
- #
65
- # @example
66
- # SpCore::Domain::Criteria('foo', single: true)
67
- # Types.Criteria('foo.bar', single: true)
68
- #
69
- # === Options
70
- # error_on_empty: will cause the repo to fail when query returns an
71
- # an empty dataset. The failure will have the message
72
- # with key as domain and text is "<domain> not found"
73
- #
74
- # single: will cause the repo to return only one, the first,
75
- # entity in the dataset
76
- #
77
- # @param domain [String] fully qualified domain name
78
- # @param opts [Hash] options for initializing criteria
79
- # @return [Criteria]
80
- def initialize(domain_name, data = {})
81
- @feature, @domain_basename, @domain_name = parse_domain_name(domain_name)
82
- @settings = data[:settings] || CriteriaSettings.new(data)
83
- @filters = nil
84
- @params = {}
85
- end
86
-
87
- def clear_filters
88
- @filters = nil
89
- end
90
-
91
- def filters?
92
- !filters.nil?
93
- end
94
-
95
- def global?
96
- !feature?
97
- end
98
-
99
- def feature?
100
- @feature != 'global'
101
- end
102
-
103
- # @example
104
- # criteria.add_param('foo', 100)
105
- #
106
- # @param key [Symbol, String] The key name where we want to keep the value
107
- # @param value [String, Integer] The value that belongs to the key param
108
- # @return [String, Integer] The saved value
109
- def add_param(key, value)
110
- fail 'key should not be nil' if key.nil?
111
-
112
- @params[key.to_sym] = value
113
- end
114
-
115
- # @param key [String, Symbol]
116
- # @return [String, Integer, Boolean] the found value
117
- def param(key)
118
- @params[key.to_sym]
119
- end
120
-
121
- # @param key [String, Symbol]
122
- # @return [Boolean]
123
- def param?(key)
124
- @params.key?(key.to_sym)
125
- end
126
-
127
- # @return [Boolean] if the @params variable has values
128
- def params?
129
- !@params.empty?
130
- end
131
-
132
- private
133
- def parse_expr(str)
134
- if !(settings.parser && settings.parser.respond_to?(:parse))
135
- fail "expression parser must implement to :parse"
136
- end
137
-
138
- if !(settings.transform && settings.transform.respond_to?(:apply))
139
- fail "expression transform must implement :apply"
140
- end
141
-
142
- begin
143
- tree = settings.parser.parse(str)
144
- rescue Parslet::ParseFailed => e
145
- msg = "The expression (#{str}) failed to parse"
146
- err = RuntimeError.new(msg)
147
- err.set_backtrace(e.backtrace)
148
- raise err
149
- end
150
-
151
- result = settings.transform.apply(tree)
152
- result = result[:domain_expr] || result[:root]
153
- unless result
154
- fail "unable to parse (#{str}) correctly"
155
- end
156
- result
157
- end
158
-
159
- def qualify_expr(domain_expr)
160
- return domain_expr if domain_expr.qualified?
161
- if global?
162
- domain_expr.qualify_global(domain_basename)
163
- return domain_expr
164
- end
165
-
166
- domain_expr.qualify_feature(feature, domain_basename)
167
- domain_expr
168
- end
169
- end
170
- end
171
- end