form_assistant 1.0.0

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.
@@ -0,0 +1,16 @@
1
+ module RPH
2
+ module FormAssistant
3
+ # class used to DRY up error handling
4
+ class Error < RuntimeError
5
+ def self.message(msg=nil)
6
+ msg.nil? ? @message : self.message = msg
7
+ end
8
+
9
+ def self.message=(msg)
10
+ @message = msg
11
+ end
12
+ end
13
+
14
+ # custom errors go here
15
+ end
16
+ end
@@ -0,0 +1,27 @@
1
+ module RPH
2
+ module FormAssistant
3
+ # extensions for formatting error messages
4
+ #
5
+ # Ex: <%= errors %>
6
+ # <%= errors.to_s(:break => true) %>
7
+ # <%= errors.to_list %>
8
+ # <%= errors.to_list(:class => 'errorz') %>
9
+ class FieldErrors < Array
10
+ def to_s(options = {})
11
+ return self.join('<br />') if options[:break]
12
+ self.to_sentence
13
+ end
14
+
15
+ # converts an array into an unordered list
16
+ def to_list(options = {})
17
+ css_class = options.delete(:class) || 'errors'
18
+
19
+ list_items = self.inject("") do |items, error|
20
+ items << "<li>#{error}</li>"
21
+ end
22
+
23
+ return '<ul class="%s">%s</ul>' % [css_class, list_items]
24
+ end
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,17 @@
1
+ module RPH
2
+ module FormAssistant
3
+ private
4
+ # used to assist generic logic throughout FormAssistant
5
+ class Rules
6
+ # used mainly for #concat() so that this plugin will
7
+ # work with versions of Rails other than edge
8
+ def self.binding_required?
9
+ !!( Rails.version < '2.2.0' )
10
+ end
11
+
12
+ def self.has_I18n_support?
13
+ !!( Rails.version > '2.2.0' )
14
+ end
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,18 @@
1
+ desc "copies basic form templates to app/views/forms"
2
+ namespace :form_assistant do
3
+ task :install do
4
+ PLUGIN_ROOT = File.join(File.dirname(__FILE__), '..')
5
+ DESTINATION = File.join(Rails.root, 'app/views', 'forms')
6
+
7
+ FileUtils.mkpath(DESTINATION) unless File.directory?(DESTINATION)
8
+ forms = Dir[File.join(PLUGIN_ROOT, 'forms/*')].select { |f| File.file?(f) }
9
+ longest_filename = forms.inject([]) { |sizes, f| sizes << f.gsub(PLUGIN_ROOT, '').length }.max
10
+
11
+ forms.each do |partial|
12
+ file_to_copy = File.join(DESTINATION, '/', File.basename(partial))
13
+ puts " - form_assistant%-#{longest_filename}s copied to %s" %
14
+ [partial.gsub(PLUGIN_ROOT, ''), DESTINATION.gsub(Rails.root, '')]
15
+ FileUtils.cp [partial], DESTINATION
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,14 @@
1
+ <div class="widget">
2
+ <div class="label">
3
+ <%= label %>
4
+ </div>
5
+ <div class="tip">
6
+ <%= tip %>
7
+ </div>
8
+ <div class="element">
9
+ <%= element %>
10
+ </div>
11
+ <div class="errors">
12
+ <%= errors %>
13
+ </div>
14
+ </div>
@@ -0,0 +1,4 @@
1
+ <h2><%= legend %></h2>
2
+ <div class="fieldset">
3
+ <%= fields %>
4
+ </div>
@@ -0,0 +1,5 @@
1
+ <%= label %>
2
+ <p>
3
+ <%= element %> <span><%= tip %></span><br />
4
+ <%= errors %>
5
+ </p>
@@ -0,0 +1,14 @@
1
+ <div class="widget">
2
+ <div class="label">
3
+ <%= label %>
4
+ </div>
5
+ <div class="tip">
6
+ <%= tip %>
7
+ </div>
8
+ <div class="element">
9
+ <%= element %>
10
+ </div>
11
+ <div class="errors">
12
+ <%= errors %>
13
+ </div>
14
+ </div>
data/test/helper.rb ADDED
@@ -0,0 +1,28 @@
1
+ require 'rubygems'
2
+ require 'bundler'
3
+ begin
4
+ Bundler.setup(:default, :development)
5
+ rescue Bundler::BundlerError => e
6
+ $stderr.puts e.message
7
+ $stderr.puts "Run `bundle install` to install missing gems"
8
+ exit e.status_code
9
+ end
10
+
11
+ require 'test/unit'
12
+
13
+ $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
14
+ $LOAD_PATH.unshift(File.dirname(__FILE__))
15
+ ENV["RAILS_ENV"] ||= "test"
16
+ $:.unshift(File.join(File.dirname(__FILE__), *%w[../lib]))
17
+
18
+ require 'ostruct'
19
+ require 'active_support'
20
+ require 'action_controller'
21
+ # require 'action_controller/test_process'
22
+ # require 'action_view/test_case'
23
+ require 'active_record'
24
+
25
+ require 'mocha'
26
+ require 'mock_rails'
27
+ require 'form_assistant'
28
+
@@ -0,0 +1,27 @@
1
+ unless Object.const_defined?(:Rails)
2
+ class Rails
3
+ class << self
4
+ attr_accessor :root, :version
5
+
6
+ def root
7
+ @root ||= File.dirname(__FILE__)
8
+ end
9
+
10
+ def version
11
+ @version ||= '2.2.2'
12
+ end
13
+
14
+ def configuration
15
+ @configuration ||= Configuration.new
16
+ end
17
+ end
18
+
19
+ class Configuration
20
+ attr_accessor :view_path
21
+
22
+ def view_path
23
+ @view_path ||= ''
24
+ end
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,25 @@
1
+ require 'helper'
2
+
3
+ class FieldErrorsTest < ActiveSupport::TestCase
4
+ def setup
5
+ @errors = RPH::FormAssistant::FieldErrors.new(%w(A B C))
6
+ end
7
+
8
+ test "should return errors as sentence" do
9
+ assert_equal 'A, B, and C', @errors.to_s
10
+ end
11
+
12
+ test "should return errors with breaks" do
13
+ assert_equal 'A<br />B<br />C', @errors.to_s(:break => true)
14
+ end
15
+
16
+ test "should return errors as list" do
17
+ assert_equal '<ul class="errors"><li>A</li><li>B</li><li>C</li></ul>',
18
+ @errors.to_list
19
+ end
20
+
21
+ test "should return errors as list with custom class" do
22
+ assert_equal '<ul class="problems"><li>A</li><li>B</li><li>C</li></ul>',
23
+ @errors.to_list(:class => 'problems')
24
+ end
25
+ end
@@ -0,0 +1,205 @@
1
+ require 'helper'
2
+
3
+ module FormAssistantHelpers
4
+ attr_accessor :render_options
5
+ attr_accessor :view
6
+ attr_accessor :response
7
+
8
+ def view
9
+ @view ||= ActionView::Base.new(Rails.configuration.view_path)
10
+ end
11
+
12
+ def render(options={})
13
+ self.render_options = options
14
+ @response = view.render(options)
15
+ end
16
+
17
+ def locals
18
+ render_options[:locals] rescue {}
19
+ end
20
+
21
+ def expect_render(expected={})
22
+ assert_hash_includes expected, render_options
23
+ end
24
+
25
+ def assert_hash_includes(expected, actual)
26
+ expected.each do |k, v|
27
+ assert_equal v, actual[k]
28
+ end
29
+ end
30
+
31
+ def expect_locals(expected={})
32
+ assert_hash_includes expected, locals
33
+ end
34
+
35
+ def template_root
36
+ RPH::FormAssistant::FormBuilder.template_root
37
+ end
38
+
39
+ def template_path(name)
40
+ File.join(template_root, name) + '.html.erb'
41
+ end
42
+ end
43
+
44
+ class AddressBook < ActiveRecord::Base
45
+ class Column
46
+ attr_accessor :name, :type
47
+ def initialize(name, type)
48
+ @name, @type = name, type
49
+ end
50
+ end
51
+
52
+ attr_accessor :first_name, :nickname,
53
+ :day, :month, :year, :is_boy,
54
+ :created_at
55
+
56
+ def self.columns
57
+ {}
58
+ end
59
+
60
+ def self.columns_hash
61
+ [ Column.new('first_name', :string),
62
+ Column.new('is_boy', :boolean),
63
+ Column.new('created_at', :datetime)
64
+ ].index_by(&:name)
65
+ end
66
+ end
67
+
68
+ class FormAssistantTest < ActionView::TestCase
69
+ include FormAssistantHelpers
70
+ include ::RPH::FormAssistant::ActionView
71
+ attr_accessor :form
72
+
73
+ def setup
74
+ Rails.configuration.view_path = File.expand_path(File.dirname(__FILE__))
75
+
76
+ @address_book = AddressBook.new
77
+ @form = RPH::FormAssistant::FormBuilder.new(:address_book, @address_book, self, {}, nil)
78
+ RPH::FormAssistant::FormBuilder.template_root = File.expand_path(File.join(File.dirname(__FILE__), 'forms'))
79
+ end
80
+
81
+ test "should use template based on input type" do
82
+ form.text_field :first_name
83
+ expect_render :partial => template_path('text_field')
84
+ end
85
+
86
+ test "should use fallback template if no specific template is found" do
87
+ form.text_field :first_name, :template => 'fancy_template_that_does_not_exist'
88
+ expect_render :partial => template_path(form.fallback_template)
89
+ end
90
+
91
+ test "should render a valid field" do
92
+ form.text_field :first_name
93
+ expect_locals :errors => nil
94
+ end
95
+
96
+ test "should render an invalid field" do
97
+ @address_book.errors.add(:first_name, 'cannot be root')
98
+ form.text_field :first_name
99
+ expect_locals :errors => ['First name cannot be root']
100
+ assert_kind_of RPH::FormAssistant::FieldErrors, locals[:errors]
101
+ end
102
+
103
+ test "should render a field with a tip" do
104
+ form.text_field :nickname, :tip => 'What should we call you?'
105
+ expect_locals :tip => 'What should we call you?'
106
+ end
107
+
108
+ test "should render a field without a template" do
109
+ result = form.text_field(:nickname, :template => false)
110
+ assert_equal text_field(:address_book, :nickname), result
111
+ end
112
+
113
+ test "should create fieldset" do
114
+ fieldset('Information') { "fields-go-here" }
115
+ expect_render :partial => template_path('fieldset')
116
+ expect_locals :legend => 'Information',
117
+ :fields => 'fields-go-here'
118
+ end
119
+
120
+ test "should support I18n if available" do
121
+ if Object.const_defined?(:I18n)
122
+ I18n.backend = I18n::Backend::Simple.new
123
+ I18n.backend.store_translations 'en', :activerecord => {
124
+ :attributes => {
125
+ :address_book => {
126
+ :first_name => 'Given name'
127
+ }
128
+ }
129
+ }
130
+
131
+ @address_book.errors.add(:first_name, 'cannot be root')
132
+ @address_book.errors.add(:first_name, 'cannot be admin')
133
+ form.text_field :first_name
134
+ expect_locals :errors => ['Given name cannot be root', 'Given name cannot be admin']
135
+ end
136
+ end
137
+
138
+ test "should massage error messages when I18n isn't not available" do
139
+ RPH::FormAssistant::Rules.expects(:has_I18n_support?).returns(false)
140
+ @address_book.errors.add(:first_name, 'cannot be root')
141
+ @address_book.errors.add(:first_name, 'cannot be admin')
142
+ form.text_field :first_name
143
+ expect_locals :errors => ['First name cannot be root', 'First name cannot be admin']
144
+ end
145
+
146
+ test "should create widget" do
147
+ @address_book.errors.add(:birthday, 'is invalid')
148
+
149
+ form.widget :birthday, :tip => 'Enter your birthday' do
150
+ concat @day = form.select(:day, (1..31))
151
+ concat @month = form.select(:month, (1..12))
152
+ concat @year = form.select(:year, (1975...1985))
153
+ end
154
+
155
+ expect_locals :element => (@day + @month + @year),
156
+ :errors => ['Birthday is invalid'],
157
+ :tip => 'Enter your birthday',
158
+ :helper => 'widget'
159
+
160
+ expect_render :partial => template_path('field')
161
+ end
162
+
163
+ test "should create widget with multiple fields" do
164
+ @address_book.errors.add(:first_name, 'cannot be root')
165
+ @address_book.errors.add(:nickname, 'cannot be batman')
166
+
167
+ form.widget([:first_name, :nickname], :label => 'Names') do
168
+ concat @first_name = form.text_field(:first_name)
169
+ concat @nickname = form.text_field(:nickname)
170
+ end
171
+
172
+ expect_locals :element => (@first_name + @nickname),
173
+ :errors => [
174
+ 'First name cannot be root',
175
+ 'Nickname cannot be batman'
176
+ ],
177
+ :helper => 'widget'
178
+
179
+ expect_render :partial => template_path('field')
180
+ end
181
+
182
+ test "should pass extra locals" do
183
+ form.text_field :first_name, :locals => { :nickname => true }
184
+ expect_locals :nickname => true
185
+ end
186
+
187
+ test 'should create proper fields with #input' do
188
+ form.expects(:text_field).with(:first_name)
189
+ form.input :first_name
190
+
191
+ form.expects(:check_box).with(:is_boy)
192
+ form.input :is_boy
193
+
194
+ form.expects(:datetime_select).with(:created_at)
195
+ form.input :created_at
196
+ end
197
+
198
+ test 'should create many fields with #inputs' do
199
+ options = { :required => true }
200
+ form.expects(:text_field).with(:first_name, options)
201
+ form.expects(:check_box).with(:is_boy, options)
202
+ form.expects(:datetime_select).with(:created_at, options)
203
+ form.inputs :first_name, :is_boy, :created_at, options
204
+ end
205
+ end
data/uninstall.rb ADDED
@@ -0,0 +1 @@
1
+ # Uninstall hook code here
metadata ADDED
@@ -0,0 +1,235 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: form_assistant
3
+ version: !ruby/object:Gem::Version
4
+ hash: 23
5
+ prerelease:
6
+ segments:
7
+ - 1
8
+ - 0
9
+ - 0
10
+ version: 1.0.0
11
+ platform: ruby
12
+ authors:
13
+ - Ryan Heath
14
+ - Chris Scharf
15
+ autorequire:
16
+ bindir: bin
17
+ cert_chain: []
18
+
19
+ date: 2012-07-06 00:00:00 -04:00
20
+ default_executable:
21
+ dependencies:
22
+ - !ruby/object:Gem::Dependency
23
+ prerelease: false
24
+ requirement: &id001 !ruby/object:Gem::Requirement
25
+ none: false
26
+ requirements:
27
+ - - "="
28
+ - !ruby/object:Gem::Version
29
+ hash: 49
30
+ segments:
31
+ - 0
32
+ - 8
33
+ - 7
34
+ version: 0.8.7
35
+ type: :runtime
36
+ name: rake
37
+ version_requirements: *id001
38
+ - !ruby/object:Gem::Dependency
39
+ prerelease: false
40
+ requirement: &id002 !ruby/object:Gem::Requirement
41
+ none: false
42
+ requirements:
43
+ - - ~>
44
+ - !ruby/object:Gem::Version
45
+ hash: 5
46
+ segments:
47
+ - 2
48
+ - 3
49
+ version: "2.3"
50
+ type: :development
51
+ name: activesupport
52
+ version_requirements: *id002
53
+ - !ruby/object:Gem::Dependency
54
+ prerelease: false
55
+ requirement: &id003 !ruby/object:Gem::Requirement
56
+ none: false
57
+ requirements:
58
+ - - ~>
59
+ - !ruby/object:Gem::Version
60
+ hash: 5
61
+ segments:
62
+ - 2
63
+ - 3
64
+ version: "2.3"
65
+ type: :development
66
+ name: actionpack
67
+ version_requirements: *id003
68
+ - !ruby/object:Gem::Dependency
69
+ prerelease: false
70
+ requirement: &id004 !ruby/object:Gem::Requirement
71
+ none: false
72
+ requirements:
73
+ - - ~>
74
+ - !ruby/object:Gem::Version
75
+ hash: 5
76
+ segments:
77
+ - 2
78
+ - 3
79
+ version: "2.3"
80
+ type: :development
81
+ name: activerecord
82
+ version_requirements: *id004
83
+ - !ruby/object:Gem::Dependency
84
+ prerelease: false
85
+ requirement: &id005 !ruby/object:Gem::Requirement
86
+ none: false
87
+ requirements:
88
+ - - ~>
89
+ - !ruby/object:Gem::Version
90
+ hash: 31
91
+ segments:
92
+ - 3
93
+ - 12
94
+ version: "3.12"
95
+ type: :development
96
+ name: rdoc
97
+ version_requirements: *id005
98
+ - !ruby/object:Gem::Dependency
99
+ prerelease: false
100
+ requirement: &id006 !ruby/object:Gem::Requirement
101
+ none: false
102
+ requirements:
103
+ - - ">="
104
+ - !ruby/object:Gem::Version
105
+ hash: 23
106
+ segments:
107
+ - 1
108
+ - 0
109
+ - 0
110
+ version: 1.0.0
111
+ type: :development
112
+ name: bundler
113
+ version_requirements: *id006
114
+ - !ruby/object:Gem::Dependency
115
+ prerelease: false
116
+ requirement: &id007 !ruby/object:Gem::Requirement
117
+ none: false
118
+ requirements:
119
+ - - ~>
120
+ - !ruby/object:Gem::Version
121
+ hash: 63
122
+ segments:
123
+ - 1
124
+ - 8
125
+ - 4
126
+ version: 1.8.4
127
+ type: :development
128
+ name: jeweler
129
+ version_requirements: *id007
130
+ - !ruby/object:Gem::Dependency
131
+ prerelease: false
132
+ requirement: &id008 !ruby/object:Gem::Requirement
133
+ none: false
134
+ requirements:
135
+ - - ">="
136
+ - !ruby/object:Gem::Version
137
+ hash: 3
138
+ segments:
139
+ - 0
140
+ version: "0"
141
+ type: :development
142
+ name: rcov
143
+ version_requirements: *id008
144
+ - !ruby/object:Gem::Dependency
145
+ prerelease: false
146
+ requirement: &id009 !ruby/object:Gem::Requirement
147
+ none: false
148
+ requirements:
149
+ - - ">="
150
+ - !ruby/object:Gem::Version
151
+ hash: 3
152
+ segments:
153
+ - 0
154
+ version: "0"
155
+ type: :development
156
+ name: mocha
157
+ version_requirements: *id009
158
+ description: Custom form builder that attempts to make your forms friendly
159
+ email: scharfie@gmail.com
160
+ executables: []
161
+
162
+ extensions: []
163
+
164
+ extra_rdoc_files:
165
+ - LICENSE.txt
166
+ - README.textile
167
+ files:
168
+ - Gemfile
169
+ - Gemfile.lock
170
+ - LICENSE.txt
171
+ - README.textile
172
+ - Rakefile
173
+ - VERSION
174
+ - autotest/discover.rb
175
+ - autotest/testunit.rb
176
+ - forms/_check_box.html.erb
177
+ - forms/_field.html.erb
178
+ - forms/_fieldset.html.erb
179
+ - forms/_file_field.html.erb
180
+ - forms/_password_field.html.erb
181
+ - forms/_radio_button.html.erb
182
+ - forms/_text_area.html.erb
183
+ - forms/_text_field.html.erb
184
+ - init.rb
185
+ - install.rb
186
+ - lib/form_assistant.rb
187
+ - lib/form_assistant/error.rb
188
+ - lib/form_assistant/field_errors.rb
189
+ - lib/form_assistant/rules.rb
190
+ - tasks/form_assistant_tasks.rake
191
+ - test/forms/_field.html.erb
192
+ - test/forms/_fieldset.html.erb
193
+ - test/forms/_text_field.html.erb
194
+ - test/forms/_widget.html.erb
195
+ - test/helper.rb
196
+ - test/mock_rails.rb
197
+ - test/test_field_errors.rb
198
+ - test/test_form_assistant.rb
199
+ - uninstall.rb
200
+ has_rdoc: true
201
+ homepage: http://github.com/scharfie/form_assistant
202
+ licenses:
203
+ - MIT
204
+ post_install_message:
205
+ rdoc_options: []
206
+
207
+ require_paths:
208
+ - lib
209
+ required_ruby_version: !ruby/object:Gem::Requirement
210
+ none: false
211
+ requirements:
212
+ - - ">="
213
+ - !ruby/object:Gem::Version
214
+ hash: 3
215
+ segments:
216
+ - 0
217
+ version: "0"
218
+ required_rubygems_version: !ruby/object:Gem::Requirement
219
+ none: false
220
+ requirements:
221
+ - - ">="
222
+ - !ruby/object:Gem::Version
223
+ hash: 3
224
+ segments:
225
+ - 0
226
+ version: "0"
227
+ requirements: []
228
+
229
+ rubyforge_project:
230
+ rubygems_version: 1.4.2
231
+ signing_key:
232
+ specification_version: 3
233
+ summary: Custom form builder that attempts to make your forms friendly
234
+ test_files: []
235
+