redtape 0.0.1

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.
Files changed (3) hide show
  1. data/lib/redtape.rb +63 -0
  2. data/spec/form_spec.rb +87 -0
  3. metadata +121 -0
@@ -0,0 +1,63 @@
1
+ require "redtape/version"
2
+
3
+ require 'active_model'
4
+
5
+ module Redtape
6
+ class Form
7
+ extend ActiveModel::Naming
8
+ include ActiveModel::Conversion
9
+ include ActiveModel::Validations
10
+
11
+ attr_accessor :model_accessors
12
+
13
+ validate :models_correct
14
+
15
+ def self.validates_and_saves(*args)
16
+ attr_accessor *args
17
+ @@model_accessors = args
18
+ end
19
+
20
+ def models_correct
21
+ @@model_accessors.each do |accessor|
22
+ begin
23
+ model = send(accessor)
24
+ unless model.valid?
25
+ errors.add(
26
+ model.class.to_s.underscore,
27
+ model.errors.full_messages
28
+ )
29
+ end
30
+ rescue
31
+ end
32
+ end
33
+ end
34
+
35
+ # Forms are never themselves persisted
36
+ def persisted?
37
+ false
38
+ end
39
+
40
+ def save
41
+ populate
42
+ if valid?
43
+ persist!
44
+ else
45
+ false
46
+ end
47
+ end
48
+
49
+ def persist!
50
+ @@model_accessors.each do |accessor|
51
+ model = send(accessor)
52
+ unless model.save
53
+ return false
54
+ end
55
+ end
56
+ true
57
+ end
58
+
59
+ def populate
60
+ fail NotImplementedError, "Implement populate in your subclass"
61
+ end
62
+ end
63
+ end
@@ -0,0 +1,87 @@
1
+ require 'virtus'
2
+
3
+ require 'redtape'
4
+ require 'active_model'
5
+
6
+ class TestUser
7
+ include Virtus
8
+
9
+ extend ActiveModel::Naming
10
+ include ActiveModel::Validations
11
+ include ActiveModel::Conversion
12
+
13
+ attribute :name, String
14
+
15
+ validates_presence_of :name
16
+ validate :name_contains_at_least_two_parts
17
+
18
+ def name_contains_at_least_two_parts
19
+ unless name =~ /.+ .+/
20
+ errors.add(:name, "should contain at least two parts")
21
+ end
22
+ end
23
+
24
+ def persisted?
25
+ valid?
26
+ end
27
+
28
+ def save
29
+ valid?
30
+ end
31
+ end
32
+
33
+ class TestRegistrationForm < Redtape::Form
34
+ validates_and_saves :test_user
35
+
36
+ attr_accessor :test_user
37
+
38
+ attr_accessor :first_name, :last_name
39
+
40
+ validates_presence_of :first_name, :last_name
41
+
42
+ def populate
43
+ self.test_user = TestUser.new(:name => "#{first_name} #{last_name}")
44
+ end
45
+ end
46
+
47
+ describe Redtape::Form do
48
+ context "given a Form accepting a first and last name that creates a User" do
49
+ context "with valid data" do
50
+ subject {
51
+ TestRegistrationForm.new.tap do |f|
52
+ f.first_name = "Evan"
53
+ f.last_name = "Light"
54
+ end
55
+ }
56
+
57
+ context "after saving the form" do
58
+ before do
59
+ subject.save
60
+ end
61
+
62
+ specify { subject.should be_valid }
63
+ specify { subject.test_user.should be_valid }
64
+ specify { subject.test_user.should be_persisted }
65
+ end
66
+ end
67
+
68
+ context "with invalid data" do
69
+ subject {
70
+ TestRegistrationForm.new.tap do |f|
71
+ f.first_name = "Evan"
72
+ end
73
+ }
74
+
75
+ context "after saving the form" do
76
+ before do
77
+ subject.save
78
+ end
79
+
80
+ specify { subject.should_not be_valid }
81
+ specify { subject.should_not be_persisted }
82
+ specify { subject.errors.should have_key(:last_name) }
83
+ specify { subject.test_user.should_not be_valid }
84
+ end
85
+ end
86
+ end
87
+ end
metadata ADDED
@@ -0,0 +1,121 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: redtape
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - Evan Light
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2012-11-05 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: virtus
16
+ requirement: !ruby/object:Gem::Requirement
17
+ none: false
18
+ requirements:
19
+ - - ! '>='
20
+ - !ruby/object:Gem::Version
21
+ version: '0'
22
+ type: :development
23
+ prerelease: false
24
+ version_requirements: !ruby/object:Gem::Requirement
25
+ none: false
26
+ requirements:
27
+ - - ! '>='
28
+ - !ruby/object:Gem::Version
29
+ version: '0'
30
+ - !ruby/object:Gem::Dependency
31
+ name: rspec
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: rails
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'
62
+ - !ruby/object:Gem::Dependency
63
+ name: activemodel
64
+ requirement: !ruby/object:Gem::Requirement
65
+ none: false
66
+ requirements:
67
+ - - ! '>='
68
+ - !ruby/object:Gem::Version
69
+ version: '0'
70
+ type: :runtime
71
+ prerelease: false
72
+ version_requirements: !ruby/object:Gem::Requirement
73
+ none: false
74
+ requirements:
75
+ - - ! '>='
76
+ - !ruby/object:Gem::Version
77
+ version: '0'
78
+ description: ! 'A handy dandy way to avoid using #accepts_nested_attributes_for'
79
+ email:
80
+ - evan.light@tripledogdare.net
81
+ executables: []
82
+ extensions: []
83
+ extra_rdoc_files: []
84
+ files:
85
+ - lib/redtape.rb
86
+ - spec/form_spec.rb
87
+ homepage: http://github.com/ClearFit/redtape
88
+ licenses: []
89
+ post_install_message:
90
+ rdoc_options: []
91
+ require_paths:
92
+ - lib
93
+ required_ruby_version: !ruby/object:Gem::Requirement
94
+ none: false
95
+ requirements:
96
+ - - ! '>='
97
+ - !ruby/object:Gem::Version
98
+ version: '0'
99
+ segments:
100
+ - 0
101
+ hash: 1171762928256566195
102
+ required_rubygems_version: !ruby/object:Gem::Requirement
103
+ none: false
104
+ requirements:
105
+ - - ! '>='
106
+ - !ruby/object:Gem::Version
107
+ version: '0'
108
+ segments:
109
+ - 0
110
+ hash: 1171762928256566195
111
+ requirements: []
112
+ rubyforge_project:
113
+ rubygems_version: 1.8.24
114
+ signing_key:
115
+ specification_version: 3
116
+ summary: Redtape provides an alternative to [ActiveRecord::NestedAttributes#accepts\_nested\_attributes\_for](http://api.rubyonrails.org/classes/ActiveRecord/NestedAttributes/ClassMethods.html#method-i-accepts_nested_attributes_for)
117
+ in the form of, well, a Form! The initial implementation was heavily inspired by
118
+ ["7 Ways to Decompose Fat Activerecord Models"](http://blog.codeclimate.com/blog/2012/10/17/7-ways-to-decompose-fat-activerecord-models/)
119
+ by [Bryan Helmkamp](https://github.com/brynary).
120
+ test_files:
121
+ - spec/form_spec.rb