dsl_compose 2.1.1 → 2.2.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +7 -0
- data/README.md +103 -5
- data/lib/dsl_compose/reader.rb +30 -0
- data/lib/dsl_compose/reader_base.rb +64 -0
- data/lib/dsl_compose/version.rb +1 -1
- data/lib/dsl_compose.rb +2 -0
- metadata +7 -6
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 409bc8ce86ea967b4a22f675ea029b609a9bb925d8b35255dd4f0a010049f115
|
4
|
+
data.tar.gz: e8d99aa8be417b6c670978dc5cf4461be8ca65dc4316b27ee840b63d82128738
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: a57708bdfb09d3d35cfa3b3e6a76ffa931bcf71c34c14ece5b8737079f6660fefc9596ab5d079cfbf7fed3f733896212b60f81f23a02504dccbcd89a110e01c1
|
7
|
+
data.tar.gz: d87d67e5e6a1f22d49d0b8bb0642f97755f004684d8c0fa7ca1850ba3ce64e46dc016f3ab5fb21edd068e221734d2bae52c09e92f59135f94b0fabd7ac7d3356
|
data/CHANGELOG.md
CHANGED
@@ -1,5 +1,12 @@
|
|
1
1
|
# Changelog
|
2
2
|
|
3
|
+
## [2.2.0](https://github.com/craigulliott/dsl_compose/compare/v2.1.1...v2.2.0) (2023-07-27)
|
4
|
+
|
5
|
+
|
6
|
+
### Features
|
7
|
+
|
8
|
+
* Added a ReaderBase which can be extended to create custom reader classes. Also added dsl_used?, dsl_used_on_ancestors? and dsl_used_on_class_or_ancestors? helper methods to the Reader class ([6507e4a](https://github.com/craigulliott/dsl_compose/commit/6507e4a082c9a0d7e63c580a17bcb8eb2bd940ea))
|
9
|
+
|
3
10
|
## [2.1.1](https://github.com/craigulliott/dsl_compose/compare/v2.1.0...v2.1.1) (2023-07-26)
|
4
11
|
|
5
12
|
|
data/README.md
CHANGED
@@ -339,10 +339,6 @@ reader = DSLCompose::Reader.new MyClass, :my_dsl
|
|
339
339
|
# If no execution of the DSL is found, then nil will be returned
|
340
340
|
execution = reader.last_execution
|
341
341
|
|
342
|
-
# `execution.arguments` returns an ArgumentsReader object which allows access
|
343
|
-
# via dot notation to to any argument values provided to the DSL
|
344
|
-
execution.arguments.my_dsl_argument # returns the value provided for the argument, or nil
|
345
|
-
|
346
342
|
# `execution.method_called?` will return true if the method with the provided
|
347
343
|
# name was called, if a method with this name does exist, but was not called
|
348
344
|
# then false will be returned. If a method with this name does not exist, then
|
@@ -372,7 +368,9 @@ execution.my_dsl_method.each do |arguments|
|
|
372
368
|
end
|
373
369
|
|
374
370
|
# Returns an array of ExecutionReaders to represent each time the DSL was used
|
375
|
-
# on
|
371
|
+
# on the provided class.
|
372
|
+
executions = reader.executions
|
373
|
+
|
376
374
|
# Returns an array of ExecutionReaders to represent each time the DSL was used
|
377
375
|
# on the ancestors of the provided class, but not on the provided class itself.
|
378
376
|
# The executions will be returned in the order they were executed, which is the
|
@@ -386,6 +384,106 @@ executions = reader.ancestor_executions
|
|
386
384
|
# and if the DSL was used more than once on a class then the order they were used.
|
387
385
|
executions = reader.all_executions
|
388
386
|
|
387
|
+
# Returns true if dsl has been executed once or more on the provided class,
|
388
|
+
# otherwise returns false.
|
389
|
+
was_used = reader.dsl_used?
|
390
|
+
|
391
|
+
# Returns true if dsl has been executed once or more on one of the ancestors
|
392
|
+
# of the provided class, otherwise returns false.
|
393
|
+
was_used = reader.dsl_used_on_ancestors?
|
394
|
+
|
395
|
+
# Returns true if dsl has been executed once or more on the provided class or
|
396
|
+
# any of its ancestors, otherwise returns false.
|
397
|
+
was_used = reader.dsl_used_on_class_or_ancestors?
|
398
|
+
|
399
|
+
# `execution.arguments` returns an ArgumentsReader object which allows access
|
400
|
+
# via dot notation to to any argument values provided to the DSL
|
401
|
+
execution.arguments.my_dsl_argument # returns the value provided for the argument, or nil
|
402
|
+
```
|
403
|
+
|
404
|
+
A ReaderBase class is also provided. You can extend this class to create your own Reader objects and provide a much cleaner interface to your specific DSLs.
|
405
|
+
|
406
|
+
```ruby
|
407
|
+
# This is an example DSL for configuring which database and schema should be used
|
408
|
+
# by classes which extend a BaseModel (it's from a hypothetical ORM).
|
409
|
+
class BaseModel
|
410
|
+
# define a DSL which can be used on descendants of this class
|
411
|
+
# to determine which database should be used
|
412
|
+
define_dsl :database_configuration do
|
413
|
+
requires :server_type, :symbol do
|
414
|
+
validate_in [:postgres, :mysql]
|
415
|
+
end
|
416
|
+
requires :server_name, :symbol
|
417
|
+
optional :database_name, :symbol
|
418
|
+
end
|
419
|
+
# define a DSL to set the schema which should be used
|
420
|
+
define_dsl :schema do
|
421
|
+
requires :schema_name, :symbol
|
422
|
+
end
|
423
|
+
end
|
424
|
+
|
425
|
+
# A hypothetical model which extends BaseModel and uses this DSL
|
426
|
+
class User < BaseModel
|
427
|
+
# Use the primary postgres server and the default database_name (because
|
428
|
+
# we are not using the optional `database_name: :foo` argument).
|
429
|
+
database_configuration :postgres, :primary
|
430
|
+
# Persist this models data in the `users` schema.
|
431
|
+
schema :users
|
432
|
+
end
|
433
|
+
|
434
|
+
# An example reader which could be created to provide a more concise
|
435
|
+
# interface to this DSL.
|
436
|
+
# Because this DSL Reader is named DatabaseConfigurationDSLReader it
|
437
|
+
# will automatically refer to the dsl named :database_configuration.
|
438
|
+
class DatabaseConfigurationDSLReader < DSLCompose::ReaderBase
|
439
|
+
# The three methods below provide a more concise access to the DSLs
|
440
|
+
# arguments. If the DSL was never used on the provided class, or any
|
441
|
+
# of it's ancestors, then an error will be raised. This error will
|
442
|
+
# be raised because we are using `last_execution!` instead of `last_execution`.
|
443
|
+
def server_type
|
444
|
+
last_execution!.arguments.server_type
|
445
|
+
end
|
446
|
+
|
447
|
+
def server_name
|
448
|
+
last_execution!.arguments.server_name
|
449
|
+
end
|
450
|
+
|
451
|
+
def database_name
|
452
|
+
last_execution!.arguments.database_name
|
453
|
+
end
|
454
|
+
|
455
|
+
# Returns true or false, depending on if the optional database_name
|
456
|
+
# attribute was used when executing the DSL. If the DSL was never
|
457
|
+
# used on the provided class, or any of it's ancestors, then an error will
|
458
|
+
# be raised (because of the bang method).
|
459
|
+
def has_database_name?
|
460
|
+
last_execution!.arguments.database_name != nil
|
461
|
+
end
|
462
|
+
|
463
|
+
# This method is provided as an example of how to reference other DSLs within
|
464
|
+
# your reader.
|
465
|
+
def schema_name
|
466
|
+
last_execution_of_schema&.arguments&.schema_name || :public
|
467
|
+
end
|
468
|
+
|
469
|
+
private
|
470
|
+
|
471
|
+
# This method is used by the schema_name method above, and is included as an
|
472
|
+
# example of how to reference other DSLs within your Reader.
|
473
|
+
def last_execution_of_schema
|
474
|
+
# Note that there is no bang method here (no "!" after last_execution), so it
|
475
|
+
# will return nil if the DSL was not used.
|
476
|
+
@schema_reader ||= DSLCompose::Reader.new(@base_class, :schema).last_execution
|
477
|
+
end
|
478
|
+
end
|
479
|
+
|
480
|
+
# Use our DatabaseConfigurationDSLReader when parsing this class to
|
481
|
+
# enjoy a more concise API for accessing our DSL values
|
482
|
+
reader = DatabaseConfigurationDSLReader.new(User)
|
483
|
+
reader.server_type # :postgres
|
484
|
+
reader.has_database_name? # false
|
485
|
+
reader.schema_name # :users
|
486
|
+
|
389
487
|
```
|
390
488
|
|
391
489
|
|
data/lib/dsl_compose/reader.rb
CHANGED
@@ -11,6 +11,9 @@ module DSLCompose
|
|
11
11
|
class DSLNotFound < StandardError
|
12
12
|
end
|
13
13
|
|
14
|
+
class NoDSLExecutionFound < StandardError
|
15
|
+
end
|
16
|
+
|
14
17
|
# given a class and the DSL name, finds and creates a reference to the DSL
|
15
18
|
# and the ancestor class where the DSL was originally defined
|
16
19
|
def initialize klass, dsl_name
|
@@ -42,6 +45,24 @@ module DSLCompose
|
|
42
45
|
end
|
43
46
|
end
|
44
47
|
|
48
|
+
# Returns true if dsl has been executed once or more on the provided class,
|
49
|
+
# otherwise returns false.
|
50
|
+
def dsl_used?
|
51
|
+
executions.any?
|
52
|
+
end
|
53
|
+
|
54
|
+
# Returns true if dsl has been executed once or more on one of the ancestors
|
55
|
+
# of the provided class, otherwise returns false.
|
56
|
+
def dsl_used_on_ancestors?
|
57
|
+
ancestor_executions.any?
|
58
|
+
end
|
59
|
+
|
60
|
+
# Returns true if dsl has been executed once or more on the provided class or
|
61
|
+
# any of its ancestors, otherwise returns false.
|
62
|
+
def dsl_used_on_class_or_ancestors?
|
63
|
+
all_executions.any?
|
64
|
+
end
|
65
|
+
|
45
66
|
# Returns an ExecutionReader class which exposes a simple API to access the
|
46
67
|
# arguments, methods and method arguments provided when using this DSL.
|
47
68
|
#
|
@@ -54,6 +75,15 @@ module DSLCompose
|
|
54
75
|
ExecutionReader.new(@dsl_defining_class.dsls.get_last_dsl_execution(@klass, @dsl_name))
|
55
76
|
end
|
56
77
|
|
78
|
+
# A wrapper for last_execution which raises an error if no execution exists
|
79
|
+
def last_execution!
|
80
|
+
execution = @dsl_defining_class.dsls.get_last_dsl_execution(@klass, @dsl_name)
|
81
|
+
if execution.nil?
|
82
|
+
raise NoDSLExecutionFound, "No execution of the `#{@dsl_name}` dsl was found on `#{@klass}` or any of its ancestors"
|
83
|
+
end
|
84
|
+
ExecutionReader.new execution
|
85
|
+
end
|
86
|
+
|
57
87
|
# Returns an array of ExecutionReaders to represent each time the DSL was used
|
58
88
|
# on the provided class.
|
59
89
|
def executions
|
@@ -0,0 +1,64 @@
|
|
1
|
+
module DSLCompose
|
2
|
+
# This class provides a skeleton for creating your own DSL readers.
|
3
|
+
#
|
4
|
+
# All classes which extend from this base class must follow a strict naming convention. The class name
|
5
|
+
# must be the camelcased form of the DSL name, followed by the string "DSLReader". For example, a reader
|
6
|
+
# for a DLS named `:foo_bar` must have the class name `FooBarDSLReader`, as seen below
|
7
|
+
#
|
8
|
+
# class FooBarDSLReader < DSLCompose::ReaderBase
|
9
|
+
# # ...
|
10
|
+
# end
|
11
|
+
class ReaderBase
|
12
|
+
attr_reader :base_class
|
13
|
+
attr_reader :dsl_name
|
14
|
+
attr_reader :reader
|
15
|
+
|
16
|
+
def initialize base_class
|
17
|
+
@base_class = base_class
|
18
|
+
# get the DSL name from the class name
|
19
|
+
@dsl_name = dsl_name_from_class_name self.class
|
20
|
+
# create the reader
|
21
|
+
@reader = DSLCompose::Reader.new(base_class, @dsl_name)
|
22
|
+
end
|
23
|
+
|
24
|
+
private
|
25
|
+
|
26
|
+
def dsl_name_from_class_name reader_class
|
27
|
+
camelcased = reader_class.name.split("::").last.gsub(/DSLReader\Z/, "")
|
28
|
+
underscored = camelcased.gsub(/([A-Z]+)([A-Z][a-z])/, '\1_\2').gsub(/([a-z\d])([A-Z])/, '\1_\2')
|
29
|
+
underscored.downcase.to_sym
|
30
|
+
end
|
31
|
+
|
32
|
+
def dsl_used?
|
33
|
+
@reader.dsl_used?
|
34
|
+
end
|
35
|
+
|
36
|
+
def dsl_used_on_ancestors?
|
37
|
+
@reader.dsl_used_on_ancestors?
|
38
|
+
end
|
39
|
+
|
40
|
+
def dsl_used_on_class_or_ancestors?
|
41
|
+
@reader.dsl_used_on_class_or_ancestors?
|
42
|
+
end
|
43
|
+
|
44
|
+
def last_execution
|
45
|
+
@reader.last_execution
|
46
|
+
end
|
47
|
+
|
48
|
+
def last_execution!
|
49
|
+
@reader.last_execution!
|
50
|
+
end
|
51
|
+
|
52
|
+
def executions
|
53
|
+
@reader.executions
|
54
|
+
end
|
55
|
+
|
56
|
+
def ancestor_executions
|
57
|
+
@reader.ancestor_executions
|
58
|
+
end
|
59
|
+
|
60
|
+
def all_executions
|
61
|
+
@reader.all_executions
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
data/lib/dsl_compose/version.rb
CHANGED
data/lib/dsl_compose.rb
CHANGED
@@ -32,6 +32,8 @@ require "dsl_compose/reader"
|
|
32
32
|
require "dsl_compose/reader/execution_reader"
|
33
33
|
require "dsl_compose/reader/execution_reader/arguments_reader"
|
34
34
|
|
35
|
+
require "dsl_compose/reader_base"
|
36
|
+
|
35
37
|
require "dsl_compose/interpreter/execution/method_calls/method_call"
|
36
38
|
require "dsl_compose/interpreter/execution/method_calls"
|
37
39
|
require "dsl_compose/interpreter/execution/arguments"
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: dsl_compose
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 2.
|
4
|
+
version: 2.2.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Craig Ulliott
|
8
|
-
autorequire:
|
8
|
+
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2023-07-
|
11
|
+
date: 2023-07-27 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: class_spec_helper
|
@@ -77,15 +77,16 @@ files:
|
|
77
77
|
- lib/dsl_compose/reader.rb
|
78
78
|
- lib/dsl_compose/reader/execution_reader.rb
|
79
79
|
- lib/dsl_compose/reader/execution_reader/arguments_reader.rb
|
80
|
+
- lib/dsl_compose/reader_base.rb
|
80
81
|
- lib/dsl_compose/shared_configuration.rb
|
81
82
|
- lib/dsl_compose/version.rb
|
82
|
-
homepage:
|
83
|
+
homepage:
|
83
84
|
licenses:
|
84
85
|
- MIT
|
85
86
|
metadata:
|
86
87
|
source_code_uri: https://github.com/craigulliott/dsl_compose/
|
87
88
|
changelog_uri: https://github.com/craigulliott/dsl_compose/blob/main/CHANGELOG.md
|
88
|
-
post_install_message:
|
89
|
+
post_install_message:
|
89
90
|
rdoc_options: []
|
90
91
|
require_paths:
|
91
92
|
- lib
|
@@ -101,7 +102,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
101
102
|
version: '0'
|
102
103
|
requirements: []
|
103
104
|
rubygems_version: 3.3.26
|
104
|
-
signing_key:
|
105
|
+
signing_key:
|
105
106
|
specification_version: 4
|
106
107
|
summary: Ruby gem to add dynamic DSLs to classes
|
107
108
|
test_files: []
|