rectify 0.0.1 → 0.0.2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/lib/rectify/command.rb +38 -0
- data/lib/rectify/form.rb +80 -0
- data/lib/rectify/save_command.rb +21 -0
- data/lib/rectify/version.rb +1 -1
- data/lib/rectify.rb +10 -5
- data/readme.md +264 -0
- metadata +187 -7
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: b0c393c5fdb2019cf7d46a8f71723f53dc5bac79
|
4
|
+
data.tar.gz: cfe199b4e00480e6b0f208d9a03004fd86455569
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 6b482e2f24f15a60441017fe4783b78ba604ff496284bcd380cf00528c4585f305d01c6829e47cfc76f3ef88204af1637c8de4d5eb87e8bde53822dacb705f8e
|
7
|
+
data.tar.gz: 7192fdc7913ba5142f382150ca45fe4cc7cc560e215440a1e110d4e1438c9632aed0ce87075a19da987abc634c465155d054d9ce7e625171849325aae1086ece
|
@@ -0,0 +1,38 @@
|
|
1
|
+
module Rectify
|
2
|
+
class Command
|
3
|
+
include Wisper::Publisher
|
4
|
+
|
5
|
+
def self.call(*args, &block)
|
6
|
+
command = new(*args)
|
7
|
+
command.evaluate(&block) if block_given?
|
8
|
+
command.call
|
9
|
+
end
|
10
|
+
|
11
|
+
def evaluate(&block)
|
12
|
+
@caller = eval("self", block.binding)
|
13
|
+
instance_eval(&block)
|
14
|
+
end
|
15
|
+
|
16
|
+
def expose(instance_variables)
|
17
|
+
instance_variables.each do |name, value|
|
18
|
+
@caller.instance_variable_set("@#{name}", value)
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
def transaction(&block)
|
23
|
+
ActiveRecord::Base.transaction(&block) if block_given?
|
24
|
+
end
|
25
|
+
|
26
|
+
def method_missing(method_name, *args, &block)
|
27
|
+
if @caller.respond_to?(method_name)
|
28
|
+
@caller.send(method_name, *args, &block)
|
29
|
+
else
|
30
|
+
super
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
def respond_to_missing?(method_name, include_private = false)
|
35
|
+
@caller.respond_to?(method_name, include_private)
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
data/lib/rectify/form.rb
ADDED
@@ -0,0 +1,80 @@
|
|
1
|
+
module Rectify
|
2
|
+
class Form
|
3
|
+
include Virtus.model
|
4
|
+
include ActiveModel::Validations
|
5
|
+
|
6
|
+
attribute :id, Integer
|
7
|
+
|
8
|
+
def self.from_params(params, additional_params = {})
|
9
|
+
params = params.with_indifferent_access
|
10
|
+
attributes = params.fetch(mimicked_model_name, {}).merge(additional_params)
|
11
|
+
|
12
|
+
new(attributes).tap do |f|
|
13
|
+
f.id = params[:id]
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
def self.from_model(model)
|
18
|
+
new(model.attributes)
|
19
|
+
end
|
20
|
+
|
21
|
+
def self.mimic(model_name)
|
22
|
+
@model_name = model_name.to_s.underscore.to_sym
|
23
|
+
end
|
24
|
+
|
25
|
+
def self.mimicked_model_name
|
26
|
+
@model_name || infer_model_name
|
27
|
+
end
|
28
|
+
|
29
|
+
def self.infer_model_name
|
30
|
+
class_name = name.split("::").last
|
31
|
+
return :form if class_name == "Form"
|
32
|
+
|
33
|
+
class_name.chomp("Form").underscore.to_sym
|
34
|
+
end
|
35
|
+
|
36
|
+
def self.model_name
|
37
|
+
ActiveModel::Name.new(self, nil, mimicked_model_name.to_s.camelize)
|
38
|
+
end
|
39
|
+
|
40
|
+
def persisted?
|
41
|
+
id.present? && id.to_i > 0
|
42
|
+
end
|
43
|
+
|
44
|
+
def valid?
|
45
|
+
[super, form_attributes_valid?, arrays_attributes_valid?].all?
|
46
|
+
end
|
47
|
+
|
48
|
+
def to_key
|
49
|
+
[id]
|
50
|
+
end
|
51
|
+
|
52
|
+
def to_model
|
53
|
+
self
|
54
|
+
end
|
55
|
+
|
56
|
+
def attributes
|
57
|
+
super.except(:id)
|
58
|
+
end
|
59
|
+
|
60
|
+
private
|
61
|
+
|
62
|
+
def form_attributes_valid?
|
63
|
+
attributes
|
64
|
+
.each_value
|
65
|
+
.select { |f| f.respond_to?(:valid?) }
|
66
|
+
.map(&:valid?)
|
67
|
+
.all?
|
68
|
+
end
|
69
|
+
|
70
|
+
def arrays_attributes_valid?
|
71
|
+
attributes
|
72
|
+
.each_value
|
73
|
+
.select { |a| a.is_a?(Array) }
|
74
|
+
.flatten
|
75
|
+
.select { |f| f.respond_to?(:valid?) }
|
76
|
+
.map(&:valid?)
|
77
|
+
.all?
|
78
|
+
end
|
79
|
+
end
|
80
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
module Rectify
|
2
|
+
class SaveCommand < Command
|
3
|
+
def initialize(form, model)
|
4
|
+
@form = form
|
5
|
+
@model = model
|
6
|
+
end
|
7
|
+
|
8
|
+
def call
|
9
|
+
return broadcast(:invalid) unless form.valid?
|
10
|
+
|
11
|
+
model.attributes = form.attributes
|
12
|
+
model.save!
|
13
|
+
|
14
|
+
broadcast(:ok)
|
15
|
+
end
|
16
|
+
|
17
|
+
private
|
18
|
+
|
19
|
+
attr_reader :form, :model
|
20
|
+
end
|
21
|
+
end
|
data/lib/rectify/version.rb
CHANGED
data/lib/rectify.rb
CHANGED
@@ -1,5 +1,10 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
1
|
+
require "virtus"
|
2
|
+
require "wisper"
|
3
|
+
require "active_support/core_ext/hash"
|
4
|
+
require "active_model"
|
5
|
+
require "active_record"
|
6
|
+
|
7
|
+
require "rectify/version"
|
8
|
+
require "rectify/form"
|
9
|
+
require "rectify/command"
|
10
|
+
require "rectify/save_command"
|
data/readme.md
CHANGED
@@ -1 +1,265 @@
|
|
1
1
|
# Rectify
|
2
|
+
|
3
|
+
[![Code Climate](https://codeclimate.com/github/andypike/rectify/badges/gpa.svg)](https://codeclimate.com/github/andypike/rectify)
|
4
|
+
|
5
|
+
Rectify is a gem that provides some lightweight classes that will make it easier
|
6
|
+
to build Rails applications in a more maintainable way. It's built on top of
|
7
|
+
several other gems and adds improved APIs to make things easier.
|
8
|
+
|
9
|
+
Rectify is an extraction from a number of projects that I've worked on and used
|
10
|
+
these techniques.
|
11
|
+
|
12
|
+
To install, add it to your `Gemfile`:
|
13
|
+
|
14
|
+
```
|
15
|
+
gem "rectify"
|
16
|
+
```
|
17
|
+
|
18
|
+
Then use Bundler to install it:
|
19
|
+
|
20
|
+
```
|
21
|
+
bundle install
|
22
|
+
```
|
23
|
+
|
24
|
+
## Overview
|
25
|
+
|
26
|
+
Currently, Rectify consists of two main concepts: Form Objects and Commands. You
|
27
|
+
can use these separately or together to improve the structure of your Rails
|
28
|
+
applications.
|
29
|
+
|
30
|
+
The main problem that Rectify tries to solve is where your logic should go. Commonly,
|
31
|
+
business logic is either placed in the controller or the model. The opinion of Rectify
|
32
|
+
is that both of these places are incorrect and that your models in particular are
|
33
|
+
doing too much.
|
34
|
+
|
35
|
+
Rectify's opinion is that controllers should just be concerned with HTTP related
|
36
|
+
things and models should just be concerned with data access. The problem then
|
37
|
+
becomes, how and where do you place validations and other business logic.
|
38
|
+
|
39
|
+
Using Rectify, the Form Objects contain validations and represent the data input
|
40
|
+
of your system. Commands then take a Form Object (as well as other data) and
|
41
|
+
perform a single action which is invoked by a controller.
|
42
|
+
|
43
|
+
Here's an example when a user registers an account. This creates a user, sends
|
44
|
+
some emails, does some special auditing and integrates with a third party system:
|
45
|
+
|
46
|
+
```ruby
|
47
|
+
class UserController < ApplicationController
|
48
|
+
def new
|
49
|
+
@form = RegistrationForm.new
|
50
|
+
end
|
51
|
+
|
52
|
+
def create
|
53
|
+
@form = RegistrationForm.from_params(params)
|
54
|
+
|
55
|
+
RegisterAccount.call(@form) do
|
56
|
+
on(:ok) { redirect_to dashboard_path }
|
57
|
+
on(:invalid) { render :new }
|
58
|
+
on(:already_registered) { redirect_to login_path }
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
62
|
+
```
|
63
|
+
|
64
|
+
The `RegistrationForm` Form Object encapsulates the relevant data that is required for the
|
65
|
+
action and the `RegisterAccount` Command encapsulates the business logic of registering
|
66
|
+
a new account. The controller is clean and business logic now has a natural home:
|
67
|
+
|
68
|
+
```
|
69
|
+
HTTP => Controller (redirecting, rendering, etc)
|
70
|
+
Data Input => Form Object (validation, acceptable input)
|
71
|
+
Business Logic => Command (logic for a specific use case)
|
72
|
+
Data Access => Model (relationships, queries)
|
73
|
+
```
|
74
|
+
|
75
|
+
The next sections will give further details about using Form Objects and Commands.
|
76
|
+
|
77
|
+
## Form Objects
|
78
|
+
|
79
|
+
Form objects in Rectify are based on [Virtus](https://github.com/solnic/virtus)
|
80
|
+
and make them compatible with Rails form builders, add ActiveModel validations
|
81
|
+
and all allow you to specify a model to mimic.
|
82
|
+
|
83
|
+
Here is how you define a form object:
|
84
|
+
|
85
|
+
```ruby
|
86
|
+
class UserForm < Rectify::Form
|
87
|
+
attribute :first_name, String
|
88
|
+
attribute :last_name, String
|
89
|
+
|
90
|
+
validates :first_name, :last_name, :presence => true
|
91
|
+
end
|
92
|
+
```
|
93
|
+
|
94
|
+
You can then set that up in your controller instead of a normal ActiveRecord model:
|
95
|
+
|
96
|
+
```ruby
|
97
|
+
class UsersController < ApplicationController
|
98
|
+
def new
|
99
|
+
@form = UserForm.new
|
100
|
+
end
|
101
|
+
|
102
|
+
def create
|
103
|
+
@form = UserForm.from_params(params)
|
104
|
+
|
105
|
+
if @form.valid?
|
106
|
+
# Do something interesting
|
107
|
+
end
|
108
|
+
end
|
109
|
+
end
|
110
|
+
```
|
111
|
+
|
112
|
+
You can use the form object with form builders such as
|
113
|
+
[simple_form](https://github.com/plataformatec/simple_form) like this:
|
114
|
+
|
115
|
+
```ruby
|
116
|
+
= simple_form_for @form do |f|
|
117
|
+
= f.input :first_name
|
118
|
+
= f.input :last_name
|
119
|
+
= f.submit
|
120
|
+
```
|
121
|
+
|
122
|
+
### Mimicking models
|
123
|
+
|
124
|
+
When the form is generated it uses the name of the form class to infer what "model"
|
125
|
+
it should mimic. In the example above, it will mimic the `User` model as it removes
|
126
|
+
the `Form` suffix from the form class name by default.
|
127
|
+
|
128
|
+
The model being mimicked affects two things about the form:
|
129
|
+
|
130
|
+
1. The route path helpers to use as the url to post to, for example: `users_path`.
|
131
|
+
2. The parent key in the params hash that the controller receives, for example
|
132
|
+
`user` in this case:
|
133
|
+
|
134
|
+
```ruby
|
135
|
+
params = {
|
136
|
+
"id" => "1",
|
137
|
+
"user" => {
|
138
|
+
"first_name" => "Andy",
|
139
|
+
"last_name" => "Pike"
|
140
|
+
}
|
141
|
+
}
|
142
|
+
```
|
143
|
+
|
144
|
+
You might want to mimic something different and use a form object that is not
|
145
|
+
named in a way where the correct model can be mimicked. For example:
|
146
|
+
|
147
|
+
```ruby
|
148
|
+
class UserForm < Rectify::Form
|
149
|
+
mimic :teacher
|
150
|
+
|
151
|
+
attribute :first_name, String
|
152
|
+
attribute :last_name, String
|
153
|
+
|
154
|
+
validates :first_name, :last_name, :presence => true
|
155
|
+
end
|
156
|
+
```
|
157
|
+
|
158
|
+
In this example we are using the same `UserForm` class but am mimicking a
|
159
|
+
`Teacher` model. The above form will then use the route path helpers
|
160
|
+
`teachers_path` and the params key will be `teacher` rather than `users_path`
|
161
|
+
and `user` respectively.
|
162
|
+
|
163
|
+
### Attributes
|
164
|
+
|
165
|
+
You define your attributes for your form object just like you do in
|
166
|
+
[Virtus](https://github.com/solnic/virtus).
|
167
|
+
|
168
|
+
By default, Rectify forms include an `id` attribute for you so you don't need to
|
169
|
+
add that. We use this `id` attribute to fulfil some of the requirements of ActiveModel
|
170
|
+
so your forms will work with form builders. For example, your form object has a
|
171
|
+
`#persisted?` method. Your form object is never persisted so technically this
|
172
|
+
should always return `false`.
|
173
|
+
|
174
|
+
However, you are normally representing something that is persistable. So we use
|
175
|
+
the value of `id` to workout if what this should return. If `id` is a number
|
176
|
+
greater than zero then we assume it is persisted otherwise we assume it isn't. This
|
177
|
+
is important as it affects where your form is posted (to the `#create` or
|
178
|
+
`#update` action in your controller).
|
179
|
+
|
180
|
+
#### Populating attributes
|
181
|
+
|
182
|
+
There are a number of ways to populate attributes of a form object.
|
183
|
+
|
184
|
+
**Constructor**
|
185
|
+
|
186
|
+
You can use the constructor and pass it a hash of values:
|
187
|
+
|
188
|
+
```ruby
|
189
|
+
form = UserForm.new(:first_name => "Andy", :last_name => "Pike")
|
190
|
+
```
|
191
|
+
|
192
|
+
**Prams hash**
|
193
|
+
|
194
|
+
You can use the params hash that a Rails controller provides that contains all
|
195
|
+
the data in the request:
|
196
|
+
|
197
|
+
```ruby
|
198
|
+
form = User.from_params(params)
|
199
|
+
```
|
200
|
+
|
201
|
+
When populating from params we will populate the built in `id` attribute from the
|
202
|
+
root of the params hash and populate the rest of the form attributes from within
|
203
|
+
the parent key. For example:
|
204
|
+
|
205
|
+
```ruby
|
206
|
+
params = {
|
207
|
+
"id" => "1",
|
208
|
+
"user" => {
|
209
|
+
"first_name" => "Andy",
|
210
|
+
"last_name" => "Pike"
|
211
|
+
}
|
212
|
+
}
|
213
|
+
|
214
|
+
form = User.from_params(params)
|
215
|
+
|
216
|
+
form.id # => 1
|
217
|
+
form.first_name # => "Andy"
|
218
|
+
form.last_name # => "Pike"
|
219
|
+
```
|
220
|
+
|
221
|
+
The other thing to notice is that (thanks to Virtus), attribute values are cast
|
222
|
+
to the correct type. The params hash is actually all string based but when you
|
223
|
+
get values from the form, they are returned as the correct type (see `id` above).
|
224
|
+
|
225
|
+
**Model**
|
226
|
+
|
227
|
+
The final way is to pass an ActiveModel to the form to populate it's attribute
|
228
|
+
values. This is useful when editing a model:
|
229
|
+
|
230
|
+
```ruby
|
231
|
+
user = User.create(:first_name => "Andy", :last_name => "Pike")
|
232
|
+
|
233
|
+
form = UserForm.from_model(user)
|
234
|
+
|
235
|
+
form.id # => 1
|
236
|
+
form.first_name # => "Andy"
|
237
|
+
form.last_name # => "Pike"
|
238
|
+
```
|
239
|
+
|
240
|
+
One important thing that is different about Rectify forms is that they are not
|
241
|
+
bound by a model. You can use a model to populate the forms attributes but that
|
242
|
+
is all it will do. It does not keep a reference to the model or interact with it.
|
243
|
+
Rectify forms are designed to be lightweight representations of the data you want
|
244
|
+
to collect or show in your forms, not something that is linked to a model. This
|
245
|
+
allows you to create any form that you like which doesn't need to match the
|
246
|
+
representation of the data in the database.
|
247
|
+
|
248
|
+
### Validations
|
249
|
+
|
250
|
+
Rectify includes `ActiveModel::Validations` for you so you can use all of the
|
251
|
+
Rails validations that you are used to within your models.
|
252
|
+
|
253
|
+
Your Form Object has a `#valid?` method that will validate the attributes of your
|
254
|
+
form as well as any nested form objects.
|
255
|
+
|
256
|
+
### Strong Parameters
|
257
|
+
|
258
|
+
Did you notice in the example above that there was no mention of strong
|
259
|
+
parameters. That's because with Form Objects you do not need strong parameters.
|
260
|
+
You only specify attributes in your form that are allowed to be accepted. All
|
261
|
+
other data in your params hash is ignored.
|
262
|
+
|
263
|
+
## Commands
|
264
|
+
|
265
|
+
Docs coming soon...
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: rectify
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Andy Pike
|
@@ -9,7 +9,183 @@ autorequire:
|
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
11
|
date: 2015-12-08 00:00:00.000000000 Z
|
12
|
-
dependencies:
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: virtus
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - "~>"
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '1.0'
|
20
|
+
- - ">="
|
21
|
+
- !ruby/object:Gem::Version
|
22
|
+
version: 1.0.5
|
23
|
+
type: :runtime
|
24
|
+
prerelease: false
|
25
|
+
version_requirements: !ruby/object:Gem::Requirement
|
26
|
+
requirements:
|
27
|
+
- - "~>"
|
28
|
+
- !ruby/object:Gem::Version
|
29
|
+
version: '1.0'
|
30
|
+
- - ">="
|
31
|
+
- !ruby/object:Gem::Version
|
32
|
+
version: 1.0.5
|
33
|
+
- !ruby/object:Gem::Dependency
|
34
|
+
name: wisper
|
35
|
+
requirement: !ruby/object:Gem::Requirement
|
36
|
+
requirements:
|
37
|
+
- - "~>"
|
38
|
+
- !ruby/object:Gem::Version
|
39
|
+
version: '1.6'
|
40
|
+
- - ">="
|
41
|
+
- !ruby/object:Gem::Version
|
42
|
+
version: 1.6.1
|
43
|
+
type: :runtime
|
44
|
+
prerelease: false
|
45
|
+
version_requirements: !ruby/object:Gem::Requirement
|
46
|
+
requirements:
|
47
|
+
- - "~>"
|
48
|
+
- !ruby/object:Gem::Version
|
49
|
+
version: '1.6'
|
50
|
+
- - ">="
|
51
|
+
- !ruby/object:Gem::Version
|
52
|
+
version: 1.6.1
|
53
|
+
- !ruby/object:Gem::Dependency
|
54
|
+
name: activesupport
|
55
|
+
requirement: !ruby/object:Gem::Requirement
|
56
|
+
requirements:
|
57
|
+
- - "~>"
|
58
|
+
- !ruby/object:Gem::Version
|
59
|
+
version: '4.2'
|
60
|
+
- - ">="
|
61
|
+
- !ruby/object:Gem::Version
|
62
|
+
version: 4.2.0
|
63
|
+
type: :runtime
|
64
|
+
prerelease: false
|
65
|
+
version_requirements: !ruby/object:Gem::Requirement
|
66
|
+
requirements:
|
67
|
+
- - "~>"
|
68
|
+
- !ruby/object:Gem::Version
|
69
|
+
version: '4.2'
|
70
|
+
- - ">="
|
71
|
+
- !ruby/object:Gem::Version
|
72
|
+
version: 4.2.0
|
73
|
+
- !ruby/object:Gem::Dependency
|
74
|
+
name: activemodel
|
75
|
+
requirement: !ruby/object:Gem::Requirement
|
76
|
+
requirements:
|
77
|
+
- - "~>"
|
78
|
+
- !ruby/object:Gem::Version
|
79
|
+
version: '4.2'
|
80
|
+
- - ">="
|
81
|
+
- !ruby/object:Gem::Version
|
82
|
+
version: 4.2.0
|
83
|
+
type: :runtime
|
84
|
+
prerelease: false
|
85
|
+
version_requirements: !ruby/object:Gem::Requirement
|
86
|
+
requirements:
|
87
|
+
- - "~>"
|
88
|
+
- !ruby/object:Gem::Version
|
89
|
+
version: '4.2'
|
90
|
+
- - ">="
|
91
|
+
- !ruby/object:Gem::Version
|
92
|
+
version: 4.2.0
|
93
|
+
- !ruby/object:Gem::Dependency
|
94
|
+
name: activerecord
|
95
|
+
requirement: !ruby/object:Gem::Requirement
|
96
|
+
requirements:
|
97
|
+
- - "~>"
|
98
|
+
- !ruby/object:Gem::Version
|
99
|
+
version: '4.2'
|
100
|
+
- - ">="
|
101
|
+
- !ruby/object:Gem::Version
|
102
|
+
version: 4.2.0
|
103
|
+
type: :runtime
|
104
|
+
prerelease: false
|
105
|
+
version_requirements: !ruby/object:Gem::Requirement
|
106
|
+
requirements:
|
107
|
+
- - "~>"
|
108
|
+
- !ruby/object:Gem::Version
|
109
|
+
version: '4.2'
|
110
|
+
- - ">="
|
111
|
+
- !ruby/object:Gem::Version
|
112
|
+
version: 4.2.0
|
113
|
+
- !ruby/object:Gem::Dependency
|
114
|
+
name: awesome_print
|
115
|
+
requirement: !ruby/object:Gem::Requirement
|
116
|
+
requirements:
|
117
|
+
- - "~>"
|
118
|
+
- !ruby/object:Gem::Version
|
119
|
+
version: '1.6'
|
120
|
+
type: :development
|
121
|
+
prerelease: false
|
122
|
+
version_requirements: !ruby/object:Gem::Requirement
|
123
|
+
requirements:
|
124
|
+
- - "~>"
|
125
|
+
- !ruby/object:Gem::Version
|
126
|
+
version: '1.6'
|
127
|
+
- !ruby/object:Gem::Dependency
|
128
|
+
name: pry
|
129
|
+
requirement: !ruby/object:Gem::Requirement
|
130
|
+
requirements:
|
131
|
+
- - "~>"
|
132
|
+
- !ruby/object:Gem::Version
|
133
|
+
version: 0.10.3
|
134
|
+
type: :development
|
135
|
+
prerelease: false
|
136
|
+
version_requirements: !ruby/object:Gem::Requirement
|
137
|
+
requirements:
|
138
|
+
- - "~>"
|
139
|
+
- !ruby/object:Gem::Version
|
140
|
+
version: 0.10.3
|
141
|
+
- !ruby/object:Gem::Dependency
|
142
|
+
name: wisper-rspec
|
143
|
+
requirement: !ruby/object:Gem::Requirement
|
144
|
+
requirements:
|
145
|
+
- - "~>"
|
146
|
+
- !ruby/object:Gem::Version
|
147
|
+
version: 0.0.2
|
148
|
+
type: :development
|
149
|
+
prerelease: false
|
150
|
+
version_requirements: !ruby/object:Gem::Requirement
|
151
|
+
requirements:
|
152
|
+
- - "~>"
|
153
|
+
- !ruby/object:Gem::Version
|
154
|
+
version: 0.0.2
|
155
|
+
- !ruby/object:Gem::Dependency
|
156
|
+
name: rspec
|
157
|
+
requirement: !ruby/object:Gem::Requirement
|
158
|
+
requirements:
|
159
|
+
- - "~>"
|
160
|
+
- !ruby/object:Gem::Version
|
161
|
+
version: '3.4'
|
162
|
+
type: :development
|
163
|
+
prerelease: false
|
164
|
+
version_requirements: !ruby/object:Gem::Requirement
|
165
|
+
requirements:
|
166
|
+
- - "~>"
|
167
|
+
- !ruby/object:Gem::Version
|
168
|
+
version: '3.4'
|
169
|
+
- !ruby/object:Gem::Dependency
|
170
|
+
name: rspec-collection_matchers
|
171
|
+
requirement: !ruby/object:Gem::Requirement
|
172
|
+
requirements:
|
173
|
+
- - "~>"
|
174
|
+
- !ruby/object:Gem::Version
|
175
|
+
version: '1.1'
|
176
|
+
- - ">="
|
177
|
+
- !ruby/object:Gem::Version
|
178
|
+
version: 1.1.2
|
179
|
+
type: :development
|
180
|
+
prerelease: false
|
181
|
+
version_requirements: !ruby/object:Gem::Requirement
|
182
|
+
requirements:
|
183
|
+
- - "~>"
|
184
|
+
- !ruby/object:Gem::Version
|
185
|
+
version: '1.1'
|
186
|
+
- - ">="
|
187
|
+
- !ruby/object:Gem::Version
|
188
|
+
version: 1.1.2
|
13
189
|
description: Build Rails apps in a more maintainable way
|
14
190
|
email: andy@andypike.com
|
15
191
|
executables: []
|
@@ -17,9 +193,12 @@ extensions: []
|
|
17
193
|
extra_rdoc_files: []
|
18
194
|
files:
|
19
195
|
- LICENSE.txt
|
20
|
-
- readme.md
|
21
|
-
- lib/rectify/version.rb
|
22
196
|
- lib/rectify.rb
|
197
|
+
- lib/rectify/command.rb
|
198
|
+
- lib/rectify/form.rb
|
199
|
+
- lib/rectify/save_command.rb
|
200
|
+
- lib/rectify/version.rb
|
201
|
+
- readme.md
|
23
202
|
homepage: https://github.com/andypike/rectify
|
24
203
|
licenses:
|
25
204
|
- MIT
|
@@ -30,18 +209,19 @@ require_paths:
|
|
30
209
|
- lib
|
31
210
|
required_ruby_version: !ruby/object:Gem::Requirement
|
32
211
|
requirements:
|
33
|
-
- -
|
212
|
+
- - ">="
|
34
213
|
- !ruby/object:Gem::Version
|
35
214
|
version: '0'
|
36
215
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
37
216
|
requirements:
|
38
|
-
- -
|
217
|
+
- - ">="
|
39
218
|
- !ruby/object:Gem::Version
|
40
219
|
version: '0'
|
41
220
|
requirements: []
|
42
221
|
rubyforge_project:
|
43
|
-
rubygems_version: 2.
|
222
|
+
rubygems_version: 2.4.7
|
44
223
|
signing_key:
|
45
224
|
specification_version: 4
|
46
225
|
summary: Improvements for building Rails apps
|
47
226
|
test_files: []
|
227
|
+
has_rdoc:
|