syrup_form_object 0.0.4 → 0.0.5
Sign up to get free protection for your applications and to get access to all the features.
- 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 Version](https://badge.fury.io/rb/syrup_form_object.png)][gem]
|
4
|
+
[![Build Status](https://travis-ci.org/alexsiri7/syrup_form_object.png?branch=master)][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
|