rectify 0.0.2 → 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: b0c393c5fdb2019cf7d46a8f71723f53dc5bac79
4
- data.tar.gz: cfe199b4e00480e6b0f208d9a03004fd86455569
3
+ metadata.gz: 4347cd2896dcb19ca5f47ac3934c433d81668ac3
4
+ data.tar.gz: 377299eed0a96ce220b70e0967ba77fbcbe4512b
5
5
  SHA512:
6
- metadata.gz: 6b482e2f24f15a60441017fe4783b78ba604ff496284bcd380cf00528c4585f305d01c6829e47cfc76f3ef88204af1637c8de4d5eb87e8bde53822dacb705f8e
7
- data.tar.gz: 7192fdc7913ba5142f382150ca45fe4cc7cc560e215440a1e110d4e1438c9632aed0ce87075a19da987abc634c465155d054d9ce7e625171849325aae1086ece
6
+ metadata.gz: 0f7a0a7f6d15d47b15283bd123118af5c3d1a4ea6a996eb1e7bd206bbb10bf761b7a3cdfb5fa91df5bc50cab9593b57fa9ea4e7acdfc819a142f0ddff6e9bd54
7
+ data.tar.gz: 25af13f81a98dea2be0918b1a1710e5ef8e3df87650ce5cf3811275fe1e75e91e6af07fe5db2da293b21f5ef41a198c3fc52c78703499f82f082d00250afb7ec
@@ -1,6 +1,6 @@
1
1
  The MIT License (MIT)
2
2
 
3
- Copyright (c) 2015 LoyaltyLion Ltd
3
+ Copyright (c) 2016 Andy Pike
4
4
 
5
5
  Permission is hereby granted, free of charge, to any person obtaining a copy
6
6
  of this software and associated documentation files (the "Software"), to deal
@@ -8,3 +8,5 @@ require "rectify/version"
8
8
  require "rectify/form"
9
9
  require "rectify/command"
10
10
  require "rectify/save_command"
11
+ require "rectify/presenter"
12
+ require "rectify/controller"
@@ -13,12 +13,6 @@ module Rectify
13
13
  instance_eval(&block)
14
14
  end
15
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
16
  def transaction(&block)
23
17
  ActiveRecord::Base.transaction(&block) if block_given?
24
18
  end
@@ -0,0 +1,34 @@
1
+ module Rectify
2
+ module Controller
3
+ def self.included(base_class)
4
+ base_class.helper_method(:presenter)
5
+ end
6
+
7
+ def present(presenter, options = {})
8
+ presenter_type = options.fetch(:for) { :template }
9
+
10
+ presenter.for_controller(self)
11
+ rectify_presenters[presenter_type] = presenter
12
+ end
13
+
14
+ def presenter(presenter_type = :template)
15
+ rectify_presenters[presenter_type]
16
+ end
17
+
18
+ def expose(presentation_data)
19
+ presentation_data.each do |attribute, value|
20
+ if presenter.respond_to?("#{attribute}=")
21
+ presenter.public_send("#{attribute}=", value)
22
+ else
23
+ instance_variable_set("@#{attribute}", value)
24
+ end
25
+ end
26
+ end
27
+
28
+ private
29
+
30
+ def rectify_presenters
31
+ @rectify_presenters ||= {}
32
+ end
33
+ end
34
+ end
@@ -41,7 +41,7 @@ module Rectify
41
41
  id.present? && id.to_i > 0
42
42
  end
43
43
 
44
- def valid?
44
+ def valid?(context = nil)
45
45
  [super, form_attributes_valid?, arrays_attributes_valid?].all?
46
46
  end
47
47
 
@@ -0,0 +1,29 @@
1
+ module Rectify
2
+ class Presenter
3
+ include Virtus.model
4
+
5
+ def for_controller(controller)
6
+ @controller = controller
7
+ end
8
+
9
+ def method_missing(method_name, *args, &block)
10
+ if view_context.respond_to?(method_name)
11
+ view_context.public_send(method_name, *args, &block)
12
+ else
13
+ super
14
+ end
15
+ end
16
+
17
+ def respond_to_missing?(method_name, include_private = false)
18
+ view_context.respond_to?(method_name, include_private)
19
+ end
20
+
21
+ private
22
+
23
+ attr_reader :controller
24
+
25
+ def view_context
26
+ controller && controller.view_context
27
+ end
28
+ end
29
+ end
@@ -1,3 +1,3 @@
1
1
  module Rectify
