syrup_form_object 0.0.4 → 0.0.5
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.
- data/.travis.yml +4 -0
- data/Gemfile +0 -6
- data/README.md +65 -50
- data/Rakefile +5 -0
- data/lib/syrup/form_object.rb +39 -2
- data/lib/syrup/version.rb +1 -1
- data/spec/lib/syrup/form_object_spec.rb +142 -25
- data/syrup_form_object.gemspec +3 -1
- metadata +38 -4
data/.travis.yml
ADDED
data/Gemfile
CHANGED
data/README.md
CHANGED
@@ -1,76 +1,91 @@
|
|
1
1
|
#Syrup::FormObject
|
2
2
|
|
3
|
+
[][gem]
|
4
|
+
[][travis]
|
5
|
+
|
6
|
+
[gem]: http://badge.fury.io/rb/syrup_form_object
|
7
|
+
[travis]: https://travis-ci.org/alexsiri7/syrup_form_object
|
8
|
+
|
9
|
+
|
3
10
|
This is a simple implementation of the FormObject... pattern?
|
4
11
|
|
5
12
|
##Installation
|
6
|
-
|
7
|
-
|
13
|
+
``` terminal
|
14
|
+
$ gem install syrup_form_object
|
15
|
+
```
|
8
16
|
|
9
17
|
or in the *Gemfile*
|
10
|
-
|
11
|
-
|
18
|
+
``` ruby
|
19
|
+
gem 'syrup_form_object'
|
20
|
+
```
|
12
21
|
|
13
22
|
##Examples
|
14
23
|
|
15
24
|
To update the ```Event``` class in your model
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
25
|
+
``` ruby
|
26
|
+
class Event < ActiveRecord::Base
|
27
|
+
validates :start_date, presence: true
|
28
|
+
validates :end_date, presence: true
|
29
|
+
end
|
30
|
+
```
|
21
31
|
|
22
32
|
You create the follwing form
|
23
33
|
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
end
|
34
|
+
``` ruby
|
35
|
+
class EventCreateForm < Syrup::FormObject
|
36
|
+
has_one :event
|
37
|
+
accepts_nested_attributes_for :event
|
38
|
+
|
39
|
+
attribute :length_of_the_event, Integer
|
40
|
+
validates :length_of_the_event, numericality:{greater_than: 0}
|
41
|
+
|
42
|
+
def save
|
43
|
+
if self.valid?
|
44
|
+
end_date = event.start_date + length_of_the_event.hours
|
45
|
+
event.end_date = end_date
|
46
|
+
event.save
|
47
|
+
else
|
48
|
+
false
|
40
49
|
end
|
50
|
+
end
|
51
|
+
end
|
52
|
+
```
|
41
53
|
|
42
54
|
Create a controller similar to this one
|
43
55
|
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
end
|
57
|
-
|
58
|
-
def create_params
|
59
|
-
params.require(:event_create_form)
|
60
|
-
.permit(:length_of_the_event)
|
61
|
-
.permit(event_attributes: [:start_date])
|
62
|
-
end
|
56
|
+
``` ruby
|
57
|
+
class EventController < ApplicationController
|
58
|
+
def new
|
59
|
+
@event_form = EventCreateForm.new
|
60
|
+
end
|
61
|
+
|
62
|
+
def create
|
63
|
+
@event_form = EventCreateForm.new(create_params)
|
64
|
+
if @event_form.save
|
65
|
+
redirect_to @event_form.event
|
66
|
+
else
|
67
|
+
render :new
|
63
68
|
end
|
69
|
+
end
|
64
70
|
|
71
|
+
def create_params
|
72
|
+
params.require(:event_create_form)
|
73
|
+
.permit(:length_of_the_event)
|
74
|
+
.permit(event_attributes: [:start_date])
|
75
|
+
end
|
76
|
+
end
|
77
|
+
```
|
65
78
|
|
66
79
|
And in the template:
|
67
80
|
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
81
|
+
``` erb
|
82
|
+
<%= form_for @event_form do %>
|
83
|
+
<%= fields_for :event do %>
|
84
|
+
<%= input_tag :start_date %>
|
85
|
+
<% end %>
|
86
|
+
<%= input_tag :length_of_the_event %>
|
87
|
+
<% end %>
|
88
|
+
```
|
74
89
|
|
75
90
|
|
76
91
|
##Some sources for Form Objects
|
data/Rakefile
ADDED
data/lib/syrup/form_object.rb
CHANGED
@@ -37,12 +37,36 @@ class Syrup::FormObject
|
|
37
37
|
attr_accessor klass
|
38
38
|
end
|
39
39
|
|
40
|
+
attr_accessor :wrapped_class
|
40
41
|
|
42
|
+
def wraps(klass)
|
43
|
+
wrapped_class = klass
|
44
|
+
has_one(klass)
|
45
|
+
alias_method :wrapped, klass
|
46
|
+
alias_method :wrapped=, "#{klass}="
|
47
|
+
|
48
|
+
end
|
49
|
+
|
50
|
+
def find(params)
|
51
|
+
form = self.new
|
52
|
+
form.find_relations(params)
|
53
|
+
form.after_find(params)
|
54
|
+
form
|
55
|
+
end
|
56
|
+
|
57
|
+
end
|
58
|
+
|
59
|
+
def method_missing(*params)
|
60
|
+
wrapped.send *params
|
61
|
+
end
|
62
|
+
|
63
|
+
def responds_to?(*params)
|
64
|
+
super || wrapped.responds_to?(*params)
|
41
65
|
end
|
42
66
|
|
43
67
|
def initialize(params={})
|
44
68
|
build_relations
|
45
|
-
build
|
69
|
+
build(params)
|
46
70
|
assign_parameters(params)
|
47
71
|
end
|
48
72
|
|
@@ -52,6 +76,18 @@ class Syrup::FormObject
|
|
52
76
|
end
|
53
77
|
end
|
54
78
|
|
79
|
+
def find_relations(params)
|
80
|
+
if params.is_a?(Hash)
|
81
|
+
self.class.relations.each do |klass|
|
82
|
+
if params[klass]
|
83
|
+
self.send "#{klass}=", klass.to_s.camelize.constantize.find(params[klass])
|
84
|
+
end
|
85
|
+
end
|
86
|
+
else
|
87
|
+
self.wrapped= self.wrapped.class.find(params)
|
88
|
+
end
|
89
|
+
end
|
90
|
+
|
55
91
|
def assign_parameters(params)
|
56
92
|
@params = params
|
57
93
|
params.each do |key, value|
|
@@ -59,7 +95,8 @@ class Syrup::FormObject
|
|
59
95
|
end
|
60
96
|
end
|
61
97
|
|
62
|
-
def build; end
|
98
|
+
def build(params); end
|
99
|
+
def after_find(params); end
|
63
100
|
|
64
101
|
def persisted?
|
65
102
|
false
|
data/lib/syrup/version.rb
CHANGED
@@ -3,14 +3,13 @@ require 'spec_helper'
|
|
3
3
|
class TestItem
|
4
4
|
include Virtus.model
|
5
5
|
attribute :test_item_value, Integer
|
6
|
+
|
7
|
+
def self.find(id)
|
8
|
+
end
|
6
9
|
end
|
7
10
|
|
8
11
|
class TestSubclass < Syrup::FormObject
|
9
|
-
|
10
|
-
has_one :test_item
|
11
|
-
accepts_nested_attributes_for :test_item
|
12
|
-
|
13
|
-
def build
|
12
|
+
def build(params)
|
14
13
|
@built = true
|
15
14
|
end
|
16
15
|
|
@@ -18,37 +17,155 @@ class TestSubclass < Syrup::FormObject
|
|
18
17
|
@built
|
19
18
|
end
|
20
19
|
|
20
|
+
def after_find(params)
|
21
|
+
@after_find = true
|
22
|
+
end
|
23
|
+
|
24
|
+
def has_called_after_find?
|
25
|
+
@after_find
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
shared_examples 'successful create' do
|
30
|
+
it 'creates a new object' do
|
31
|
+
expect(subject).to be_a(Syrup::FormObject)
|
32
|
+
end
|
33
|
+
it 'calls the build method' do
|
34
|
+
expect(subject).to have_called_build
|
35
|
+
end
|
21
36
|
end
|
22
37
|
|
23
38
|
describe Syrup::FormObject do
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
39
|
+
context 'when using simple attributes' do
|
40
|
+
let(:test_subclass) {
|
41
|
+
Class.new(TestSubclass) do
|
42
|
+
attribute :test_value, String
|
43
|
+
end
|
44
|
+
}
|
45
|
+
describe '#new' do
|
46
|
+
subject { test_subclass.new(params) }
|
47
|
+
let(:params) { {} }
|
48
|
+
include_examples 'successful create'
|
49
|
+
context 'with a params hash' do
|
50
|
+
let(:params) { {test_value: 'a Test'} }
|
51
|
+
|
52
|
+
include_examples 'successful create'
|
53
|
+
|
54
|
+
it 'assigns the parameters in the right places' do
|
55
|
+
expect(subject.test_value).to eq 'a Test'
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
59
|
+
pending '#save'
|
60
|
+
describe '::find' do
|
61
|
+
subject { test_subclass.find(params) }
|
62
|
+
let(:params) { {} }
|
63
|
+
it 'calls the after_find method' do
|
64
|
+
expect(subject).to have_called_after_find
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
end
|
69
|
+
context 'when using nested attributes' do
|
70
|
+
let(:test_subclass) {
|
71
|
+
Class.new(TestSubclass) do
|
72
|
+
has_one :test_item
|
73
|
+
accepts_nested_attributes_for :test_item
|
74
|
+
end
|
75
|
+
}
|
76
|
+
describe '#new' do
|
77
|
+
subject { test_subclass.new(params) }
|
78
|
+
let(:params) { {} }
|
79
|
+
include_examples 'successful create' do
|
80
|
+
it 'creates the nested object' do
|
81
|
+
expect(subject.test_item).to be_a(TestItem)
|
82
|
+
end
|
83
|
+
end
|
84
|
+
|
85
|
+
context 'with a params hash' do
|
86
|
+
let(:params) {{ test_item_attributes: {
|
87
|
+
test_item_value: '2'}}}
|
88
|
+
|
89
|
+
include_examples 'successful create'
|
90
|
+
|
91
|
+
it 'assigns the parameters in the nested attributes' do
|
92
|
+
expect(subject.test_item.test_item_value).to eq 2
|
93
|
+
end
|
30
94
|
end
|
31
|
-
|
32
|
-
|
95
|
+
end
|
96
|
+
|
97
|
+
pending '#save'
|
98
|
+
describe '::find' do
|
99
|
+
subject { test_subclass.find(params) }
|
100
|
+
let(:params) { {test_item: 2} }
|
101
|
+
|
102
|
+
it 'loads the test_item from the attributes sent' do
|
103
|
+
TestItem.should_receive(:find).once { TestItem.new }
|
104
|
+
|
105
|
+
expect(subject.test_item).to be_a(TestItem)
|
106
|
+
end
|
107
|
+
it 'calls the after_find method' do
|
108
|
+
expect(subject).to have_called_after_find
|
33
109
|
end
|
34
110
|
end
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
111
|
+
|
112
|
+
end
|
113
|
+
|
114
|
+
context 'when using a wrapped object' do
|
115
|
+
let(:test_subclass) {
|
116
|
+
Class.new(TestSubclass) do
|
117
|
+
wraps :test_item
|
118
|
+
end
|
119
|
+
}
|
120
|
+
describe '#new' do
|
121
|
+
subject { test_subclass.new(params) }
|
122
|
+
let(:params) { {} }
|
123
|
+
include_examples 'successful create' do
|
124
|
+
it 'creates the wrapped object' do
|
125
|
+
expect(subject.test_item).to be_a(TestItem)
|
126
|
+
end
|
127
|
+
|
128
|
+
it 'creates the wrapped object' do
|
129
|
+
expect(subject.wrapped).to be_a(TestItem)
|
130
|
+
end
|
41
131
|
end
|
42
|
-
|
43
|
-
|
132
|
+
|
133
|
+
context 'with a params hash' do
|
134
|
+
let(:params) {{ test_item_value: '2' }}
|
135
|
+
|
136
|
+
include_examples 'successful create' do
|
137
|
+
it 'creates the wrapped object' do
|
138
|
+
expect(subject.test_item).to be_a(TestItem)
|
139
|
+
end
|
140
|
+
|
141
|
+
it 'creates the wrapped object' do
|
142
|
+
expect(subject.wrapped).to be_a(TestItem)
|
143
|
+
end
|
144
|
+
end
|
145
|
+
|
146
|
+
it 'assigns the parameters to the object' do
|
147
|
+
expect(subject.test_item.test_item_value).to eq 2
|
148
|
+
end
|
149
|
+
|
150
|
+
it 'has an accesor to the parameter' do
|
151
|
+
expect(subject.test_item_value).to eq 2
|
152
|
+
end
|
44
153
|
end
|
45
|
-
|
46
|
-
|
154
|
+
end
|
155
|
+
|
156
|
+
pending '#save'
|
157
|
+
describe '::find' do
|
158
|
+
subject { test_subclass.find(params) }
|
159
|
+
let(:params) { 2 }
|
160
|
+
|
161
|
+
it 'loads the test_item from the id sent' do
|
162
|
+
end
|
163
|
+
it 'calls the after_find method' do
|
164
|
+
expect(subject).to have_called_after_find
|
47
165
|
end
|
48
166
|
end
|
167
|
+
|
49
168
|
end
|
50
169
|
|
51
|
-
pending '#save'
|
52
|
-
pending '::find'
|
53
170
|
|
54
171
|
end
|
data/syrup_form_object.gemspec
CHANGED
@@ -16,5 +16,7 @@ Gem::Specification.new do |gem|
|
|
16
16
|
gem.test_files = `git ls-files -- {spec}/*`.split("\n")
|
17
17
|
gem.extra_rdoc_files = %w[LICENSE README.md]
|
18
18
|
|
19
|
-
gem.add_dependency('virtus', '~> 1.0
|
19
|
+
gem.add_dependency('virtus', '~> 1.0')
|
20
|
+
gem.add_development_dependency('rake')
|
21
|
+
gem.add_development_dependency('rspec')
|
20
22
|
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: syrup_form_object
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.5
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2013-11-
|
12
|
+
date: 2013-11-11 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: virtus
|
@@ -18,7 +18,7 @@ dependencies:
|
|
18
18
|
requirements:
|
19
19
|
- - ~>
|
20
20
|
- !ruby/object:Gem::Version
|
21
|
-
version: 1.0
|
21
|
+
version: '1.0'
|
22
22
|
type: :runtime
|
23
23
|
prerelease: false
|
24
24
|
version_requirements: !ruby/object:Gem::Requirement
|
@@ -26,7 +26,39 @@ dependencies:
|
|
26
26
|
requirements:
|
27
27
|
- - ~>
|
28
28
|
- !ruby/object:Gem::Version
|
29
|
-
version: 1.0
|
29
|
+
version: '1.0'
|
30
|
+
- !ruby/object:Gem::Dependency
|
31
|
+
name: rake
|
32
|
+
requirement: !ruby/object:Gem::Requirement
|
33
|
+
none: false
|
34
|
+
requirements:
|
35
|
+
- - ! '>='
|
36
|
+
- !ruby/object:Gem::Version
|
37
|
+
version: '0'
|
38
|
+
type: :development
|
39
|
+
prerelease: false
|
40
|
+
version_requirements: !ruby/object:Gem::Requirement
|
41
|
+
none: false
|
42
|
+
requirements:
|
43
|
+
- - ! '>='
|
44
|
+
- !ruby/object:Gem::Version
|
45
|
+
version: '0'
|
46
|
+
- !ruby/object:Gem::Dependency
|
47
|
+
name: rspec
|
48
|
+
requirement: !ruby/object:Gem::Requirement
|
49
|
+
none: false
|
50
|
+
requirements:
|
51
|
+
- - ! '>='
|
52
|
+
- !ruby/object:Gem::Version
|
53
|
+
version: '0'
|
54
|
+
type: :development
|
55
|
+
prerelease: false
|
56
|
+
version_requirements: !ruby/object:Gem::Requirement
|
57
|
+
none: false
|
58
|
+
requirements:
|
59
|
+
- - ! '>='
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '0'
|
30
62
|
description: Form Objects for ActiveRecord
|
31
63
|
email:
|
32
64
|
- alexsiri7@gmail.com
|
@@ -38,9 +70,11 @@ extra_rdoc_files:
|
|
38
70
|
files:
|
39
71
|
- .gitignore
|
40
72
|
- .rspec
|
73
|
+
- .travis.yml
|
41
74
|
- Gemfile
|
42
75
|
- LICENSE
|
43
76
|
- README.md
|
77
|
+
- Rakefile
|
44
78
|
- lib/syrup.rb
|
45
79
|
- lib/syrup/form_object.rb
|
46
80
|
- lib/syrup/version.rb
|