massager 0.1.1 → 0.2.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/README.md +102 -10
- data/lib/massager/attributes/attribute.rb +29 -0
- data/lib/massager/attributes/enum_attribute.rb +21 -0
- data/lib/massager/version.rb +1 -1
- data/lib/massager.rb +33 -26
- metadata +4 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 53f2c10f9317523283972f8951006e762166f9c9
|
4
|
+
data.tar.gz: ce31aa5c501efde93d6b7fa5ad2787690e502689
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 738f93609dbd29d766e922f239d2da48aab11404b449e7a0041263f8f3af7dd493c83acb3120e7a208c134ad9627d3244d9f793dbf89316cc44b6ea7cad9aa6d
|
7
|
+
data.tar.gz: b5e655c41a1a8623a006c4f09190508a22e648c2ce79f7b29f26a2af6fa21206562d26db128042faa8ea5f1e785492a42eb33dedfc7da0ddfcf90d42e6d28ba1
|
data/README.md
CHANGED
@@ -1,8 +1,6 @@
|
|
1
1
|
# Massager
|
2
2
|
|
3
|
-
|
4
|
-
|
5
|
-
TODO: Delete this and the text above, and describe your gem
|
3
|
+
Have you ever felt a need to massage your data just a little bit before working with it? This is what Massager was built for.
|
6
4
|
|
7
5
|
## Installation
|
8
6
|
|
@@ -20,20 +18,114 @@ Or install it yourself as:
|
|
20
18
|
|
21
19
|
$ gem install massager
|
22
20
|
|
23
|
-
##
|
21
|
+
## Simplest usecase
|
22
|
+
To start using Massager, just include it in your classes, like so:
|
23
|
+
```ruby
|
24
|
+
class ExampleClass
|
25
|
+
include Massager
|
26
|
+
attribute :foo, "bar"
|
27
|
+
end
|
28
|
+
```
|
29
|
+
In this scenario, the "bar" key's value will become the result `foo` method
|
30
|
+
```ruby
|
31
|
+
testable = ExampleClass.build({"bar" => "value"})
|
32
|
+
testable.foo #=> "value"
|
33
|
+
```
|
34
|
+
|
35
|
+
## Type checking
|
36
|
+
You can also pass type checks using dry-types library:
|
37
|
+
```ruby
|
38
|
+
class ExampleClass
|
39
|
+
include Massager
|
40
|
+
attribute :foo, "bar", type: Types::Strict::String
|
41
|
+
end
|
42
|
+
```
|
43
|
+
It will raise an error if the type is not correct:
|
44
|
+
```ruby
|
45
|
+
testable = ExampleClass.build({"bar" => "value"})
|
46
|
+
testable.foo #=> "value"
|
47
|
+
testable = ExampleClass.build({"bar" => 123})
|
48
|
+
testable.foo #=> raises Dry::Types::ConstraintError
|
49
|
+
```
|
50
|
+
If you want to define your own types, check the Dry Types library. Type needs to respond to `call` method, so
|
51
|
+
you can define your own
|
52
|
+
|
53
|
+
## Preprocessing the value via block
|
54
|
+
|
55
|
+
You can add bit of preprocessing via block (The type check will be preformed afer the block is executed):
|
56
|
+
```ruby
|
57
|
+
class ExampleClass
|
58
|
+
include Massager
|
59
|
+
attribute :foo, "bar", type: Types::Strict::String do |v|
|
60
|
+
v.upcase
|
61
|
+
end
|
62
|
+
end
|
63
|
+
```
|
64
|
+
And it will have following result
|
65
|
+
```ruby
|
66
|
+
testable = ExampleClass.build({"bar" => "value"})
|
67
|
+
testable.foo #=> "VALUE"
|
68
|
+
```
|
24
69
|
|
25
|
-
|
70
|
+
## Combining multiple keys
|
26
71
|
|
27
|
-
|
72
|
+
```ruby
|
73
|
+
class ExampleClass
|
74
|
+
include Massager
|
75
|
+
attribute :foo, "bar", "baz", type: Types::Strict::String do |bar, baz|
|
76
|
+
"#{bar} #{baz}"
|
77
|
+
end
|
78
|
+
end
|
79
|
+
```
|
80
|
+
Note that if you pass multiple keys, the modifier block is mandatory
|
28
81
|
|
29
|
-
|
82
|
+
```ruby
|
83
|
+
testable = ExampleClass.build({"bar" => "bar", "baz" => "baz"})
|
84
|
+
testable.foo #=> "bar baz"
|
85
|
+
```
|
30
86
|
|
31
|
-
|
87
|
+
## Enum attributes
|
88
|
+
If you want to have enum as a result, you will need to use `enum_attribute`
|
89
|
+
```ruby
|
90
|
+
class ExampleClass
|
91
|
+
include Massager
|
92
|
+
enum_attribute :foo, "bar", "baz"
|
93
|
+
end
|
94
|
+
```
|
95
|
+
```ruby
|
96
|
+
testable = ExampleClass.build({"bar" => "bar", "baz" => "baz"})
|
97
|
+
testable.foo #=> ["bar", "baz"]
|
98
|
+
```
|
32
99
|
|
33
|
-
##
|
100
|
+
## Enum attribute with modifier
|
101
|
+
You can apply modifications to the collection
|
102
|
+
```ruby
|
103
|
+
class ExampleClass
|
104
|
+
include Massager
|
105
|
+
enum_attribute :foo, "bar", "baz" do |values|
|
106
|
+
values.reverse
|
107
|
+
end
|
108
|
+
end
|
109
|
+
```
|
110
|
+
```ruby
|
111
|
+
testable = ExampleClass.build({"bar" => "bar", "baz" => "baz"})
|
112
|
+
testable.foo #=> ["baz", "bar"]
|
113
|
+
```
|
34
114
|
|
35
|
-
|
115
|
+
## Enum attribute with type check
|
116
|
+
You can provide type checks as well
|
117
|
+
```ruby
|
118
|
+
class ExampleClass
|
119
|
+
include Massager
|
120
|
+
enum_attribute :foo, "bar", "baz", type: Types::Strict::Array.member(Types::Strict::String)
|
121
|
+
end
|
122
|
+
```
|
123
|
+
```ruby
|
124
|
+
testable = ExampleClass.build({"bar" => "bar", "baz" => "baz"})
|
125
|
+
testable.foo #=> ["bar", "baz"]
|
36
126
|
|
127
|
+
testable = ExampleClass.build({"bar" => 123, "baz" => "baz"}) # Will raise Dry::Types::ConstraintError
|
128
|
+
```
|
37
129
|
|
38
130
|
## License
|
39
131
|
|
@@ -0,0 +1,29 @@
|
|
1
|
+
module Massager
|
2
|
+
class Attribute
|
3
|
+
def initialize(name:, target_keys:, opts: {}, block: nil)
|
4
|
+
raise ArgumentError, "If you pass multiple keys, you have to use modifier block" if block.nil? && target_keys.count > 1
|
5
|
+
@name, @target_keys, @opts, @block = name, target_keys, opts, block
|
6
|
+
end
|
7
|
+
|
8
|
+
def call(values)
|
9
|
+
begin
|
10
|
+
values = values.values_at(*target_keys)
|
11
|
+
Dry::Monads::Maybe(block).fmap {|block| values = block.call(*values)}
|
12
|
+
Dry::Monads::Maybe(opts[:type]).fmap {|type| values = type.call(*values)}
|
13
|
+
return_result(*values)
|
14
|
+
rescue ArgumentError
|
15
|
+
raise ArgumentError, "The result of modifier block should return single element"
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
def return_result(values)
|
20
|
+
values
|
21
|
+
end
|
22
|
+
|
23
|
+
def match_schema?(attrs)
|
24
|
+
(attrs.keys & target_keys).any?
|
25
|
+
end
|
26
|
+
|
27
|
+
attr_reader :target_keys, :block, :opts, :name
|
28
|
+
end
|
29
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
module Massager
|
2
|
+
class EnumAttribute
|
3
|
+
def initialize(name:, target_keys:, opts: {}, block:)
|
4
|
+
@name, @target_keys, @opts, @block = name, target_keys, opts, block
|
5
|
+
end
|
6
|
+
|
7
|
+
def call(values)
|
8
|
+
values = values.values_at(*target_keys)
|
9
|
+
Dry::Monads::Maybe(block).fmap {|block| values = block.call(values)}
|
10
|
+
Dry::Monads::Maybe(opts[:type]).fmap {|type| values = type.call(values)}
|
11
|
+
raise ArgumentError, "The result of modifier block is not an enum" unless values.respond_to? :each
|
12
|
+
values
|
13
|
+
end
|
14
|
+
|
15
|
+
def match_schema?(attrs)
|
16
|
+
(attrs.keys & target_keys).any?
|
17
|
+
end
|
18
|
+
|
19
|
+
attr_reader :target_keys, :block, :opts, :name
|
20
|
+
end
|
21
|
+
end
|
data/lib/massager/version.rb
CHANGED
data/lib/massager.rb
CHANGED
@@ -3,52 +3,60 @@ require "dry-types"
|
|
3
3
|
require "dry-monads"
|
4
4
|
require "dry-container"
|
5
5
|
|
6
|
+
require "massager/attributes/attribute"
|
7
|
+
require "massager/attributes/enum_attribute"
|
6
8
|
|
7
9
|
module Massager
|
8
10
|
module ClassMethods
|
9
|
-
def
|
11
|
+
def attribute(name, *target_keys, **opts, &block)
|
10
12
|
set_container
|
11
|
-
|
12
|
-
|
13
|
-
|
13
|
+
register_attribute(
|
14
|
+
Attribute.new(name: name, target_keys: target_keys, opts: opts, block: block)
|
15
|
+
)
|
16
|
+
define_setter(name)
|
17
|
+
define_getter(name)
|
18
|
+
end
|
19
|
+
|
20
|
+
def enum_attribute(name, *target_keys, **opts, &block)
|
21
|
+
set_container
|
22
|
+
register_attribute(
|
23
|
+
EnumAttribute.new(name: name, target_keys: target_keys, opts: opts, block: block)
|
24
|
+
)
|
25
|
+
define_setter(name)
|
26
|
+
define_getter(name)
|
14
27
|
end
|
15
28
|
|
16
29
|
def build(attrs)
|
17
|
-
instance =
|
18
|
-
|
19
|
-
|
20
|
-
instance.
|
30
|
+
instance = new
|
31
|
+
container.each_key do |k|
|
32
|
+
attribute = container.resolve(k)
|
33
|
+
instance.public_send("#{k}=", attrs) if attribute.match_schema?(attrs)
|
21
34
|
end
|
22
35
|
instance
|
23
36
|
end
|
24
37
|
|
25
38
|
private
|
26
39
|
|
27
|
-
def
|
28
|
-
|
29
|
-
@container ||= Dry::Container.new
|
30
|
-
end
|
40
|
+
def register_attribute(attribute)
|
41
|
+
container.register(attribute.name) {attribute}
|
31
42
|
end
|
32
43
|
|
33
|
-
def define_setter(
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
container[:type].fmap {|v| val = v[val]}
|
38
|
-
instance_variable_set(:"@#{container[:name]}", val)
|
44
|
+
def define_setter(name)
|
45
|
+
define_method "#{name}=", Proc.new {|values|
|
46
|
+
attribute = self.class.container.resolve(name)
|
47
|
+
instance_variable_set(:"@#{name}", attribute.call(values))
|
39
48
|
}
|
40
49
|
end
|
41
50
|
|
42
|
-
def define_getter(
|
43
|
-
|
44
|
-
|
45
|
-
instance_variable_get(:"@#{container[:name]}")
|
51
|
+
def define_getter(name)
|
52
|
+
define_method name, Proc.new {
|
53
|
+
instance_variable_get(:"@#{name}")
|
46
54
|
}
|
47
55
|
end
|
48
56
|
|
49
|
-
def
|
50
|
-
|
51
|
-
|
57
|
+
def set_container
|
58
|
+
self.define_singleton_method(:container) do
|
59
|
+
@container ||= Dry::Container.new
|
52
60
|
end
|
53
61
|
end
|
54
62
|
end
|
@@ -57,4 +65,3 @@ module Massager
|
|
57
65
|
base.extend(ClassMethods)
|
58
66
|
end
|
59
67
|
end
|
60
|
-
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: massager
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.2.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Janis Miezitis
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2016-09-
|
11
|
+
date: 2016-09-16 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: dry-types
|
@@ -99,6 +99,8 @@ files:
|
|
99
99
|
- bin/console
|
100
100
|
- bin/setup
|
101
101
|
- lib/massager.rb
|
102
|
+
- lib/massager/attributes/attribute.rb
|
103
|
+
- lib/massager/attributes/enum_attribute.rb
|
102
104
|
- lib/massager/version.rb
|
103
105
|
- massager.gemspec
|
104
106
|
homepage: http://github.com/janjiss/massager
|