2
- VERSION = "0.0.2"
2
+ VERSION = "0.1.0"
3
3
  end
data/readme.md CHANGED
@@ -6,8 +6,8 @@ Rectify is a gem that provides some lightweight classes that will make it easier
6
6
  to build Rails applications in a more maintainable way. It's built on top of
7
7
  several other gems and adds improved APIs to make things easier.
8
8
 
9
- Rectify is an extraction from a number of projects that I've worked on and used
10
- these techniques.
9
+ Rectify is an extraction from a number of projects that use these techniques and
10
+ proved to be successful.
11
11
 
12
12
  To install, add it to your `Gemfile`:
13
13
 
@@ -23,14 +23,17 @@ bundle install
23
23
 
24
24
  ## Overview
25
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
26
+ Currently, Rectify consists of the following concepts:
27
+
28
+ * Form Objects
29
+ * Commands
30
+ * Presenters
31
+
32
+ You can use these separately or together to improve the structure of your Rails
28
33
  applications.
29
34
 
30
35
  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.
36
+ business logic is either placed in the controller or the model and the views are filled with too much logic. The opinion of Rectify is that these places are incorrect and that your models in particular are doing too much.
34
37
 
35
38
  Rectify's opinion is that controllers should just be concerned with HTTP related
36
39
  things and models should just be concerned with data access. The problem then
@@ -38,13 +41,20 @@ becomes, how and where do you place validations and other business logic.
38
41
 
39
42
  Using Rectify, the Form Objects contain validations and represent the data input
40
43
  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.
44
+ perform a single action which is invoked by a controller. Presenters contain the
45
+ presentation logic in a way that is easily testable and keeps your views as clean
46
+ as possible.
42
47
 
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:
48
+ Here's an example controller that shows details about a user and also allows a user to register an account. This creates a user, sends some emails, does some special auditing and integrates with a third party system:
45
49
 
46
50
  ```ruby
47
51
  class UserController < ApplicationController
52
+ include Rectify::Controller
53
+
54
+ def show
55
+ present UserDetailsPresenter.new(:user => current_user)
56
+ end
57
+
48
58
  def new
49
59
  @form = RegistrationForm.new
50
60
  end
@@ -70,9 +80,11 @@ HTTP => Controller (redirecting, rendering, etc)
70
80
  Data Input => Form Object (validation, acceptable input)
71
81
  Business Logic => Command (logic for a specific use case)
72
82
  Data Access => Model (relationships, queries)
83
+ View Logic => Presenter (formatting data)
73
84
  ```
74
85
 
75
- The next sections will give further details about using Form Objects and Commands.
86
+ The next sections will give further details about using Form Objects, Commands
87
+ and Presenters.
76
88
 
77
89
  ## Form Objects
78
90
 
@@ -84,8 +96,8 @@ Here is how you define a form object:
84
96
 
85
97
  ```ruby
86
98
  class UserForm < Rectify::Form
87
- attribute :first_name, String
88
- attribute :last_name, String
99
+ attribute :first_name, String
100
+ attribute :last_name, String
89
101
 
90
102
  validates :first_name, :last_name, :presence => true
91
103
  end
@@ -195,7 +207,7 @@ You can use the params hash that a Rails controller provides that contains all
195
207
  the data in the request:
196
208
 
197
209
  ```ruby
198
- form = User.from_params(params)
210
+ form = UserForm.from_params(params)
199
211
  ```
200
212
 
201
213
  When populating from params we will populate the built in `id` attribute from the
@@ -211,7 +223,7 @@ params = {
211
223
  }
212
224
  }
213
225
 
214
- form = User.from_params(params)
226
+ form = UserForm.from_params(params)
215
227
 
216
228
  form.id # => 1
217
229
  form.first_name # => "Andy"
@@ -222,6 +234,20 @@ The other thing to notice is that (thanks to Virtus), attribute values are cast
222
234
  to the correct type. The params hash is actually all string based but when you
223
235
  get values from the form, they are returned as the correct type (see `id` above).
224
236
 
237
+ In addition to the params hash, you may want to add additional contextual data.
238
+ This can be done by supplying a second hash to the `.from_params` method.
239
+ Elements from this hash will be available to populate form attributes as if they
240
+ were under the params key:
241
+
242
+ ```ruby
243
+ form = UserForm.from_params(params, :ip_address => "1.2.3.4")
244
+
245
+ form.id # => 1
246
+ form.first_name # => "Andy"
247
+ form.last_name # => "Pike"
248
+ form.ip_address # => "1.2.3.4"
249
+ ```
250
+
225
251
  **Model**
226
252
 
227
253
  The final way is to pass an ActiveModel to the form to populate it's attribute
@@ -251,7 +277,8 @@ Rectify includes `ActiveModel::Validations` for you so you can use all of the
251
277
  Rails validations that you are used to within your models.
252
278
 
253
279
  Your Form Object has a `#valid?` method that will validate the attributes of your
