massager 0.1.1 → 0.2.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|