monkey_forms 0.0.15

Sign up to get free protection for your applications and to get access to all the features.
data/.gitignore ADDED
@@ -0,0 +1,6 @@
1
+ *.gem
2
+ .bundle
3
+ Gemfile.lock
4
+ pkg/*
5
+ bin
6
+ *.rbc
data/BUGS ADDED
@@ -0,0 +1 @@
1
+ - Forms that inherit from other forms don't seem have their form_name set correctly (according to Rails, anyways).
data/Gemfile ADDED
@@ -0,0 +1,9 @@
1
+ source "http://rubygems.org"
2
+
3
+ gem "deep_merge",
4
+ '0',
5
+ :git => "git://github.com/joevandyk/deep_merge.git",
6
+ :ref => "a244fdd2d3a633743b054857b43f1ee4cacad9ff"
7
+
8
+ # Specify your gem's dependencies in monkey_forms.gemspec
9
+ gemspec
data/NOTES ADDED
@@ -0,0 +1,4 @@
1
+ ActiveModel::Validator seems to depend on
2
+ ActiveSupport::Callbacks?
3
+ Got undefined method `extlib_inheritable_reader'
4
+ when I included ActiveModel into a class.
data/README.md ADDED
@@ -0,0 +1,154 @@
1
+ NOTE! If you use the cookie serialization feature, you
2
+ need to use this version of deep_merge for now.
3
+ https://github.com/joevandyk/deep_merge
4
+
5
+
6
+ MonkeyForms::Form is an ActiveModel-compliant interface
7
+ between your controllers and models (or whatever you are
8
+ saving the data to).
9
+
10
+ MonkeyForms supports multi-page wizards and validation groups.
11
+
12
+ class OrderForm
13
+ include MonkeyForms::Form
14
+ form_name 'cart'
15
+ form_attributes :name, :address, :city, :state, :zip
16
+
17
+ validates :name, :presence => true
18
+
19
+ # Save the data however you want.
20
+ def save
21
+ address = Address.new(:street => address, :city => city, :state => state, :zip => zip)
22
+ OrderService.place_order(:the_name => name, :address => address)
23
+ end
24
+ end
25
+
26
+
27
+ In your controller:
28
+ def new
29
+ @cart = OrderForm.new
30
+ end
31
+ def create
32
+ @cart = OrderForm.new(:form => params[:cart])
33
+ if @cart.valid?
34
+ @cart.save
35
+ redirect_to "/thanks"
36
+ else
37
+ render :action => 'new'
38
+ end
39
+ end
40
+ end
41
+
42
+ In your view:
43
+ = form_for @cart do |f|
44
+ = f.text_field :name
45
+ = f.text_field :address
46
+ = f.text_field :city
47
+ = # etc
48
+ = f.submit
49
+
50
+
51
+ A more complex multi-page order process.
52
+ State is remembered in a cookie; the form params are merged into the cookie's state on each request.
53
+
54
+ class OrderForm
55
+ include MonkeyForms::Form
56
+
57
+ # Declares a few attributes on the form.
58
+ form_attributes :name, :email, :city, :state, :line_items
59
+ custom_attributes :user_id
60
+ form_name :cart
61
+
62
+ # This form serializes the submit into a gzip'd cookie with a name
63
+ # of 'order_cookie'.
64
+ set_form_storage(
65
+ MonkeyForms::Serializers::GzipCookie.new(
66
+ :name => 'order_cookie',
67
+ :domain => 'test.domain.com',
68
+ :secure => true,
69
+ :httponly => true))
70
+
71
+ after_initialize :set_default_state
72
+
73
+ # We must submit an email address for the form to validate.
74
+ validates :email, :presence => true
75
+
76
+ validation_group :cart do
77
+ # Scope some of the validation checks
78
+ validates :name, :presence => true
79
+ end
80
+
81
+ validation_group :address do
82
+ validates :city, :presence => true
83
+ validates :state, :presence => true
84
+ end
85
+
86
+ # This is a method that uses some form attributes.
87
+ def person
88
+ "#{ name } <#{ email }>"
89
+ end
90
+
91
+ private
92
+
93
+ def set_default_state
94
+ if state.blank?
95
+ self.state = "WA"
96
+ end
97
+ end
98
+ end
99
+
100
+
101
+ class Controller
102
+ before_filter :load_cart
103
+ # Name / Email
104
+ def page1
105
+ if request.post?
106
+ if group.valid?(:name)
107
+ redirect_to "/page2"
108
+ end
109
+ end
110
+ end
111
+
112
+ # Address
113
+ def page2
114
+ if request.post?
115
+ if group.valid?(:address)
116
+ # whatever..
117
+ end
118
+ end
119
+ end
120
+
121
+ private
122
+
123
+ def load_cart
124
+ @cart = OrderForm::Form.new(:form => params[:cart]
125
+ end
126
+ end
127
+
128
+
129
+ The validation_group code is modified from
130
+ https://github.com/adzap/grouped_validations
131
+
132
+
133
+ This is pretty similar to the Presenter Pattern as described
134
+ by Jay Fields, by the way. http://blog.jayfields.com/2007/03/rails-presenter-pattern.html
135
+
136
+
137
+
138
+ There is a sample sinatra application in test/sinatra. Run with:
139
+ cd test/sinatra
140
+ rackup config.ru
141
+
142
+
143
+
144
+ ??? WHY ???
145
+
146
+ Moving the form logic to a separate class has a ton of advantages:
147
+
148
+ * Keeps the controller really simple.
149
+ * Makes it easier to test. You can write tests directly against the form handling class.
150
+ * Classes should do one thing.
151
+ * You can have complex validations.
152
+ * Your ActiveRecord models can probably become simpler.
153
+ * Since the form handling logic is encapsulated into one class, you can use inheritance, modules, etc.
154
+ * You want to move away from ActiveRecord? It's no problem -- just change how the form values are saved in the #save method.
data/Rakefile ADDED
@@ -0,0 +1,13 @@
1
+ require 'rubygems'
2
+ require 'rake'
3
+ require 'rake/testtask'
4
+ require 'bundler/setup'
5
+
6
+ Bundler::GemHelper.install_tasks
7
+
8
+ Rake::TestTask.new(:test) do |test|
9
+ test.libs << 'lib' << 'test'
10
+ test.pattern = 'test/**/test_*.rb'
11
+ end
12
+
13
+ task :default => :test
@@ -0,0 +1,12 @@
1
+ # Saves form as cookie as json+gzip
2
+ class MonkeyForms::Serializers::ActiveRecordSesssion
3
+ def initialize options={}
4
+ @cookie_name = options[:name]
5
+ end
6
+
7
+ def load options={}
8
+ end
9
+
10
+ def save options = {}
11
+ end
12
+ end
@@ -0,0 +1,34 @@
1
+ # encoding: UTF-8
2
+ require 'zlib'
3
+
4
+ # Saves form as cookie as json+gzip
5
+ class MonkeyForms::Serializers::GzipCookie
6
+ def initialize options={}
7
+ @cookie_name = options[:name]
8
+ @domain = options[:domain]
9
+ @secure = options[:secure]
10
+ @httponly = options[:httponly]
11
+ end
12
+
13
+ def load options={}
14
+ request = options[:request]
15
+ result = ActiveSupport::HashWithIndifferentAccess.new
16
+ return result if request.blank?
17
+ cookie = request.cookies[@cookie_name]
18
+ return result if cookie.nil? or cookie.empty?
19
+ result.merge!(ActiveSupport::JSON.decode(Zlib::Inflate.inflate(cookie)).stringify_keys)
20
+ end
21
+
22
+ def save options = {}
23
+ attributes = options[:attributes]
24
+ response = options[:response]
25
+
26
+ cookie_json = ActiveSupport::JSON.encode(attributes)
27
+ cookie_json = Zlib::Deflate.deflate(cookie_json, Zlib::BEST_COMPRESSION)
28
+ cookie_hash = { :value => cookie_json,
29
+ :httponly => @httponly,
30
+ :secure => @secure,
31
+ :domain => @domain }
32
+ response.set_cookie(@cookie_name, cookie_hash)
33
+ end
34
+ end
@@ -0,0 +1,32 @@
1
+ require 'msgpack'
2
+
3
+ # Saves form as cookie as json+gzip
4
+ class MonkeyForms::Serializers::MessagePackJson
5
+ def initialize options={}
6
+ @cookie_name = options[:name]
7
+ @domain = options[:domain]
8
+ @secure = options[:secure]
9
+ @httponly = options[:httponly]
10
+ end
11
+
12
+ def load options={}
13
+ request = options[:request]
14
+ result = ActiveSupport::HashWithIndifferentAccess.new
15
+ return result if request.blank?
16
+ cookie = request.cookies[@cookie_name]
17
+ return result if cookie.blank?
18
+ result.merge!(ActiveSupport::JSON.decode(MessagePack.unpack(cookie)).stringify_keys)
19
+ end
20
+
21
+ def save options = {}
22
+ attributes = options[:attributes]
23
+ response = options[:response]
24
+
25
+ cookie_json = ActiveSupport::JSON.encode(attributes).to_msgpack
26
+ cookie_hash = { :value => cookie_json,
27
+ :httponly => @httponly,
28
+ :secure => @secure,
29
+ :domain => @domain }
30
+ response.set_cookie(@cookie_name, cookie_hash)
31
+ end
32
+ end
@@ -0,0 +1,7 @@
1
+
2
+ module MonkeyForms
3
+ module Serializers
4
+ autoload :GzipCookie, 'monkey_forms/serializers/gzip_cookie'
5
+ autoload :MessagePackJson, 'monkey_forms/serializers/message_pack_json'
6
+ end
7
+ end
@@ -0,0 +1,3 @@
1
+ module MonkeyForms
2
+ VERSION = "0.0.15"
3
+ end
@@ -0,0 +1,146 @@
1
+ module MonkeyForms
2
+ require 'monkey_forms/serializers'
3
+ require 'active_model'
4
+ require 'active_support/hash_with_indifferent_access'
5
+ require 'active_support/core_ext/object/try'
6
+ require 'grouped_validations'
7
+ require 'deep_merge'
8
+
9
+ module Form
10
+
11
+ def self.included base
12
+ base.send :include, ActiveModel::Validations
13
+ base.send :extend, ActiveModel::Callbacks
14
+ base.send :include, InstanceMethods
15
+ base.send :extend, ClassMethods
16
+ base.instance_eval do
17
+ define_model_callbacks :initialize
18
+ end
19
+ base.send :include, ActiveModel::Validations
20
+ end
21
+
22
+ module InstanceMethods
23
+ attr_reader :attributes
24
+
25
+ def persisted?
26
+ false
27
+ end
28
+
29
+ # TODO not sure what's best here
30
+ def html_error_messages
31
+ errors.full_messages.join("<br />")
32
+ end
33
+
34
+ def to_model
35
+ self
36
+ end
37
+
38
+ def to_param
39
+ nil
40
+ end
41
+
42
+ def to_key
43
+ nil
44
+ end
45
+
46
+ def initialize options = {}
47
+ _run_initialize_callbacks do
48
+ form_params = options.delete(:form) || {}
49
+ @options = options
50
+
51
+ @options.each do |key, value|
52
+ instance_variable_set "@#{key}", value
53
+ end
54
+
55
+ # Load the saved form from storage
56
+ @attributes =
57
+ if self.class.form_storage
58
+ self.class.form_storage.load(@options)
59
+ else
60
+ ActiveSupport::HashWithIndifferentAccess.new
61
+ end
62
+
63
+ # Merge in this form's params
64
+ DeepMerge.deep_merge!(form_params, @attributes)
65
+
66
+ self.class.attributes.each do |a|
67
+ @attributes[a] ||= ""
68
+ end
69
+ end
70
+ end
71
+
72
+ def save_to_storage!
73
+ @options[:attributes] = @attributes
74
+ self.class.form_storage.save(@options)
75
+ end
76
+
77
+ end
78
+
79
+ module ClassMethods
80
+ attr_reader :form_storage
81
+
82
+ def attributes
83
+ @attributes ||= {}
84
+ end
85
+
86
+ # Compatibility with ActiveModel::Naming
87
+ def model_name
88
+ if !defined?(@_model_name)
89
+ # EWWWW
90
+ @_model_name = (@_form_name.try(:to_s) ||
91
+ superclass.instance_variable_get(:@_form_name).try(:to_s) ||
92
+ name.underscore).try(:underscore)
93
+ %w( singular human i18n_key partial_path plural ).each do |method|
94
+ @_model_name.class_eval do
95
+ define_method method do
96
+ self
97
+ end
98
+ end
99
+ end
100
+ end
101
+ @_model_name
102
+ end
103
+
104
+ def form_name name
105
+ @_form_name = name
106
+ end
107
+
108
+ def set_form_storage storage_object
109
+ @form_storage = storage_object
110
+ end
111
+
112
+ def set_form_attribute_human_names options
113
+ @_form_attribute_names ||= {}
114
+ @_form_attribute_names.merge!(options)
115
+ end
116
+
117
+ def human_attribute_name name, *options
118
+ @_form_attribute_names ||= {}
119
+ @_form_attribute_names[name] || super
120
+ end
121
+
122
+ def form_attributes *attrs
123
+ @attributes ||= []
124
+ attrs.each do |attr|
125
+ @attributes << attr
126
+
127
+ # Defines public method
128
+ define_method attr do
129
+ @attributes[attr.to_s]
130
+ end
131
+ define_method "#{attr}=" do |value|
132
+ @attributes[attr.to_s] = value
133
+ end
134
+ end
135
+ end
136
+
137
+ def custom_attributes *attrs
138
+ attrs.each do |attr|
139
+ instance_eval do
140
+ attr_reader attr
141
+ end
142
+ end
143
+ end
144
+ end
145
+ end
146
+ end
@@ -0,0 +1,31 @@
1
+ # -*- encoding: utf-8 -*-
2
+ $:.push File.expand_path("../lib", __FILE__)
3
+ require "monkey_forms/version"
4
+
5
+ Gem::Specification.new do |s|
6
+ s.name = "monkey_forms"
7
+ s.version = MonkeyForms::VERSION
8
+ s.platform = Gem::Platform::RUBY
9
+ s.authors = ["Joe Van Dyk"]
10
+ s.email = ["joe@tanga.com"]
11
+ s.homepage = "https://github.com/joevandyk/monkey_forms"
12
+ s.summary = %q{Helps make complex forms}
13
+ s.description = %q{Helps make complex forms}
14
+ s.rubyforge_project = "monkey_forms"
15
+
16
+ s.add_dependency('activemodel')
17
+ s.add_dependency('deep_merge')
18
+
19
+ s.add_development_dependency 'minitest'
20
+ s.add_development_dependency 'rake'
21
+ s.add_development_dependency 'sinatra'
22
+ s.add_development_dependency 'rack-test'
23
+ s.add_development_dependency 'shotgun'
24
+ s.add_development_dependency 'haml'
25
+ s.add_development_dependency('msgpack')
26
+
27
+ s.files = `git ls-files`.split("\n")
28
+ s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
29
+ s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
30
+ s.require_paths = ["lib"]
31
+ end
@@ -0,0 +1,8 @@
1
+ require 'monkey_forms'
2
+
3
+ class BasicForm
4
+ include MonkeyForms::Form
5
+ form_attributes :name
6
+ validates :name, :presence => true
7
+ end
8
+
@@ -0,0 +1,54 @@
1
+ require 'monkey_forms'
2
+
3
+ class OrderForm
4
+ include MonkeyForms::Form
5
+ attr_reader :an_attribute
6
+
7
+ # Declares a few attributes on the form.
8
+ form_attributes :name, :email, :city, :state, :line_items
9
+ custom_attributes :user_id
10
+ form_name :cart
11
+
12
+ # This form serializes the submit into a gzip'd cookie with a name
13
+ # of 'order_cookie'.
14
+ set_form_storage(
15
+ MonkeyForms::Serializers::GzipCookie.new(
16
+ :name => 'order_cookie',
17
+ :domain => 'test.domain.com',
18
+ :secure => true,
19
+ :httponly => true))
20
+
21
+ after_initialize :set_attribute, :set_default_state
22
+
23
+ # We must submit an email address for the form to validate.
24
+ validates :email, :presence => true
25
+
26
+ set_form_attribute_human_names :name => "Your Name"
27
+
28
+ validation_group :cart do
29
+ # Scope some of the validation checks
30
+ validates :name, :presence => true
31
+ end
32
+
33
+ validation_group :address do
34
+ validates :city, :presence => true
35
+ validates :state, :presence => true
36
+ end
37
+
38
+ # This is a method that uses some form attributes.
39
+ def person
40
+ "#{ name } <#{ email }>"
41
+ end
42
+
43
+ private
44
+
45
+ def set_attribute
46
+ @an_attribute = true
47
+ end
48
+
49
+ def set_default_state
50
+ if state.blank?
51
+ self.state = "WA"
52
+ end
53
+ end
54
+ end
@@ -0,0 +1,4 @@
1
+ require 'monkey_forms'
2
+ class OrderFormChild < OrderForm
3
+ form_attributes :child
4
+ end
@@ -0,0 +1,5 @@
1
+ require 'bundler'
2
+ require 'bundler/setup'
3
+
4
+ require 'sample_sinatra'
5
+ run SampleSinatra
@@ -0,0 +1,50 @@
1
+ require 'sinatra/base'
2
+ require 'forms/order_form'
3
+
4
+ class SampleSinatra < Sinatra::Base
5
+ #set :show_exceptions, false
6
+
7
+ before do
8
+ load_form
9
+ end
10
+
11
+ get "/" do
12
+ @page = 1
13
+ haml :form
14
+ end
15
+
16
+ get "/2" do
17
+ @page = 2
18
+ haml :form
19
+ end
20
+
21
+ get "/3" do
22
+ @page = 3
23
+ haml :form
24
+ end
25
+
26
+ post "/haml_form" do
27
+ # We could probably do something with the form object here, maybe
28
+ # Tells the form to serialize itself.
29
+ @form.save_to_storage!
30
+ redirect "/"
31
+ end
32
+
33
+ # Only used in unit tests
34
+ post "/form" do
35
+ # Tells the form to serialize itself.
36
+ @form.save_to_storage!
37
+
38
+ # Renders something (used in tests)
39
+ @form.person
40
+ end
41
+
42
+ private
43
+
44
+ def load_form
45
+ @form = OrderForm.new(:form => request.params["form"],
46
+ :request => request,
47
+ :response => response)
48
+ end
49
+ end
50
+
@@ -0,0 +1,25 @@
1
+ %h1 Welcome to Monkey Forms Page #{ @page }
2
+
3
+ %h3
4
+ %a{:href => "/"} Page 1
5
+ |
6
+ %a{:href => "/2"} Page 2
7
+ |
8
+ %a{:href => "/3"} Page 3
9
+
10
+ %h3 Form Values
11
+ = @form.attributes.inspect
12
+
13
+ %p
14
+ As you click from page to page, note that your form
15
+ values are saved. They are saved in a cookie!
16
+
17
+ %form{:action => '/haml_form', :method => 'post'}
18
+ - @form.class.attributes.each do |name|
19
+ %input{:type => 'text', :id => "form_#{name}", :name => "form[#{name}]", :value => @form.send(name)}
20
+ %label{:for => "form_#{name}"}= name
21
+
22
+ %br
23
+
24
+ %input{:type => 'submit'}
25
+
@@ -0,0 +1,182 @@
1
+ require 'minitest/autorun'
2
+ require 'minitest/pride'
3
+ require 'rack/test'
4
+
5
+ require 'sinatra/sample_sinatra'
6
+ require 'forms/order_form'
7
+ require 'forms/order_form_child'
8
+ require 'forms/basic_form'
9
+
10
+ # I want to ensure this library works fine with all of ActiveSupport loaded
11
+ require 'active_support/all'
12
+
13
+ class TestMonkeyForms < MiniTest::Unit::TestCase
14
+ include Rack::Test::Methods
15
+
16
+ def app
17
+ SampleSinatra.new
18
+ end
19
+
20
+ def test_form_post_with_cookie
21
+ post "https://test.domain.com/form", :form => { :name => "Joe" }
22
+ assert_equal "Joe <>", last_response.body
23
+ post "https://test.domain.com/form", :form => { :email => "joe@tanga.com" }
24
+ assert_equal "Joe <joe@tanga.com>", last_response.body
25
+ end
26
+
27
+ def test_attribute_name
28
+ o = OrderForm.new
29
+ o.valid?
30
+ assert o.errors.full_messages.include?("Your Name can't be blank")
31
+ end
32
+
33
+ def test_form_works_without_human_names_set
34
+ o = BasicForm.new
35
+ o.valid?
36
+ assert o.errors.full_messages.include?("Name can't be blank")
37
+ end
38
+
39
+ def test_form_cookie
40
+ submit_form :name => "joe"
41
+ # TODO figure out how to get test the cookie stuff properly
42
+ assert last_response.headers["Set-Cookie"].include?("HttpOnly")
43
+ assert last_response.headers["Set-Cookie"].include?("secure")
44
+ assert last_response.headers["Set-Cookie"].include?("test.domain.com")
45
+ end
46
+
47
+ def test_setters_from_inside_form
48
+ a = submit_form :name => 'joe'
49
+ assert_equal 'WA', a[:state]
50
+ end
51
+
52
+ def test_child_form
53
+ o = OrderFormChild.new :form => { :child => 'new', :name => 'joe' }
54
+ assert_equal 'new', o.child
55
+ assert_equal 'joe', o.name
56
+
57
+ assert_equal 'cart', o.class.model_name
58
+ end
59
+
60
+ def test_basic
61
+ o = OrderForm.new :form => { :name => "Joe", :email => "joe@tanga.com" }
62
+ assert_equal "Joe", o.name
63
+ assert_equal "joe@tanga.com", o.email
64
+ assert_equal "", o.city
65
+ assert_equal 5, o.attributes.size
66
+ assert_equal "Joe", o.attributes[:name]
67
+ assert_equal "Joe", o.attributes["name"]
68
+ end
69
+
70
+ def test_validation
71
+ o = OrderForm.new :form => { :name => "Joe" }
72
+ o.valid?
73
+ assert_equal ["can't be blank"], o.errors[:email]
74
+ end
75
+
76
+ def test_validation_before_valid_called
77
+ o = OrderForm.new
78
+ assert_equal [], o.errors[:name]
79
+ assert_equal [], o.errors[:email]
80
+ end
81
+
82
+ def test_html_errors
83
+ o = OrderForm.new
84
+ o.valid?
85
+ assert o.html_error_messages.include?("City can't be blank")
86
+ end
87
+
88
+ def test_validation_scope_after_valid_called
89
+ o = OrderForm.new
90
+ refute o.valid?
91
+ assert ["can't be blank"], o.errors[:name]
92
+ assert ["can't be blank"], o.errors[:email]
93
+ end
94
+
95
+ def test_group_validation
96
+ o = OrderForm.new
97
+ refute o.group_valid?(:cart)
98
+ assert_equal ["can't be blank"], o.errors[:name]
99
+ assert_equal [], o.errors[:email]
100
+
101
+ o.valid?
102
+ assert_equal ["can't be blank"], o.errors[:email]
103
+ end
104
+
105
+ def test_after_initialize
106
+ o = OrderForm.new
107
+ assert o.an_attribute
108
+ end
109
+
110
+ def test_set_custom_attributes
111
+ o = OrderForm.new :user_id => 1
112
+ assert_equal 1, o.user_id
113
+ end
114
+
115
+ def test_can_access_attributes
116
+ o = OrderForm.new :form => { :email => "joe@tanga.com" , :name => "Joe" }
117
+ assert_equal "Joe <joe@tanga.com>", o.person
118
+ end
119
+
120
+ def test_array
121
+ submit_form(:line_items => [ {:id => "previous"}])
122
+ attributes = submit_form(:line_items => [ {:id => "new"}])
123
+
124
+ assert_equal 2, attributes[:line_items].size
125
+ assert_equal "previous", attributes[:line_items].first[:id]
126
+ assert_equal "new", attributes[:line_items].last[:id]
127
+ end
128
+
129
+ def test_array_update
130
+ submit_form(:line_items => [ {:id => "first", :quantity => 1}])
131
+ attributes = submit_form(:line_items => [ {:id => "first", :quantity => 3}])
132
+ assert_equal "3", attributes[:line_items].last[:quantity]
133
+ end
134
+
135
+ def test_submit_blank
136
+ a = submit_form(:name => "Joe", :city => "Seattle")
137
+ assert_equal "Joe", a[:name]
138
+
139
+ a = submit_form(:name => "", :city => "Seattle")
140
+ assert_equal "", a[:name]
141
+ end
142
+
143
+
144
+ def extract_attributes request
145
+ serializer = MonkeyForms::Serializers::GzipCookie.new(:name => "order_cookie")
146
+ serializer.load(:request => request)
147
+ end
148
+
149
+ def submit_form attributes
150
+ post "https://test.domain.com/form", :form => attributes
151
+ post "https://test.domain.com/form", :form => {} # not sure why the cookies don't get set in last_request without this
152
+ extract_attributes last_request
153
+ end
154
+ end
155
+
156
+ class TestMonkeyFormsActiveModelLint < MiniTest::Unit::TestCase
157
+ include ActiveModel::Lint::Tests
158
+
159
+ def setup
160
+ @model = OrderForm.new
161
+ end
162
+
163
+ def test_form_name
164
+ assert_equal "cart", @model.class.model_name
165
+ end
166
+ end
167
+
168
+ class TestMonkeyFormsBasic < MiniTest::Unit::TestCase
169
+ include ActiveModel::Lint::Tests
170
+
171
+ def setup
172
+ @model = BasicForm.new
173
+ end
174
+
175
+ def test_form_name
176
+ assert_equal "basic_form", @model.class.model_name
177
+ end
178
+
179
+ def test_attributes
180
+ assert_equal @model.attributes, {"name" => ""}
181
+ end
182
+ end
metadata ADDED
@@ -0,0 +1,179 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: monkey_forms
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.15
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - Joe Van Dyk
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2011-07-03 00:00:00.000000000 -07:00
13
+ default_executable:
14
+ dependencies:
15
+ - !ruby/object:Gem::Dependency
16
+ name: activemodel
17
+ requirement: &2165026280 !ruby/object:Gem::Requirement
18
+ none: false
19
+ requirements:
20
+ - - ! '>='
21
+ - !ruby/object:Gem::Version
22
+ version: '0'
23
+ type: :runtime
24
+ prerelease: false
25
+ version_requirements: *2165026280
26
+ - !ruby/object:Gem::Dependency
27
+ name: deep_merge
28
+ requirement: &2165025680 !ruby/object:Gem::Requirement
29
+ none: false
30
+ requirements:
31
+ - - ! '>='
32
+ - !ruby/object:Gem::Version
33
+ version: '0'
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: *2165025680
37
+ - !ruby/object:Gem::Dependency
38
+ name: minitest
39
+ requirement: &2165025120 !ruby/object:Gem::Requirement
40
+ none: false
41
+ requirements:
42
+ - - ! '>='
43
+ - !ruby/object:Gem::Version
44
+ version: '0'
45
+ type: :development
46
+ prerelease: false
47
+ version_requirements: *2165025120
48
+ - !ruby/object:Gem::Dependency
49
+ name: rake
50
+ requirement: &2165024680 !ruby/object:Gem::Requirement
51
+ none: false
52
+ requirements:
53
+ - - ! '>='
54
+ - !ruby/object:Gem::Version
55
+ version: '0'
56
+ type: :development
57
+ prerelease: false
58
+ version_requirements: *2165024680
59
+ - !ruby/object:Gem::Dependency
60
+ name: sinatra
61
+ requirement: &2165024140 !ruby/object:Gem::Requirement
62
+ none: false
63
+ requirements:
64
+ - - ! '>='
65
+ - !ruby/object:Gem::Version
66
+ version: '0'
67
+ type: :development
68
+ prerelease: false
69
+ version_requirements: *2165024140
70
+ - !ruby/object:Gem::Dependency
71
+ name: rack-test
72
+ requirement: &2165023560 !ruby/object:Gem::Requirement
73
+ none: false
74
+ requirements:
75
+ - - ! '>='
76
+ - !ruby/object:Gem::Version
77
+ version: '0'
78
+ type: :development
79
+ prerelease: false
80
+ version_requirements: *2165023560
81
+ - !ruby/object:Gem::Dependency
82
+ name: shotgun
83
+ requirement: &2165022960 !ruby/object:Gem::Requirement
84
+ none: false
85
+ requirements:
86
+ - - ! '>='
87
+ - !ruby/object:Gem::Version
88
+ version: '0'
89
+ type: :development
90
+ prerelease: false
91
+ version_requirements: *2165022960
92
+ - !ruby/object:Gem::Dependency
93
+ name: haml
94
+ requirement: &2162564820 !ruby/object:Gem::Requirement
95
+ none: false
96
+ requirements:
97
+ - - ! '>='
98
+ - !ruby/object:Gem::Version
99
+ version: '0'
100
+ type: :development
101
+ prerelease: false
102
+ version_requirements: *2162564820
103
+ - !ruby/object:Gem::Dependency
104
+ name: msgpack
105
+ requirement: &2162564280 !ruby/object:Gem::Requirement
106
+ none: false
107
+ requirements:
108
+ - - ! '>='
109
+ - !ruby/object:Gem::Version
110
+ version: '0'
111
+ type: :development
112
+ prerelease: false
113
+ version_requirements: *2162564280
114
+ description: Helps make complex forms
115
+ email:
116
+ - joe@tanga.com
117
+ executables: []
118
+ extensions: []
119
+ extra_rdoc_files: []
120
+ files:
121
+ - .gitignore
122
+ - BUGS
123
+ - Gemfile
124
+ - NOTES
125
+ - README.md
126
+ - Rakefile
127
+ - lib/monkey_forms.rb
128
+ - lib/monkey_forms/serializers.rb
129
+ - lib/monkey_forms/serializers/active_record_session.rb
130
+ - lib/monkey_forms/serializers/gzip_cookie.rb
131
+ - lib/monkey_forms/serializers/message_pack_json.rb
132
+ - lib/monkey_forms/version.rb
133
+ - monkey_forms.gemspec
134
+ - test/forms/basic_form.rb
135
+ - test/forms/order_form.rb
136
+ - test/forms/order_form_child.rb
137
+ - test/sinatra/config.ru
138
+ - test/sinatra/sample_sinatra.rb
139
+ - test/sinatra/views/form.haml
140
+ - test/test_monkey_forms.rb
141
+ has_rdoc: true
142
+ homepage: https://github.com/joevandyk/monkey_forms
143
+ licenses: []
144
+ post_install_message:
145
+ rdoc_options: []
146
+ require_paths:
147
+ - lib
148
+ required_ruby_version: !ruby/object:Gem::Requirement
149
+ none: false
150
+ requirements:
151
+ - - ! '>='
152
+ - !ruby/object:Gem::Version
153
+ version: '0'
154
+ segments:
155
+ - 0
156
+ hash: -2757128949908824304
157
+ required_rubygems_version: !ruby/object:Gem::Requirement
158
+ none: false
159
+ requirements:
160
+ - - ! '>='
161
+ - !ruby/object:Gem::Version
162
+ version: '0'
163
+ segments:
164
+ - 0
165
+ hash: -2757128949908824304
166
+ requirements: []
167
+ rubyforge_project: monkey_forms
168
+ rubygems_version: 1.6.2
169
+ signing_key:
170
+ specification_version: 3
171
+ summary: Helps make complex forms
172
+ test_files:
173
+ - test/forms/basic_form.rb
174
+ - test/forms/order_form.rb
175
+ - test/forms/order_form_child.rb
176
+ - test/sinatra/config.ru
177
+ - test/sinatra/sample_sinatra.rb
178
+ - test/sinatra/views/form.haml
179
+ - test/test_monkey_forms.rb