254
- form as well as any nested form objects.
280
+ form as well as any (deeply) nested form objects and array attributes that contain
281
+ form objects.
255
282
 
256
283
  ### Strong Parameters
257
284
 
@@ -260,6 +287,410 @@ parameters. That's because with Form Objects you do not need strong parameters.
260
287
  You only specify attributes in your form that are allowed to be accepted. All
261
288
  other data in your params hash is ignored.
262
289
 
290
+ Take a look at [Virtus](https://github.com/solnic/virtus) for more information
291
+ about how to build a form object.
292
+
263
293
  ## Commands
264
294
 
265
- Docs coming soon...
295
+ Commands in Rectify are based on [Wisper](https://github.com/krisleech/wisper)
296
+ which allows classes to broadcast events for publish/subscribe capabilities.
297
+ `Rectify::Command` is a lightweight class that gives an alternate API and adds some
298
+ helper methods to improve Command logic.
299
+
300
+ The reason for using the pub/sub model rather than returning a result means that
301
+ we can reduce the number of conditionals in our code as the outcome of a Command
302
+ might be more complex than just success or failure.
303
+
304
+ With regard to naming, Rectify suggests using verbs rather than nouns for Command
305
+ class names, for example `RegisterAccount`, `PlaceOrder` or `GenerateEndOfYearReport`.
306
+ Notice that we don't suffix commands with `Command` or `Service` or similar.
307
+
308
+ Here is an example Command with the structure Rectify suggests (as seen in the
309
+ overview above):
310
+
311
+ ```ruby
312
+ class RegisterAccount < Rectify::Command
313
+ def initialize(form)
314
+ @form = form
315
+ end
316
+
317
+ def call
318
+ return broadcast(:invalid) if form.invalid?
319
+
320
+ transaction do
321
+ creates_user
322
+ notifiy_admins
323
+ audit_event
324
+ send_user_details_to_crm
325
+ end
326
+
327
+ broadcast(:ok)
328
+ end
329
+
330
+ private
331
+
332
+ attr_reader :form
333
+
334
+ def creates_user
335
+ # ...
336
+ end
337
+
338
+ def notifiy_admins
339
+ # ...
340
+ end
341
+
342
+ def audit_event
343
+ # ...
344
+ end
345
+
346
+ def send_user_details_to_crm
347
+ # ...
348
+ end
349
+ end
350
+ ```
351
+
352
+ To invoke this Command, you would do the following:
353
+
354
+ ```ruby
355
+ def create
356
+ @form = RegistrationForm.from_params(params)
357
+
358
+ RegisterAccount.call(@form) do
359
+ on(:ok) { redirect_to dashboard_path }
360
+ on(:invalid) { render :new }
361
+ on(:already_registered) { redirect_to login_path }
362
+ end
363
+ end
364
+ ```
365
+
366
+ ### What happens inside a Command?
367
+
368
+ When you call the `.call` class method, Rectify will instantiate a new instance
369
+ of the command and will pass the parameters to it's constructor, it will then
370
+ call the instance method `#call` on the newly created command object. The `.call`
371
+ method also allows you to supply a block where you can handle the events that may
372
+ have been broadcast from the command.
373
+
374
+ The events that your Command broadcasts can be anything, Rectify suggests `:ok`
375
+ for success and `:invalid` if the form data is not valid, but it's totally up to
376
+ you.
377
+
378
+ From here you can choose to implement your Command how you see fit. A
379
+ `Rectify::Command` only has to have the instance method `#call`.
380
+
381
+ ### Writing Commands
382
+
383
+ As your application grows and Commands get more complex we recommend using the
384
+ structure above. Within the `#call` method you first check that the input data is
385
+ valid. If it is you then perform the various tasks that need to be completed.
386
+ We recommend using private methods for each step that are well named which makes
387
+ it very easy for anyone reading the code to workout what it does.
388
+
389
+ Feel free to use other classes and objects where appropriate to keep your code
390
+ well organised and maintainable.
391
+
392
+ ### Events
393
+
394
+ Just as in [Wisper](https://github.com/krisleech/wisper), you fire events using
395
+ the `broadcast` method. You can use any event name you like. You can also pass
396
+ parameters to the handling block:
397
+
398
+ ```ruby
399
+ # within the command:
400
+
401
+ class RegisterAccount < Rectify::Command
402
+ def call
403
+ # ...
404
+ broadcast(:ok, user)
405
+ end
406
+ end
407
+
408
+ # within the controller:
409
+
410
+ def create
411
+ RegisterAccount.call(@form) do
412
+ on(:ok) { |user| logger.info("#{user.first_name} created") }
413
+ end
414
+ end
415
+ ```
416
+
417
+ When an event is handled, the appropriate block is called in the context of the
418
+ controller. Basically, any method call within the block is delegated back to the
419
+ controller.
420
+
421
+ You may occasionally want to expose a value within a handler block to the view.
422
+ You do this via the `expose` method within the handler block. If you want to
423
+ use `expose` then you must include the `Rectify::Controller` module in your
424
+ controller. You pass a hash of the variables you wish to expose to the view and
425
+ they will then be available. If you have set a Presenter for the view then
426
+ `expose` will try to set an attribute on that presenter. If there is no Presenter
427
+ or the Presenter doesn't have a matching attribute then `expose` will set an
428
+ instance variable of the same name. See below for more details about Presenters.
429
+
430
+ ```ruby
431
+ # within the controller:
432
+
433
+ include Rectify::Controller
434
+
435
+ def create
436
+ present HomePresenter.new(:name => "Guest")
437
+
438
+ RegisterAccount.call(@form) do
439
+ on(:ok) { |user| expose(:name => user.name, :greeting => "Hello") }
440
+ end
441
+ end
442
+ ```
443
+
444
+ ```html
445
+ <!-- within the view: -->
446
+
447
+ <p><%= @greeting %> <%= presenter.name %></p>
448
+ # => <p>Hello Andy</p>
449
+ ```
450
+
451
+ Take a look at [Wisper](https://github.com/krisleech/wisper) for more information
452
+ around how to do publish/subscribe.
453
+
454
+ ## Presenters
455
+
456
+ A Presenter is a class that contains the presentational logic for your views. These
457
+ are also known as an "exhibit", "view model", "view object" or just a "view" (Rails
458
+ views are actually templates, but anyway). To avoid confusion Rectify calls these
459
+ classes Presenters.
460
+
461
+ It's often the case that you need some logic that is just for the UI. The same
462
+ question comes up, where should this logic go? You could put it directly in the
463
+ view, add it to the model or create a helper. Rectify's opinion is that all of
464
+ these are incorrect. Instead, create a Presenter for the view (or component of
465
+ the view) and place your logic here. These classes are easily testable and provide
466
+ a more object oriented approach to the problem.
467
+
468
+ To create a Presenter just derive off of `Rectify::Presenter`, add attributes as
469
+ you do for Form Objects using [Virtus](https://github.com/solnic/virtus) `attribute`
470
+ declaration. Inside a Presenter you have access to all view helper methods so
471
+ it's easy to move the presetation logic here:
472
+
473
+ ```ruby
474
+ class UserDetailsPresenter < Rectify::Presenter
475
+ attribute :user, User
476
+
477
+ def edit_link
478
+ return "" unless user.admin?
479
+
480
+ link_to "Edit #{user.name}", edit_user_path(user)
481
+ end
482
+ end
483
+ ```
484
+
485
+ Once you have a Presenter, you typically create it in your controller and make it
486
+ accessible to your views. There are two ways to do that. The first way is to just
487
+ treat it as a normal class:
488
+
489
+ ```ruby
490
+ class UsersController < ApplicationController
491
+ def show
492
+ user = User.find(params[:id])
493
+
494
+ @presenter = UserDetailsPresenter.new(:user => user).for_controller(self)
495
+ end
496
+ end
497
+ ```
498
+
499
+ You need to call `#for_controller` and pass it a controller instance which will
500
+ allow it access to the view helpers. You can then use the Presenter in your views
501
+ as you would expect:
502
+
503
+ ```html
504
+ <p><%= @presenter.edit_link %></p>
505
+ ```
506
+
507
+ The second way is a little cleaner as we have supplied a few helper methods to
508
+ clean up remove some of the boilerplate. You need to include the `Rectify::Controller`
509
+ module and then use the `present` helper:
510
+
511
+ ```ruby
512
+ class UsersController < ApplicationController
513
+ include Rectify::Controller
514
+
515
+ def show
516
+ user = User.find(params[:id])
517
+
518
+ present UserDetailsPresenter.new(:user => user)
519
+ end
520
+ end
521
+ ```
522
+
523
+ In your view, you can access this presenter using the `presenter` helper method:
524
+
525
+ ```html
526
+ <p><%= presenter.edit_link %></p>
527
+ ```
528
+
529
+ We recommend having a single Presenter per view but you may want to have more
530
+ than one presenter. You can use a Presenter to to hold the presentation logic
531
+ of your layout or for a component view. To do this, you can either use the first
532
+ method above or use the `present` method and add a `for` option with any key:
533
+
534
+ ```ruby
535
+ class ApplicationController < ActionController::Base
536
+ include Rectify::Controller
537
+
538
+ before_action { present LayoutPresenter.new(:user => user), :for => :layout }
539
+ end
540
+ ```
541
+
542
+ To access this Presenter in the view, just pass the Presenter key to the `presenter`
543
+ method like so:
544
+
545
+ ```html
546
+ <p><%= presenter(:layout).login_link %></p>
547
+ ```
548
+
549
+ ### Updating values of a Presenter
550
+
551
+ After a presenter has been instantiated you can update it's values but just setting
552
+ their attributes:
553
+
554
+ ```ruby
555
+ class UsersController < ApplicationController
556
+ include Rectify::Controller
557
+
558
+ def show
559
+ user = User.find(params[:id])
560
+
561
+ present UserDetailsPresenter.new(:user => user)
562
+ presenter.user = User.first
563
+ end
564
+
565
+ # or...
566
+
567
+ def other_action
568
+ user = User.find(params[:id])
569
+
570
+ @presenter = UserDetailsPresenter.new(:user => user).for_controller(self)
571
+ @presenter.user = User.first
572
+ end
573
+ end
574
+ ```
575
+
576
+ As mentioned above in the Commands section, you can use the `expose` method (if
577
+ you include `Rectify::Controller`). You can use this anywhere in the controller
578
+ action including the Command handler block. If you have set a Presenter for the
579
+ view then `expose` will try to set an attribute on that presenter. If there is
580
+ no Presenter or the Presenter doesn't have a matching attribute then `expose`
581
+ will set an instance variable of the same name:
582
+
583
+ ```ruby
584
+ class UsersController < ApplicationController
585
+ include Rectify::Controller
586
+
587
+ def show
588
+ user = User.find(params[:id])
589
+
590
+ present UserDetailsPresenter.new(:user => user)
591
+
592
+ expose(:user => User.first, :message => "Hello there!")
593
+
594
+ # presenter.user == User.first
595
+ # @message == "Hello there!"
596
+ end
597
+ end
598
+ ```
599
+
600
+ ### Decorators
601
+
602
+ Another option for containing your UI logic is to use a Decorator. Rectify doesn't
603
+ ship with a built in way to create a decorator but we recommend either using
604
+ [Draper](https://github.com/drapergem/draper) or you can roll your own using
605
+ `SimpleDelegator`:
606
+
607
+ ```ruby
608
+ class UserDecorator < SimpleDelegator
609
+ def full_name
610
+ "#{first_name} #{last_name}"
611
+ end
612
+ end
613
+
614
+ user = User.new(:first_name => "Andy", :last_name => "Pike")
615
+ decorator = UserDecorator.new(user)
616
+ decorator.full_name # => "Andy Pike"
617
+ ```
618
+
619
+ If you want to decorate a collection of objects you can do that by adding the
620
+ `for_collection` method:
621
+
622
+ ```ruby
623
+ class UserDecorator < SimpleDelegator
624
+ # ...
625
+
626
+ def self.for_collection(users)
627
+ users.map { |u| new(u) }
628
+ end
629
+ end
630
+
631
+ users = UserDecorator.for_collection(User.all)
632
+ user.each do |u|
633
+ u.full_name # => Works for each user :o)
634
+ end
635
+ ```
636
+
637
+ ## Where do I put my files?
638
+
639
+ The next inevitable question is "Where do I put my Forms, Commands and Presenters?".
640
+ You could create `forms`, `commands` and `presenters` folders and follow the Rails Way.
641
+ Rectify suggests grouping your classes by feature rather than by pattern. For example,
642
+ create a folder called `core` (this can be anything) and within that, create a
643
+ folder for each broad feature of your application. Something like the following:
644
+
645
+ ```
646
+ .
647
+ └── app
648
+ ├── controllers
649
+ ├── core
650
+ │   ├── billing
651
+ │   ├── fulfilment
652
+ │   ├── ordering
653
+ │   ├── reporting
654
+ │   └── security
655
+ ├── models
656
+ └── views
657
+ ```
658
+
659
+ Then you would place your classes in the appropriate feature folder. If you follow
660
+ this pattern remember to namespace your classes with a matching module:
661
+
662
+ ```ruby
663
+ # in app/core/billing/send_invoice.rb
664
+
665
+ module Billing
666
+ class SendInvoice < Rectify::Command
667
+ # ...
668
+ end
669
+ end
670
+ ```
671
+
672
+ You don't need to alter your load path as everything in the `app` folder is
673
+ loaded automatically.
674
+
675
+ ## Trade offs
676
+
677
+ This style of Rails architecture is not a silver bullet for all projects. If your
678
+ app is pretty much just basic CRUD then you are unlikely to get much benefit from
679
+ this. However, if your app is more than just CRUD then you should see an
680
+ improvement in code structure and maintainability.
681
+
682
+ The downside to this approach is that there will be many more classes and files
683
+ to deal with. This can be tricky as the application gets bigger to hold the whole
684
+ system in your head. Personally I would prefer that as maintaining it will be
685
+ easier as all code around a specific user task is on one place.
686
+
687
+ Before you use these methods in your project, consider the trade off and use these
688
+ strategies where they make sense for you and your project.
689
+
690
+ ## What's next?
691
+
692
+ We stated above that the models should be responsible for data access. We
693
+ may introduce a nice way to keep using the power of ActiveRecord but in a way
694
+ where your models don't end up as a big ball of queries. We're thinking about
695
+ Query Objects and a nice way to do this and we're also thinking about a nicer way
696
+ to use raw SQL.
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: rectify
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.2
4
+ version: 0.1.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Andy Pike
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2015-12-08 00:00:00.000000000 Z
11
+ date: 2016-02-16 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: virtus
@@ -110,6 +110,26 @@ dependencies:
110
110
  - - ">="
111
111
  - !ruby/object:Gem::Version
112
112
  version: 4.2.0
113
+ - !ruby/object:Gem::Dependency
114
+ name: actionpack
115
+ requirement: !ruby/object:Gem::Requirement
116
+ requirements:
117
+ - - "~>"
118
+ - !ruby/object:Gem::Version
119
+ version: '4.2'
120
+ - - ">="
121
+ - !ruby/object:Gem::Version
122
+ version: 4.2.0
123
+ type: :development
124
+ prerelease: false
125
+ version_requirements: !ruby/object:Gem::Requirement
126
+ requirements:
127
+ - - "~>"
128
+ - !ruby/object:Gem::Version
129
+ version: '4.2'
130
+ - - ">="
131
+ - !ruby/object:Gem::Version
132
+ version: 4.2.0
113
133
  - !ruby/object:Gem::Dependency
114
134
  name: awesome_print
115
135
  requirement: !ruby/object:Gem::Requirement
@@ -195,7 +215,9 @@ files:
195
215
  - LICENSE.txt
196
216
  - lib/rectify.rb
197
217
  - lib/rectify/command.rb
218
+ - lib/rectify/controller.rb
198
219
  - lib/rectify/form.rb
220
+ - lib/rectify/presenter.rb
199
221
  - lib/rectify/save_command.rb
200
222
  - lib/rectify/version.rb
201
223
  - readme.md
@@ -219,9 +241,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
219
241
  version: '0'
220
242
  requirements: []
221
243
  rubyforge_project:
222
- rubygems_version: 2.4.7
244
+ rubygems_version: 2.4.5
223
245
  signing_key:
224
246
  specification_version: 4
225
247
  summary: Improvements for building Rails apps
226
248
  test_files: []
227
- has_rdoc: