mini_form 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 6d427b889425b8c2acd15827c88bc61430a70652
4
+ data.tar.gz: 582b6cf7164ab75b6f4df2f306eeb5580d9a0f3c
5
+ SHA512:
6
+ metadata.gz: 9e0f762fd07558b4c30386d9cd2a9a51b8855efb0279bb70b7f842d0e3748d7a413a0f449a31eb1d448e8b93c649930b3b90dbbb9ece8a4151ae013dd0f4d096
7
+ data.tar.gz: d23461cd996d47cbbdfe7efd5219aed986a72e83c5693e6d1e413927fa947786c200bd1e6bb1cd227573af8f4b1a8c9be7d89926111b4fc3bbd8fbd5efeec448
@@ -0,0 +1,17 @@
1
+ *.gem
2
+ *.rbc
3
+ .bundle
4
+ .config
5
+ .yardoc
6
+ Gemfile.lock
7
+ InstalledFiles
8
+ _yardoc
9
+ coverage
10
+ doc/
11
+ lib/bundler/man
12
+ pkg
13
+ rdoc
14
+ spec/reports
15
+ test/tmp
16
+ test/version_tmp
17
+ tmp
data/.rspec ADDED
@@ -0,0 +1,2 @@
1
+ --colour
2
+ --format=documentation
@@ -0,0 +1,24 @@
1
+ require: rubocop-rspec
2
+
3
+ AllCops:
4
+ RunRailsCops: true
5
+ Exclude:
6
+ - example/db/**/*
7
+ - example/config/**/*
8
+ - search_object.gemspec
9
+
10
+ # Disables "Line is too long"
11
+ LineLength:
12
+ Enabled: false
13
+
14
+ # Disables "Missing top-level class documentation comment"
15
+ Documentation:
16
+ Enabled: false
17
+
18
+ # Disables "Use each_with_object instead of inject"
19
+ Style/EachWithObject:
20
+ Enabled: false
21
+
22
+ # Disables "Prefer reduce over inject."
23
+ Style/CollectionMethods:
24
+ Enabled: false
@@ -0,0 +1,10 @@
1
+ language: ruby
2
+ rvm:
3
+ - 2.0
4
+ - 2.1
5
+ - 2.2
6
+ script:
7
+ - bundle exec rubocop
8
+ - bundle exec rspec spec
9
+ notifications:
10
+ email: false
@@ -0,0 +1,5 @@
1
+ # Changelog
2
+
3
+ ## Version 0.1.0
4
+
5
+ * Initial release
data/Gemfile ADDED
@@ -0,0 +1,3 @@
1
+ source 'https://rubygems.org'
2
+
3
+ gemspec
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2013-2015 Radoslav Stankov
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,261 @@
1
+ [![Gem Version](https://badge.fury.io/rb/mini_form.png)](http://badge.fury.io/rb/mini_form)
2
+ [![Code Climate](https://codeclimate.com/github/RStankov/MiniForm.png)](https://codeclimate.com/github/RStankov/MiniForm)
3
+ [![Build Status](https://secure.travis-ci.org/RStankov/MiniForm.png)](http://travis-ci.org/RStankov/MiniForm)
4
+ [![Code coverage](https://coveralls.io/repos/RStankov/MiniForm/badge.png?branch=master)](https://coveralls.io/r/RStankov/MiniForm)
5
+
6
+ # MiniForm
7
+
8
+ Helpers for dealing with form objects and nested forms.
9
+
10
+ ## Installation
11
+
12
+ Add this line to your application's Gemfile:
13
+
14
+ ```ruby
15
+ gem 'mini_form'
16
+ ```
17
+
18
+ And then execute:
19
+
20
+ $ bundle
21
+
22
+ Or install it yourself as:
23
+
24
+ $ gem install mini_form
25
+
26
+ ## Usage
27
+
28
+ ```ruby
29
+ class ProductForm
30
+ include MiniForm::Model
31
+
32
+ attributes :id, :name, :price, :description
33
+
34
+ validates :name, :price, :description, presence: true
35
+
36
+ # called after successful validations in update
37
+ def perform
38
+ @id = ExternalService.create(attributes)
39
+ end
40
+ end
41
+ ```
42
+
43
+ ```ruby
44
+ class ProductsController < ApplicationController
45
+ def create
46
+ @product = ProductForm.new
47
+
48
+ if @product.update(product_params)
49
+ redirect_to product_path(product.id)
50
+ else
51
+ render :edit
52
+ end
53
+ end
54
+
55
+ private
56
+
57
+ def product_params
58
+ params.require(:product).permit(:name, :price, :description)
59
+ end
60
+ end
61
+ ```
62
+
63
+ ### Delegated attributes
64
+
65
+ Attributes can be delegated to a sub object.
66
+
67
+ ```ruby
68
+ class SignUpForm
69
+ include MiniForm::Model
70
+
71
+ attr_reader :account, :user
72
+
73
+ attributes :name, :email, delegate: :user
74
+ attributes :company_name, :plan, delegate: :account
75
+
76
+ validates :name, :email, :company_name, :plan, presence: true
77
+
78
+ def initialize
79
+ @account = Account.new
80
+ @user = User.new account: @account
81
+ end
82
+
83
+ def perform
84
+ user.save!
85
+ account.save!
86
+ end
87
+ end
88
+ ```
89
+
90
+ ```ruby
91
+ form = SignUpForm.new
92
+ form.name = 'name' # => form.user.name = 'name'
93
+ form.name # => form.user.name
94
+ form.plan = 'free' # => form.account.plan = 'free'
95
+ form.plan # => form.account.plan
96
+ ```
97
+
98
+ ### Nested validator
99
+
100
+ `mini_form/nested` validator runs validations on the given model and copies errors to the form object.
101
+
102
+ ```ruby
103
+ class SignUpForm
104
+ include MiniForm::Model
105
+
106
+ attr_reader :account, :user
107
+
108
+ attributes :name, :email, delegate: :user
109
+ attributes :company_name, :plan, delegate: :account
110
+
111
+ validates :account, :user, 'mini_form/nested' => true
112
+
113
+ def initialize
114
+ @account = Account.new
115
+ @user = User.new account: @account
116
+ end
117
+
118
+ def perform
119
+ account.save!
120
+ user.save!
121
+ end
122
+ end
123
+ ```
124
+
125
+ ### Nested models
126
+
127
+ Combines delegated attributes and nested validation into a single call.
128
+
129
+ ```ruby
130
+ class SignUpForm
131
+ include MiniForm::Model
132
+
133
+ modal :user, attributes: %i(name email)
134
+ model :account, attributes: %i(company_name plan)
135
+
136
+ def initialize
137
+ @account = Account.new
138
+ @user = User.new account: @account
139
+ end
140
+
141
+ def perform
142
+ account.save!
143
+ user.save!
144
+ end
145
+ end
146
+ ```
147
+
148
+ ### Auto saving nested models
149
+
150
+ In most of the time `perform` is just calling `save!`.
151
+
152
+ ```ruby
153
+ class SignUpForm
154
+ include MiniForm::Model
155
+
156
+ modal :user, attributes: %i(name email), save: true
157
+ model :account, attributes: %i(company_name plan), save: true
158
+
159
+ def initialize
160
+ @account = Account.new
161
+ @user = User.new account: @account
162
+ end
163
+ end
164
+ ```
165
+
166
+ ### Before/after callbacks
167
+
168
+ ```ruby
169
+ class SignUpForm
170
+ include MiniForm::Model
171
+
172
+ # ... code
173
+
174
+ before_update :run_before_update
175
+ after_update :run_after_update
176
+
177
+ private
178
+
179
+ def run_before_update
180
+ # ...
181
+ end
182
+
183
+ def run_after_update
184
+ # ...
185
+ end
186
+
187
+ # alternatively you can overwrite "before_update"
188
+ def before_update
189
+ end
190
+
191
+ # alternatively you can overwrite "after_update"
192
+ def after_update
193
+ end
194
+ end
195
+ ```
196
+
197
+ ### Methods
198
+
199
+ <table>
200
+ <tr>
201
+ <th>Method</th>
202
+ <th>Description</th>
203
+ </tr>
204
+ <tr>
205
+ <td>.model</td>
206
+ <td>Defines a sub object for the form</td>
207
+ </tr>
208
+ <tr>
209
+ <td>.attributes</td>
210
+ <td>Defines an attribute, it can delegate to sub object</td>
211
+ </tr>
212
+ <tr>
213
+ <td>#initialize</td>
214
+ <td>Meant to be overwritten. By defaults calls `attributes=`</td>
215
+ </tr>
216
+ <tr>
217
+ <td>#attributes=</td>
218
+ <td>Sets values of all attributes</td>
219
+ </tr>
220
+ <tr>
221
+ <td>#attributes</td>
222
+ <td>Returns all attributes of the form</td>
223
+ </tr>
224
+ <tr>
225
+ <td>#update</td>
226
+ <td>Sets attributes, calls validations, saves models and `perform`</td>
227
+ </tr>
228
+ <tr>
229
+ <td>#update!</td>
230
+ <td>Calls `update`. If validation fails, it raises an error</td>
231
+ </tr>
232
+ <tr>
233
+ <td>#perform</td>
234
+ <td>Meant to be overwritten. Doesn't do anything by default</td>
235
+ </tr>
236
+ <tr>
237
+ <td>#before_update</td>
238
+ <td>Meant to be overwritten.</td>
239
+ </tr>
240
+ <tr>
241
+ <td>#after_update</td>
242
+ <td>Meant to be overwritten.</td>
243
+ </tr>
244
+ <tr>
245
+ <td>#transaction</td>
246
+ <td>If ActiveRecord is available, wraps `perform` in transaction.</td>
247
+ </tr>
248
+ </table>
249
+
250
+ ## Contributing
251
+
252
+ 1. Fork it
253
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
254
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
255
+ 4. Push to the branch (`git push origin my-new-feature`)
256
+ 5. Run the tests (`rake`)
257
+ 6. Create new Pull Request
258
+
259
+ ## License
260
+
261
+ **[MIT License](https://github.com/RStankov/MiniForm/blob/master/LICENSE.txt)**
@@ -0,0 +1,8 @@
1
+ require 'bundler/gem_tasks'
2
+ require 'rspec/core/rake_task'
3
+ require 'rubocop/rake_task'
4
+
5
+ RSpec::Core::RakeTask.new(:spec)
6
+ RuboCop::RakeTask.new(:rubocop)
7
+
8
+ task default: [:rubocop, :spec]
@@ -0,0 +1,7 @@
1
+ require 'mini_form/version'
2
+ require 'mini_form/model'
3
+ require 'mini_form/errors'
4
+ require 'mini_form/nested_validator'
5
+
6
+ module MiniForm
7
+ end
@@ -0,0 +1,4 @@
1
+ module MiniForm
2
+ class InvalidForm < StandardError
3
+ end
4
+ end
@@ -0,0 +1,120 @@
1
+ require 'active_support/all'
2
+ require 'active_model'
3
+
4
+ module MiniForm
5
+ module Model
6
+ def self.included(base)
7
+ base.class_eval do
8
+ include ActiveModel::Validations
9
+ include ActiveModel::Conversion
10
+
11
+ extend ActiveModel::Naming
12
+ extend ActiveModel::Callbacks
13
+
14
+ extend ClassMethods
15
+
16
+ define_model_callbacks :update
17
+
18
+ before_update :before_update
19
+ after_update :after_update
20
+ end
21
+ end
22
+
23
+ def initialize(attributes = {})
24
+ self.attributes = attributes
25
+ end
26
+
27
+ def persisted?
28
+ false
29
+ end
30
+
31
+ def attributes=(attributes)
32
+ attributes.slice(*self.class.attribute_names).each do |name, value|
33
+ public_send "#{name}=", value
34
+ end
35
+ end
36
+
37
+ def attributes
38
+ Hash[self.class.attribute_names.map { |name| [name, public_send(name)] }]
39
+ end
40
+
41
+ def update(attributes = {})
42
+ self.attributes = attributes unless attributes.empty?
43
+
44
+ return false unless valid?
45
+
46
+ run_callbacks :update do
47
+ transaction do
48
+ save_models
49
+ perform
50
+ end
51
+ end
52
+
53
+ true
54
+ end
55
+
56
+ def update!(attributes = {})
57
+ fail InvalidForm unless update attributes
58
+ self
59
+ end
60
+
61
+ private
62
+
63
+ def transaction(&block)
64
+ if defined? ActiveRecord
65
+ ActiveRecord::Base.transaction(&block)
66
+ else
67
+ yield
68
+ end
69
+ end
70
+
71
+ # :api: private
72
+ def save_models
73
+ self.class.models_to_save.each { |model_name| public_send(model_name).save! }
74
+ end
75
+
76
+ def perform
77
+ # noop
78
+ end
79
+
80
+ def before_update
81
+ # noop
82
+ end
83
+
84
+ def after_update
85
+ # noop
86
+ end
87
+
88
+ module ClassMethods
89
+ # :api: private
90
+ def attribute_names
91
+ @attribute_names ||= []
92
+ end
93
+
94
+ # :api: private
95
+ def models_to_save
96
+ @models_to_save ||= []
97
+ end
98
+
99
+ def attributes(*attributes, delegate: nil, prefix: nil, allow_nil: nil)
100
+ attribute_names.push(*attributes)
101
+
102
+ if delegate.nil?
103
+ attr_accessor(*attributes)
104
+ else
105
+ self.delegate(*attributes, to: delegate, prefix: prefix, allow_nil: allow_nil)
106
+ self.delegate(*attributes.map { |attr| "#{attr}=" }, to: delegate, prefix: prefix, allow_nil: allow_nil)
107
+ end
108
+ end
109
+
110
+ def model(name, attributes: [], prefix: nil, allow_nil: nil, save: false)
111
+ attributes(name)
112
+ attributes(*attributes, delegate: name, prefix: prefix, allow_nil: allow_nil) unless attributes.empty?
113
+
114
+ validates name, 'mini_form/nested' => true
115
+
116
+ models_to_save << name if save
117
+ end
118
+ end
119
+ end
120
+ end
@@ -0,0 +1,13 @@
1
+ require 'active_model'
2
+
3
+ module MiniForm
4
+ class NestedValidator < ActiveModel::EachValidator
5
+ def validate_each(record, _, relation)
6
+ return if relation.valid?
7
+
8
+ relation.errors.each do |name, value|
9
+ record.errors.add name, value
10
+ end
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,3 @@
1
+ module MiniForm
2
+ VERSION = '0.1.0'
3
+ end
@@ -0,0 +1,30 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'mini_form/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = 'mini_form'
8
+ spec.version = MiniForm::VERSION
9
+ spec.authors = ['Radoslav Stankov']
10
+ spec.email = ['rstankov@gmail.com']
11
+ spec.description = 'Sugar around ActiveModel::Model'
12
+ spec.summary = 'Easy to use form objects in Rails projects'
13
+ spec.homepage = 'https://github.com/RStankov/MiniForm'
14
+ spec.license = 'MIT'
15
+
16
+ spec.files = `git ls-files`.split($INPUT_RECORD_SEPARATOR)
17
+ spec.executables = spec.files.grep(/^bin\//) { |f| File.basename(f) }
18
+ spec.test_files = spec.files.grep(/^(spec)\//)
19
+ spec.require_paths = ['lib']
20
+
21
+ spec.add_dependency 'activemodel', '~> 4.0'
22
+
23
+ spec.add_development_dependency 'bundler', '~> 1.3'
24
+ spec.add_development_dependency 'rake'
25
+ spec.add_development_dependency 'rspec', '~> 2.14'
26
+ spec.add_development_dependency 'rspec-mocks', '>= 2.12.3'
27
+ spec.add_development_dependency 'coveralls'
28
+ spec.add_development_dependency 'rubocop'
29
+ spec.add_development_dependency 'rubocop-rspec'
30
+ end
@@ -0,0 +1,41 @@
1
+ require 'spec_helper'
2
+
3
+ module MiniForm
4
+ describe NestedValidator do
5
+ class User
6
+ include ActiveModel::Model
7
+
8
+ attr_accessor :name
9
+
10
+ validates :name, presence: true
11
+ end
12
+
13
+ class Record
14
+ include ActiveModel::Validations
15
+
16
+ attr_accessor :user
17
+
18
+ def initialize(user)
19
+ @user = user
20
+ end
21
+ end
22
+
23
+ let(:validator) { NestedValidator.new(attributes: [:user]) }
24
+ let(:user) { User.new }
25
+ let(:record) { Record.new(user) }
26
+
27
+ it 'copies errors from submodel to model' do
28
+ validator.validate(record)
29
+
30
+ expect(record.errors[:name]).not_to be_blank
31
+ end
32
+
33
+ it 'does not copy errors when there are not any' do
34
+ user.name = 'valid name'
35
+
36
+ validator.validate(record)
37
+
38
+ expect(record.errors[:name]).to be_blank
39
+ end
40
+ end
41
+ end
@@ -0,0 +1,238 @@
1
+ require 'spec_helper'
2
+
3
+ module MiniForm
4
+ describe Model do
5
+ let(:user) { User.new name: 'Name' }
6
+
7
+ class User
8
+ include ActiveModel::Model
9
+
10
+ attr_accessor :name
11
+
12
+ validates :name, presence: true
13
+ end
14
+
15
+ Example = Class.new do
16
+ include Model
17
+ attributes :name, :price
18
+ end
19
+
20
+ ExampleWithDelegate = Class.new do
21
+ include Model
22
+
23
+ attr_reader :user
24
+
25
+ attributes :name, delegate: :user
26
+
27
+ def initialize(user)
28
+ @user = user
29
+ end
30
+ end
31
+
32
+ ExampleWithModel = Class.new do
33
+ include Model
34
+
35
+ model :user, attributes: %i(name)
36
+ end
37
+
38
+ describe 'acts as ActiveModel' do
39
+ include ActiveModel::Lint::Tests
40
+
41
+ before do
42
+ @model = Example.new
43
+ end
44
+
45
+ def assert(condition, message = nil)
46
+ expect(condition).to be_truthy, message
47
+ end
48
+
49
+ def assert_kind_of(expected_kind, object, message = nil)
50
+ expect(object).to be_kind_of(expected_kind), message
51
+ end
52
+
53
+ def assert_equal(expected_value, value, message = nil)
54
+ expect(value).to eq(expected_value), message
55
+ end
56
+
57
+ ActiveModel::Lint::Tests.public_instance_methods.map(&:to_s).grep(/^test/).each do |method|
58
+ example(method.gsub('_', ' ')) { send method }
59
+ end
60
+ end
61
+
62
+ describe '.attributes' do
63
+ it 'generates getters' do
64
+ object = Example.new name: 'value'
65
+ expect(object.name).to eq 'value'
66
+ end
67
+
68
+ it 'generates setters' do
69
+ object = Example.new
70
+ object.name = 'value'
71
+
72
+ expect(object.name).to eq 'value'
73
+ end
74
+
75
+ it 'can delegate getter' do
76
+ object = ExampleWithDelegate.new user
77
+ expect(object.name).to eq user.name
78
+ end
79
+
80
+ it 'can delegate setter' do
81
+ object = ExampleWithDelegate.new user
82
+
83
+ object.name = 'New Name'
84
+
85
+ expect(object.name).to eq 'New Name'
86
+ expect(user.name).to eq 'New Name'
87
+ end
88
+ end
89
+
90
+ describe '.model' do
91
+ it 'generates model accessors' do
92
+ object = ExampleWithModel.new user: user
93
+ expect(object.user).to eq user
94
+ end
95
+
96
+ it 'can delegate model attributes' do
97
+ object = ExampleWithModel.new user: user
98
+ expect(object.name).to eq user.name
99
+ end
100
+
101
+ it 'performs nested validation for model' do
102
+ user = User.new
103
+ object = ExampleWithModel.new user: user
104
+
105
+ expect(object).not_to be_valid
106
+ expect(object.errors[:name]).to be_present
107
+ end
108
+ end
109
+
110
+ describe '.attributes_names' do
111
+ it 'returns attribute names' do
112
+ expect(Example.attribute_names).to eq %i(name price)
113
+ end
114
+ end
115
+
116
+ describe '#initialize' do
117
+ it 'can be called with no arguments' do
118
+ expect { Example.new }.not_to raise_error
119
+ end
120
+
121
+ it 'assign the passed attributes' do
122
+ object = Example.new price: '$5'
123
+
124
+ expect(object.price).to eq '$5'
125
+ end
126
+
127
+ it 'ignores invalid attributes' do
128
+ expect { Example.new invalid: 'attribute' }.not_to raise_error
129
+ end
130
+
131
+ it 'handles HashWithIndifferentAccess hashes' do
132
+ hash = ActiveSupport::HashWithIndifferentAccess.new 'price' => '$5'
133
+ object = Example.new hash
134
+
135
+ expect(object.price).to eq '$5'
136
+ end
137
+ end
138
+
139
+ describe '#attributes' do
140
+ it 'returns attributes' do
141
+ object = Example.new name: 'iPhone', price: '$5'
142
+ expect(object.attributes).to eq name: 'iPhone', price: '$5'
143
+ end
144
+ end
145
+
146
+ describe '#update' do
147
+ ExampleForUpdate = Class.new do
148
+ include Model
149
+
150
+ attributes :name
151
+
152
+ validates :name, presence: true
153
+ end
154
+
155
+ ExampleForSave = Class.new do
156
+ include Model
157
+
158
+ model :user, attributes: %i(name), save: true
159
+ end
160
+
161
+ it 'updates attributes' do
162
+ object = ExampleForUpdate.new name: 'value'
163
+
164
+ expect { object.update(name: 'new value') }.to change { object.name }.to 'new value'
165
+ end
166
+
167
+ it 'returns true when validations pass' do
168
+ object = ExampleForUpdate.new name: 'value'
169
+
170
+ expect(object.update).to eq true
171
+ end
172
+
173
+ it 'calls "perfom" method when validation pass' do
174
+ object = ExampleForUpdate.new name: 'value'
175
+
176
+ expect(object).to receive(:perform)
177
+
178
+ object.update
179
+ end
180
+
181
+ it 'calls "save" for the model' do
182
+ object = ExampleForSave.new user: user
183
+
184
+ allow(user).to receive(:save!)
185
+
186
+ object.update
187
+
188
+ expect(user).to have_received(:save!)
189
+ end
190
+
191
+ it 'supports update callbacks' do
192
+ object = ExampleForUpdate.new name: 'value'
193
+
194
+ expect(object).to receive(:before_update)
195
+ expect(object).to receive(:after_update)
196
+
197
+ object.update
198
+ end
199
+
200
+ it 'returns false when validations fail' do
201
+ object = ExampleForUpdate.new name: nil
202
+
203
+ expect(object.update).to eq false
204
+ end
205
+
206
+ it 'does not call "perfom" method when validation fail' do
207
+ object = ExampleForUpdate.new name: nil
208
+
209
+ expect(object).not_to receive(:perform)
210
+
211
+ object.update
212
+ end
213
+ end
214
+
215
+ describe '#update!' do
216
+ it 'returns self' do
217
+ object = Example.new
218
+ expect(object.update!).to eq object
219
+ end
220
+
221
+ it 'calls update with given arguments' do
222
+ object = Example.new
223
+
224
+ expect(object).to receive(:update).with(:attributes).and_return true
225
+
226
+ object.update! :attributes
227
+ end
228
+
229
+ it 'raises error when update fails' do
230
+ object = Example.new
231
+
232
+ allow(object).to receive(:update).and_return false
233
+
234
+ expect { object.update! }.to raise_error InvalidForm
235
+ end
236
+ end
237
+ end
238
+ end
@@ -0,0 +1,12 @@
1
+ require 'bundler/setup'
2
+
3
+ if ENV['TRAVIS']
4
+ require 'coveralls'
5
+ Coveralls.wear!
6
+ end
7
+
8
+ require 'mini_form'
9
+
10
+ RSpec.configure do |config|
11
+ config.expect_with(:rspec) { |c| c.syntax = :expect }
12
+ end
metadata ADDED
@@ -0,0 +1,177 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: mini_form
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Radoslav Stankov
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2015-03-02 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: activemodel
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '4.0'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '4.0'
27
+ - !ruby/object:Gem::Dependency
28
+ name: bundler
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '1.3'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '1.3'
41
+ - !ruby/object:Gem::Dependency
42
+ name: rake
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ">="
46
+ - !ruby/object:Gem::Version
47
+ version: '0'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ">="
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
55
+ - !ruby/object:Gem::Dependency
56
+ name: rspec
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - "~>"
60
+ - !ruby/object:Gem::Version
61
+ version: '2.14'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - "~>"
67
+ - !ruby/object:Gem::Version
68
+ version: '2.14'
69
+ - !ruby/object:Gem::Dependency
70
+ name: rspec-mocks
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - ">="
74
+ - !ruby/object:Gem::Version
75
+ version: 2.12.3
76
+ type: :development
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - ">="
81
+ - !ruby/object:Gem::Version
82
+ version: 2.12.3
83
+ - !ruby/object:Gem::Dependency
84
+ name: coveralls
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - ">="
88
+ - !ruby/object:Gem::Version
89
+ version: '0'
90
+ type: :development
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - ">="
95
+ - !ruby/object:Gem::Version
96
+ version: '0'
97
+ - !ruby/object:Gem::Dependency
98
+ name: rubocop
99
+ requirement: !ruby/object:Gem::Requirement
100
+ requirements:
101
+ - - ">="
102
+ - !ruby/object:Gem::Version
103
+ version: '0'
104
+ type: :development
105
+ prerelease: false
106
+ version_requirements: !ruby/object:Gem::Requirement
107
+ requirements:
108
+ - - ">="
109
+ - !ruby/object:Gem::Version
110
+ version: '0'
111
+ - !ruby/object:Gem::Dependency
112
+ name: rubocop-rspec
113
+ requirement: !ruby/object:Gem::Requirement
114
+ requirements:
115
+ - - ">="
116
+ - !ruby/object:Gem::Version
117
+ version: '0'
118
+ type: :development
119
+ prerelease: false
120
+ version_requirements: !ruby/object:Gem::Requirement
121
+ requirements:
122
+ - - ">="
123
+ - !ruby/object:Gem::Version
124
+ version: '0'
125
+ description: Sugar around ActiveModel::Model
126
+ email:
127
+ - rstankov@gmail.com
128
+ executables: []
129
+ extensions: []
130
+ extra_rdoc_files: []
131
+ files:
132
+ - ".gitignore"
133
+ - ".rspec"
134
+ - ".rubocop.yml"
135
+ - ".travis.yml"
136
+ - CHANGELOG.md
137
+ - Gemfile
138
+ - LICENSE.txt
139
+ - README.md
140
+ - Rakefile
141
+ - lib/mini_form.rb
142
+ - lib/mini_form/errors.rb
143
+ - lib/mini_form/model.rb
144
+ - lib/mini_form/nested_validator.rb
145
+ - lib/mini_form/version.rb
146
+ - mini_form.gemspec
147
+ - spec/mini_form/nested_validator_spec.rb
148
+ - spec/mini_form_spec.rb
149
+ - spec/spec_helper.rb
150
+ homepage: https://github.com/RStankov/MiniForm
151
+ licenses:
152
+ - MIT
153
+ metadata: {}
154
+ post_install_message:
155
+ rdoc_options: []
156
+ require_paths:
157
+ - lib
158
+ required_ruby_version: !ruby/object:Gem::Requirement
159
+ requirements:
160
+ - - ">="
161
+ - !ruby/object:Gem::Version
162
+ version: '0'
163
+ required_rubygems_version: !ruby/object:Gem::Requirement
164
+ requirements:
165
+ - - ">="
166
+ - !ruby/object:Gem::Version
167
+ version: '0'
168
+ requirements: []
169
+ rubyforge_project:
170
+ rubygems_version: 2.4.5
171
+ signing_key:
172
+ specification_version: 4
173
+ summary: Easy to use form objects in Rails projects
174
+ test_files:
175
+ - spec/mini_form/nested_validator_spec.rb
176
+ - spec/mini_form_spec.rb
177
+ - spec/spec_helper.rb