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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 2c546a423a524c000586945f454df552aad095cc9cf83c9f5a5a1f632c270a44
4
- data.tar.gz: 2a8699af62652d17dc4f0705136855e827a1273488c873022c3057621058abfe
3
+ metadata.gz: 5edecb23ff1a41bdee5b20058e2a3f89688cb84c4c75d5bca1dd588388cfccbf
4
+ data.tar.gz: 2e31ce2197aee8f2289026a1589c838c31eeb589d0f223ccb55a4801b19eaea1
5
5
  SHA512:
6
- metadata.gz: 45f65ccdfbc46528f966fe48ccb799c1232bf67e00db3572569788b3560cd8b59c7d0154578c76bd71d234e38498025e13187af6d0a89ba8a7a236e794f72ef7
7
- data.tar.gz: f8274e3f6e55fb7774634ea3ac47ed84514f3bcc50093220559192e4e52458bf7398e245824d0519577010ad393f2f10fa23eb4e40d18e770eb08003eae8141b
6
+ metadata.gz: cf6686bed0df0f9cc26e5c0f7447e636603e6ceb0802fe7f36e40906850b702bab4514265e5e5f642ae712ee375d8336788af1fd4413b9379d822ee275001f4d
7
+ data.tar.gz: e33e92164712e7720c6842b52d7064bfe232608b78ed44bb50e29674e64261260ab9aa0d5ef009593db38096430b0c2a2cd8e0b77dd5dd958699fbc4bf964258
@@ -34,5 +34,8 @@ Style/ModuleFunction:
34
34
  Lint/AmbiguousOperator:
35
35
  Enabled: false
36
36
 
37
+ Layout/IndentArray:
38
+ EnforcedStyle: consistent
39
+
37
40
  Lint/AmbiguousBlockAssociation:
38
41
  Enabled: false
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- ciesta (0.3.2)
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
- - [Installation](#installation)
14
- - [Usage](#usage)
15
- - [Basic case](#basic-case)
16
- - [Syncing](#syncing)
17
- - [Validation](#validation)
18
- - [Advanced field declaration](#advanced-field-declaration)
19
- - [Types](#types)
20
- - [Default value](#default-value)
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 user object with `name` and `age` attributes:
45
+ For example will be used a hash with `name` and `age` attributes:
47
46
 
48
47
  ```ruby
49
- User = Struct.new(:name, :age)
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.sync! # => true
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).
@@ -38,4 +38,5 @@ Gem::Specification.new do |spec|
38
38
  spec.add_development_dependency "rake", "~> 10.5"
39
39
  spec.add_development_dependency "rspec", "~> 3.8"
40
40
  spec.add_development_dependency "rubocop", "~> 0.59"
41
+ spec.add_development_dependency "simplecov", "~> 0.16"
41
42
  end
@@ -5,7 +5,6 @@ require "dry-types"
5
5
  require "dry-validation"
6
6
  require "ciesta/version"
7
7
  require "ciesta/field_list"
8
- require "ciesta/syncer"
9
8
  require "ciesta/types"
10
9
  require "ciesta/validator"
11
10
  require "ciesta/errors"
@@ -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
- fields << Ciesta::Field.new(name, options)
12
+ definitions[name] = options
21
13
  proxy.instance_eval do
22
- define_method(name) { self.class.fields[name] }
23
- define_method("#{name}=") { |value| self.class.fields[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 valudation
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 field list
27
+ # Returns fields definitions
36
28
  #
37
29
  # @api private
38
30
  # @return [Ciesta::FieldList]
39
- def fields
40
- @fields ||= Ciesta::FieldList.new
31
+ def definitions
32
+ @definitions ||= {}
41
33
  end
42
34
 
43
35
  # Returns form validator
@@ -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
@@ -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
@@ -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 StandardError
62
- false
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
- # @!method sync
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 [Object] object Object wich will be updated though this form
25
- def initialize(object = nil)
26
- @object = object
27
- clear!
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?(params = nil)
44
- assign(params) if params
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
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Ciesta
4
- VERSION = "0.3.2".freeze
4
+ VERSION = "0.4.0".freeze
5
5
  end
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.3.2
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 00:00:00.000000000 Z
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
@@ -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