ciesta 0.3.2 → 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/.rubocop.yml +3 -0
- data/Gemfile.lock +2 -1
- data/README.md +14 -47
- data/ciesta.gemspec +1 -0
- data/lib/ciesta.rb +0 -1
- data/lib/ciesta/class_methods.rb +7 -15
- data/lib/ciesta/errors.rb +0 -9
- data/lib/ciesta/field.rb +2 -12
- data/lib/ciesta/field_list.rb +14 -11
- data/lib/ciesta/instance_methods.rb +7 -51
- data/lib/ciesta/version.rb +1 -1
- metadata +16 -3
- data/lib/ciesta/syncer.rb +0 -65
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 5edecb23ff1a41bdee5b20058e2a3f89688cb84c4c75d5bca1dd588388cfccbf
|
4
|
+
data.tar.gz: 2e31ce2197aee8f2289026a1589c838c31eeb589d0f223ccb55a4801b19eaea1
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: cf6686bed0df0f9cc26e5c0f7447e636603e6ceb0802fe7f36e40906850b702bab4514265e5e5f642ae712ee375d8336788af1fd4413b9379d822ee275001f4d
|
7
|
+
data.tar.gz: e33e92164712e7720c6842b52d7064bfe232608b78ed44bb50e29674e64261260ab9aa0d5ef009593db38096430b0c2a2cd8e0b77dd5dd958699fbc4bf964258
|
data/.rubocop.yml
CHANGED
data/Gemfile.lock
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
PATH
|
2
2
|
remote: .
|
3
3
|
specs:
|
4
|
-
ciesta (0.
|
4
|
+
ciesta (0.4.0)
|
5
5
|
dry-types (~> 0.13)
|
6
6
|
dry-validation (~> 0.12)
|
7
7
|
|
@@ -102,6 +102,7 @@ DEPENDENCIES
|
|
102
102
|
rake (~> 10.5)
|
103
103
|
rspec (~> 3.8)
|
104
104
|
rubocop (~> 0.59)
|
105
|
+
simplecov (~> 0.16)
|
105
106
|
|
106
107
|
BUNDLED WITH
|
107
108
|
1.16.3
|
data/README.md
CHANGED
@@ -10,18 +10,17 @@ Supported Ruby 2.2.0+
|
|
10
10
|
|
11
11
|
You should keep it in mind that here uses [dry-validation](https://github.com/dry-rb/dry-validation) and [dry-types](https://github.com/dry-rb/dry-types) for validation and typification respectively.
|
12
12
|
|
13
|
-
- [
|
14
|
-
- [
|
15
|
-
- [
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
- [Virtual field](#virtual-field)
|
13
|
+
- [Ciesta](#ciesta)
|
14
|
+
- [Installation](#installation)
|
15
|
+
- [Usage](#usage)
|
16
|
+
- [Basic case](#basic-case)
|
17
|
+
- [Validation](#validation)
|
18
|
+
- [Advanced field declaration](#advanced-field-declaration)
|
19
|
+
- [Types](#types)
|
20
|
+
- [Default value](#default-value)
|
22
21
|
- [Values mass update](#values-mass-update)
|
23
|
-
- [Contributing](#contributing)
|
24
|
-
- [License](#license)
|
22
|
+
- [Contributing](#contributing)
|
23
|
+
- [License](#license)
|
25
24
|
|
26
25
|
## Installation
|
27
26
|
|
@@ -43,12 +42,10 @@ Or install it yourself as:
|
|
43
42
|
## Usage
|
44
43
|
|
45
44
|
### Basic case
|
46
|
-
For example will be used
|
45
|
+
For example will be used a hash with `name` and `age` attributes:
|
47
46
|
|
48
47
|
```ruby
|
49
|
-
|
50
|
-
|
51
|
-
user = User.new(nil, nil)
|
48
|
+
user = Hash[name: nil, age: nil]
|
52
49
|
```
|
53
50
|
|
54
51
|
For setting and syncing new values let's create a form object:
|
@@ -71,22 +68,8 @@ form = Form.new(user)
|
|
71
68
|
```ruby
|
72
69
|
form.name = "John"
|
73
70
|
form.age = "33"
|
74
|
-
form.sync!
|
75
|
-
|
76
|
-
user.name # => "John"
|
77
|
-
user.age # => 33
|
78
71
|
```
|
79
72
|
|
80
|
-
### Syncing
|
81
|
-
You can pass a block to sync method to do some stuff with object after syncing.
|
82
|
-
|
83
|
-
```ruby
|
84
|
-
form.sync! do |user|
|
85
|
-
user.make_happy!
|
86
|
-
end
|
87
|
-
```
|
88
|
-
Both `sync` and `sync!` provide this DSL.
|
89
|
-
|
90
73
|
### Validation
|
91
74
|
For validating incoming values you can use `validate` method:
|
92
75
|
|
@@ -111,13 +94,10 @@ An attempt to sync with invalid form will raise `Ciesta::FormNotValid` error.
|
|
111
94
|
```ruby
|
112
95
|
form.age = 15
|
113
96
|
form.valid? # => false
|
114
|
-
form.sync! # => raises Ciesta::FormNotValid
|
115
97
|
form.errors # => { age: ["must be greater than 18"] }
|
116
98
|
...
|
117
99
|
form.age = 42
|
118
|
-
form.
|
119
|
-
|
120
|
-
user.age # => 42
|
100
|
+
form.valid? # => true
|
121
101
|
```
|
122
102
|
|
123
103
|
### Advanced field declaration
|
@@ -159,25 +139,11 @@ field :age, default: -> { default_age }
|
|
159
139
|
form.age # => 42
|
160
140
|
```
|
161
141
|
|
162
|
-
### Virtual field
|
163
|
-
You can declare field as "virtual". It means that when you call `sync!` it will not raise an error "model attribute is not defined".
|
164
|
-
|
165
|
-
```ruby
|
166
|
-
User = Struct.new(:name)
|
167
|
-
...
|
168
|
-
field :age, virtual: true
|
169
|
-
...
|
170
|
-
form.age = "42"
|
171
|
-
form.age # => 42
|
172
|
-
form.sync! # => true
|
173
|
-
```
|
174
|
-
|
175
142
|
## Values mass update
|
176
143
|
There are two methods for form fields mass update: `assign` and `assign!`.
|
177
144
|
|
178
145
|
```ruby
|
179
146
|
form.assign!(name: "Neo", age: 30)
|
180
|
-
form.sync!
|
181
147
|
...
|
182
148
|
user.name # => "Neo"
|
183
149
|
user.age # => 30
|
@@ -185,6 +151,7 @@ user.age # => 30
|
|
185
151
|
|
186
152
|
`assign!` method will raise `Ciesta::FieldNotDefined` error if one of the passed attributes is not declared in the form.
|
187
153
|
|
154
|
+
|
188
155
|
## Contributing
|
189
156
|
|
190
157
|
Bug reports and pull requests are welcome on GitHub at [https://github.com/nulldef/ciesta](https://github.com/nulldef/ciesta).
|
data/ciesta.gemspec
CHANGED
data/lib/ciesta.rb
CHANGED
data/lib/ciesta/class_methods.rb
CHANGED
@@ -2,14 +2,6 @@ module Ciesta
|
|
2
2
|
module ClassMethods
|
3
3
|
extend self
|
4
4
|
|
5
|
-
def form_from(**hash)
|
6
|
-
form = new
|
7
|
-
hash.each do |(k, v)|
|
8
|
-
form.public_send("#{k}=", v) if form.respond_to?("#{k}=")
|
9
|
-
end
|
10
|
-
form
|
11
|
-
end
|
12
|
-
|
13
5
|
# Declare new form field
|
14
6
|
#
|
15
7
|
# @param [Symbol] name Field name
|
@@ -17,14 +9,14 @@ module Ciesta
|
|
17
9
|
# @option (see Ciesta::Field)
|
18
10
|
def field(name, **options)
|
19
11
|
name = name.to_sym
|
20
|
-
|
12
|
+
definitions[name] = options
|
21
13
|
proxy.instance_eval do
|
22
|
-
define_method(name) {
|
23
|
-
define_method("#{name}=") { |value|
|
14
|
+
define_method(name) { fields[name] }
|
15
|
+
define_method("#{name}=") { |value| fields[name] = value }
|
24
16
|
end
|
25
17
|
end
|
26
18
|
|
27
|
-
# Declare rules for
|
19
|
+
# Declare rules for validation
|
28
20
|
#
|
29
21
|
# @param [Block] block Block with validation rules
|
30
22
|
# @see http://dry-rb.org/gems/dry-validation
|
@@ -32,12 +24,12 @@ module Ciesta
|
|
32
24
|
validator.use(&block)
|
33
25
|
end
|
34
26
|
|
35
|
-
# Returns
|
27
|
+
# Returns fields definitions
|
36
28
|
#
|
37
29
|
# @api private
|
38
30
|
# @return [Ciesta::FieldList]
|
39
|
-
def
|
40
|
-
@
|
31
|
+
def definitions
|
32
|
+
@definitions ||= {}
|
41
33
|
end
|
42
34
|
|
43
35
|
# Returns form validator
|
data/lib/ciesta/errors.rb
CHANGED
@@ -4,15 +4,6 @@ module Ciesta
|
|
4
4
|
# Error for violating constraints
|
5
5
|
ViolatesConstraints = Class.new(ArgumentError)
|
6
6
|
|
7
|
-
# Error for invalid object
|
8
|
-
FormNotValid = Class.new(StandardError)
|
9
|
-
|
10
7
|
# Error for missing field definition
|
11
8
|
FieldNotDefined = Class.new(NoMethodError)
|
12
|
-
|
13
|
-
# Error for missing method of model
|
14
|
-
AttributeNotDefined = Class.new(NoMethodError)
|
15
|
-
|
16
|
-
# Error for nil object
|
17
|
-
ModelNotPresent = Class.new(StandardError)
|
18
9
|
end
|
data/lib/ciesta/field.rb
CHANGED
@@ -16,11 +16,10 @@ class Ciesta::Field
|
|
16
16
|
# @param [Hash] options Field's options
|
17
17
|
# @option [Ciesta::Types::Definition] :type Type of value stored in this field
|
18
18
|
# @option [Proc, Lambda, any] :default Default value for this field
|
19
|
-
def initialize(name, options)
|
19
|
+
def initialize(name, **options)
|
20
20
|
@name = name.to_sym
|
21
21
|
@type = options.delete(:type) || DEFAULT_TYPE
|
22
22
|
@default = options.delete(:default)
|
23
|
-
@virtual = options.delete(:virtual) || false
|
24
23
|
end
|
25
24
|
|
26
25
|
# Sets a new value for field
|
@@ -32,7 +31,7 @@ class Ciesta::Field
|
|
32
31
|
@value = type[val]
|
33
32
|
@was_set = true
|
34
33
|
rescue Dry::Types::ConstraintError
|
35
|
-
raise Ciesta::ViolatesConstraints, "#{val} is not a #{type.name}"
|
34
|
+
raise Ciesta::ViolatesConstraints, "#{val} is not a valid #{name} (#{type.name})"
|
36
35
|
end
|
37
36
|
|
38
37
|
# Returns current value
|
@@ -52,15 +51,6 @@ class Ciesta::Field
|
|
52
51
|
@binding = obj
|
53
52
|
end
|
54
53
|
|
55
|
-
# Returns true if field is virtual
|
56
|
-
#
|
57
|
-
# @api private
|
58
|
-
#
|
59
|
-
# @return [Boolean]
|
60
|
-
def virtual?
|
61
|
-
@virtual
|
62
|
-
end
|
63
|
-
|
64
54
|
# Clear field
|
65
55
|
def clear!
|
66
56
|
@value = nil
|
data/lib/ciesta/field_list.rb
CHANGED
@@ -4,6 +4,18 @@
|
|
4
4
|
#
|
5
5
|
# @attr_reader [Hash<Symbol, Ciesta::Field>] list Field list
|
6
6
|
class Ciesta::FieldList
|
7
|
+
# Define a new field list
|
8
|
+
#
|
9
|
+
# @api private
|
10
|
+
# @param [Hash] definitions Hash of fields definitions
|
11
|
+
#
|
12
|
+
# @return Ciesta::FieldList
|
13
|
+
def self.define(definitions)
|
14
|
+
definitions.each_with_object(new) do |(name, options), list|
|
15
|
+
list << Ciesta::Field.new(name, options)
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
7
19
|
# Constructor
|
8
20
|
def initialize
|
9
21
|
@list = {}
|
@@ -44,7 +56,6 @@ class Ciesta::FieldList
|
|
44
56
|
# @return [Boolean]
|
45
57
|
def assign!(attributes)
|
46
58
|
attributes.each { |name, value| self[name] = value }
|
47
|
-
true
|
48
59
|
rescue NoMethodError => e
|
49
60
|
raise Ciesta::FieldNotDefined, "Field #{e.name} is not specified"
|
50
61
|
end
|
@@ -58,8 +69,8 @@ class Ciesta::FieldList
|
|
58
69
|
attributes = attributes.keep_if { |key| keys.include?(key) }
|
59
70
|
begin
|
60
71
|
assign!(attributes)
|
61
|
-
rescue
|
62
|
-
|
72
|
+
rescue Ciesta::FieldNotDefined # rubocop:disable Lint/HandleExceptions
|
73
|
+
# do nothing
|
63
74
|
end
|
64
75
|
end
|
65
76
|
|
@@ -79,14 +90,6 @@ class Ciesta::FieldList
|
|
79
90
|
list.values.map { |field| [field.name, field.value] }.to_h
|
80
91
|
end
|
81
92
|
|
82
|
-
# Iterate over all fields
|
83
|
-
#
|
84
|
-
# @api private
|
85
|
-
# @param [Block] block Block to iterate
|
86
|
-
def each
|
87
|
-
list.each_value { |field| yield(field) }
|
88
|
-
end
|
89
|
-
|
90
93
|
# Clear all fields
|
91
94
|
#
|
92
95
|
# @api private
|
@@ -12,27 +12,14 @@ module Ciesta
|
|
12
12
|
# @see Ciesta::Validator
|
13
13
|
def_delegators :validator, :errors
|
14
14
|
|
15
|
-
|
16
|
-
# @!method sync!
|
17
|
-
# @see Ciesta::Syncer
|
18
|
-
def_delegators :syncer, :sync
|
19
|
-
|
20
|
-
attr_accessor :object
|
15
|
+
attr_reader :fields
|
21
16
|
|
22
17
|
# Constructor
|
23
18
|
#
|
24
|
-
# @param [
|
25
|
-
def initialize(
|
26
|
-
@
|
27
|
-
|
28
|
-
|
29
|
-
return if object.nil?
|
30
|
-
|
31
|
-
values = fields.keys.each_with_object({}) do |key, mem|
|
32
|
-
mem[key] = object.public_send(key) if object.respond_to?(key)
|
33
|
-
end
|
34
|
-
|
35
|
-
assign(values)
|
19
|
+
# @param [Hash] values Hash with values
|
20
|
+
def initialize(values = {})
|
21
|
+
@fields = Ciesta::FieldList.define(self.class.definitions)
|
22
|
+
assign(values || {})
|
36
23
|
end
|
37
24
|
|
38
25
|
# Checks if form is valid
|
@@ -40,36 +27,13 @@ module Ciesta
|
|
40
27
|
# @param [Hash] params Attrubutes to assign before validation
|
41
28
|
#
|
42
29
|
# @return [Boolean]
|
43
|
-
def valid?(
|
44
|
-
assign(
|
30
|
+
def valid?(values = {})
|
31
|
+
assign(values) unless values.empty?
|
45
32
|
validator.valid?(attributes)
|
46
33
|
end
|
47
34
|
|
48
|
-
# Sync form attributes to object
|
49
|
-
#
|
50
|
-
# @see Ciesta::Syncer
|
51
|
-
#
|
52
|
-
# @param [Block] block Block wich will be yielded after synfing
|
53
|
-
#
|
54
|
-
# @raise Ciesta::ModelNotPresent
|
55
|
-
# @raise Ciesta::FormNotValid
|
56
|
-
# @return [Boolean]
|
57
|
-
def sync!(&block)
|
58
|
-
raise Ciesta::FormNotValid, "Form is not valid" unless valid?
|
59
|
-
|
60
|
-
syncer.sync!(&block)
|
61
|
-
end
|
62
|
-
|
63
35
|
private
|
64
36
|
|
65
|
-
# Sync class for form
|
66
|
-
#
|
67
|
-
# @api private
|
68
|
-
# @return [Ciesta::Syncer]
|
69
|
-
def syncer
|
70
|
-
@syncer ||= Ciesta::Syncer.new(object, fields)
|
71
|
-
end
|
72
|
-
|
73
37
|
# Returns form validator
|
74
38
|
#
|
75
39
|
# @api private
|
@@ -77,13 +41,5 @@ module Ciesta
|
|
77
41
|
def validator
|
78
42
|
self.class.validator
|
79
43
|
end
|
80
|
-
|
81
|
-
# Returns field list
|
82
|
-
#
|
83
|
-
# @api private
|
84
|
-
# @see Ciesta::Form.fields
|
85
|
-
def fields
|
86
|
-
self.class.fields
|
87
|
-
end
|
88
44
|
end
|
89
45
|
end
|
data/lib/ciesta/version.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: ciesta
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.4.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Alexey
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2018-10-
|
11
|
+
date: 2018-10-13 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: dry-types
|
@@ -122,6 +122,20 @@ dependencies:
|
|
122
122
|
- - "~>"
|
123
123
|
- !ruby/object:Gem::Version
|
124
124
|
version: '0.59'
|
125
|
+
- !ruby/object:Gem::Dependency
|
126
|
+
name: simplecov
|
127
|
+
requirement: !ruby/object:Gem::Requirement
|
128
|
+
requirements:
|
129
|
+
- - "~>"
|
130
|
+
- !ruby/object:Gem::Version
|
131
|
+
version: '0.16'
|
132
|
+
type: :development
|
133
|
+
prerelease: false
|
134
|
+
version_requirements: !ruby/object:Gem::Requirement
|
135
|
+
requirements:
|
136
|
+
- - "~>"
|
137
|
+
- !ruby/object:Gem::Version
|
138
|
+
version: '0.16'
|
125
139
|
description: Gem for creating and using form object
|
126
140
|
email:
|
127
141
|
- nulldefiner@gmail.com
|
@@ -151,7 +165,6 @@ files:
|
|
151
165
|
- lib/ciesta/field.rb
|
152
166
|
- lib/ciesta/field_list.rb
|
153
167
|
- lib/ciesta/instance_methods.rb
|
154
|
-
- lib/ciesta/syncer.rb
|
155
168
|
- lib/ciesta/types.rb
|
156
169
|
- lib/ciesta/validator.rb
|
157
170
|
- lib/ciesta/version.rb
|
data/lib/ciesta/syncer.rb
DELETED
@@ -1,65 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
# Class for syncing fields and object
|
4
|
-
#
|
5
|
-
# @attr_reader [Object] object Form objecy
|
6
|
-
# @attr_reader [Ciesta::FieldList] fields Field list
|
7
|
-
class Ciesta::Syncer
|
8
|
-
# Constructor
|
9
|
-
#
|
10
|
-
# @api private
|
11
|
-
# @param [Object] object Form object
|
12
|
-
# @param [Ciesta::FieldList] fields Field list
|
13
|
-
def initialize(object, fields)
|
14
|
-
@object = object
|
15
|
-
@fields = fields
|
16
|
-
end
|
17
|
-
|
18
|
-
# Sync attributes with object
|
19
|
-
#
|
20
|
-
# @param [Block] block Block which will be yielded after syncing
|
21
|
-
#
|
22
|
-
# @return [Booelan]
|
23
|
-
def sync
|
24
|
-
return if object.nil?
|
25
|
-
|
26
|
-
fields.each do |field|
|
27
|
-
begin
|
28
|
-
save_to_object(field)
|
29
|
-
rescue StandardError
|
30
|
-
nil
|
31
|
-
end
|
32
|
-
end
|
33
|
-
|
34
|
-
yield(object) if block_given?
|
35
|
-
|
36
|
-
true
|
37
|
-
end
|
38
|
-
|
39
|
-
# Sync attributes with object
|
40
|
-
#
|
41
|
-
# @param [Block] block Block which will be yielded after syncing
|
42
|
-
#
|
43
|
-
# @raise Ciesta::ModelNotPresent
|
44
|
-
# @raise Ciesta::AttributeNotDefined
|
45
|
-
# @return [Booelan]
|
46
|
-
def sync!
|
47
|
-
raise Ciesta::ModelNotPresent, "Cannot sync without model" if object.nil?
|
48
|
-
|
49
|
-
fields.each { |field| save_to_object(field) }
|
50
|
-
|
51
|
-
yield(object) if block_given?
|
52
|
-
|
53
|
-
true
|
54
|
-
end
|
55
|
-
|
56
|
-
private
|
57
|
-
|
58
|
-
attr_reader :object, :fields
|
59
|
-
|
60
|
-
def save_to_object(field)
|
61
|
-
object.send("#{field.name}=", field.value) unless field.virtual?
|
62
|
-
rescue NoMethodError
|
63
|
-
raise Ciesta::AttributeNotDefined, "Attribute #{field.name} is not defined on model"
|
64
|
-
end
|
65
|
-
end
|