formative 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,5 @@
1
+ lib/**/*.rb
2
+ bin/*
3
+ -
4
+ features/**/*.feature
5
+ LICENSE.txt
data/.rspec ADDED
@@ -0,0 +1 @@
1
+ --color
data/Gemfile ADDED
@@ -0,0 +1,11 @@
1
+ source "http://rubygems.org"
2
+
3
+ gem "actionpack"
4
+
5
+ group :development do
6
+ gem "rspec", "~> 2.3.0"
7
+ gem "yard", "~> 0.6.0"
8
+ gem "bundler", "~> 1.0.0"
9
+ gem "jeweler", "~> 1.5.2"
10
+ gem "rcov", ">= 0"
11
+ end
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2011 Martin Rehfeld
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,77 @@
1
+ = Formative
2
+
3
+ Formative is an extraction of the custom form builder I used in my last couple of Rails projects. It is the simplest thing that could possibly work for me. YMMV.
4
+
5
+ I am packaging this as a gem mainly for my personal use. So do not expect this to be any of well-documented, stable or refined.
6
+
7
+ == Usage
8
+
9
+ I am using Formative together with this initializer to enable inline error messages:
10
+
11
+ # Show error messages next to form field labels
12
+ ActionView::Base.field_error_proc = Proc.new {|html_tag, instance_tag|
13
+ if html_tag =~ /type="hidden"/ || !(html_tag =~ /<label/)
14
+ html_tag
15
+ else
16
+ %(<span class="field-with-errors">#{html_tag} <span class="error-message">#{[instance_tag.error_message].flatten.first}</span></span>).html_safe
17
+ end
18
+ }
19
+
20
+ Then just use `Formative::FormBuilder` as your builder -- here is an example form (haml):
21
+
22
+ = form_for :resource, :builder => Formative::FormBuilder do |f|
23
+ %fieldset
24
+ %legend Request Form
25
+
26
+ = f.text_field :bananas, :unit => 'kg'
27
+ :hint => 'Enter the amount of bananas in kg you would like to eat right now'
28
+
29
+ .controls
30
+ = f.submit 'Request', :disable_with => 'Request'
31
+ %p.cancel= link_to 'Cancel', resource_path(@resource)
32
+
33
+ The generated markup would look something like this:
34
+
35
+ <form action="/resource" method="post">
36
+ <fieldset>
37
+ <legend>Request Form</legend>
38
+
39
+ <p class="field text-field bananas">
40
+ <label for="resource_bananas">Bananas</label>
41
+ <input id="resource_bananas" name="resource[bananas]" type="text">
42
+ <span class="unit">kg</span>
43
+ <span class="hint">Enter the amount of bananas in kg you would like to eat right now</span>
44
+ </p>
45
+ </fieldset>
46
+
47
+ <div class="controls">
48
+ <input data-disable-with="Request" id="resource_submit" name="commit" type="submit" value="Request">
49
+ <p class="cancel">
50
+ <a href="/resource">Cancel</a>
51
+ </p>
52
+ </div>
53
+ </form>
54
+
55
+ You can customize the markup for each field with these options:
56
+
57
+ Option Default Possible Value(s)
58
+ :wrapper :p Symbol to specify alternate tag or false to suppress wrapper
59
+ :label true false to suppress label
60
+ :required false/auto true will add "required" as a class to the label
61
+ :label_class auto specify a class for the label directly
62
+ :hint false hint text
63
+ :unit false unit text
64
+
65
+ == Contributing to formative (if you want to help make it a real Gem)
66
+
67
+ * Check out the latest master to make sure the feature hasn't been implemented or the bug hasn't been fixed yet
68
+ * Check out the issue tracker to make sure someone already hasn't requested it and/or contributed it
69
+ * Fork the project
70
+ * Start a feature/bugfix branch
71
+ * Commit and push until you are happy with your contribution
72
+ * Make sure to add tests for it. This is important so I don't break it in a future version unintentionally.
73
+ * Please try not to mess with the Rakefile, version, or history. If you want to have your own version, or is otherwise necessary, that is fine, but please isolate to its own commit so I can cherry-pick around it.
74
+
75
+ == Copyright
76
+
77
+ Copyright (c) 2011 Martin Rehfeld. See MIT-LICENSE for further details.
@@ -0,0 +1,41 @@
1
+ # encoding: utf-8
2
+
3
+ require 'rubygems'
4
+ require 'bundler'
5
+ begin
6
+ Bundler.setup(:default, :development)
7
+ rescue Bundler::BundlerError => e
8
+ $stderr.puts e.message
9
+ $stderr.puts "Run `bundle install` to install missing gems"
10
+ exit e.status_code
11
+ end
12
+ require 'rake'
13
+
14
+ require 'jeweler'
15
+ Jeweler::Tasks.new do |gem|
16
+ # gem is a Gem::Specification... see http://docs.rubygems.org/read/chapter/20 for more options
17
+ gem.name = "formative"
18
+ gem.homepage = "http://github.com/martinrehfeld/formative"
19
+ gem.license = "MIT"
20
+ gem.summary = %Q{Simple yet useful form builder for Rails 2 and 3}
21
+ gem.description = %Q{Formative is an extraction of the custom form builder I used in my last couple of Rails projects. It is the simplest thing that could possibly work for me. YMMV.}
22
+ gem.email = "martin.rehfeld@glnetworks.de"
23
+ gem.authors = ["Martin Rehfeld"]
24
+ end
25
+ Jeweler::RubygemsDotOrgTasks.new
26
+
27
+ require 'rspec/core'
28
+ require 'rspec/core/rake_task'
29
+ RSpec::Core::RakeTask.new(:spec) do |spec|
30
+ spec.pattern = FileList['spec/**/*_spec.rb']
31
+ end
32
+
33
+ RSpec::Core::RakeTask.new(:rcov) do |spec|
34
+ spec.pattern = 'spec/**/*_spec.rb'
35
+ spec.rcov = true
36
+ end
37
+
38
+ task :default => :spec
39
+
40
+ require 'yard'
41
+ YARD::Rake::YardocTask.new
data/VERSION ADDED
@@ -0,0 +1 @@
1
+ 0.0.1
@@ -0,0 +1,72 @@
1
+ # Generated by jeweler
2
+ # DO NOT EDIT THIS FILE DIRECTLY
3
+ # Instead, edit Jeweler::Tasks in Rakefile, and run 'rake gemspec'
4
+ # -*- encoding: utf-8 -*-
5
+
6
+ Gem::Specification.new do |s|
7
+ s.name = %q{formative}
8
+ s.version = "0.0.1"
9
+
10
+ s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
+ s.authors = ["Martin Rehfeld"]
12
+ s.date = %q{2011-02-17}
13
+ s.description = %q{Formative is an extraction of the custom form builder I used in my last couple of Rails projects. It is the simplest thing that could possibly work for me. YMMV.}
14
+ s.email = %q{martin.rehfeld@glnetworks.de}
15
+ s.extra_rdoc_files = [
16
+ "README.rdoc"
17
+ ]
18
+ s.files = [
19
+ ".document",
20
+ ".rspec",
21
+ "Gemfile",
22
+ "MIT-LICENSE",
23
+ "README.rdoc",
24
+ "Rakefile",
25
+ "VERSION",
26
+ "formative.gemspec",
27
+ "init.rb",
28
+ "lib/formative.rb",
29
+ "lib/formative/form_builder.rb",
30
+ "rails/init.rb",
31
+ "spec/form_builder_spec.rb",
32
+ "spec/spec_helper.rb"
33
+ ]
34
+ s.homepage = %q{http://github.com/martinrehfeld/formative}
35
+ s.licenses = ["MIT"]
36
+ s.require_paths = ["lib"]
37
+ s.rubygems_version = %q{1.3.7}
38
+ s.summary = %q{Simple yet useful form builder for Rails 2 and 3}
39
+ s.test_files = [
40
+ "spec/form_builder_spec.rb",
41
+ "spec/spec_helper.rb"
42
+ ]
43
+
44
+ if s.respond_to? :specification_version then
45
+ current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
46
+ s.specification_version = 3
47
+
48
+ if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
49
+ s.add_runtime_dependency(%q<actionpack>, [">= 0"])
50
+ s.add_development_dependency(%q<rspec>, ["~> 2.3.0"])
51
+ s.add_development_dependency(%q<yard>, ["~> 0.6.0"])
52
+ s.add_development_dependency(%q<bundler>, ["~> 1.0.0"])
53
+ s.add_development_dependency(%q<jeweler>, ["~> 1.5.2"])
54
+ s.add_development_dependency(%q<rcov>, [">= 0"])
55
+ else
56
+ s.add_dependency(%q<actionpack>, [">= 0"])
57
+ s.add_dependency(%q<rspec>, ["~> 2.3.0"])
58
+ s.add_dependency(%q<yard>, ["~> 0.6.0"])
59
+ s.add_dependency(%q<bundler>, ["~> 1.0.0"])
60
+ s.add_dependency(%q<jeweler>, ["~> 1.5.2"])
61
+ s.add_dependency(%q<rcov>, [">= 0"])
62
+ end
63
+ else
64
+ s.add_dependency(%q<actionpack>, [">= 0"])
65
+ s.add_dependency(%q<rspec>, ["~> 2.3.0"])
66
+ s.add_dependency(%q<yard>, ["~> 0.6.0"])
67
+ s.add_dependency(%q<bundler>, ["~> 1.0.0"])
68
+ s.add_dependency(%q<jeweler>, ["~> 1.5.2"])
69
+ s.add_dependency(%q<rcov>, [">= 0"])
70
+ end
71
+ end
72
+
data/init.rb ADDED
@@ -0,0 +1,2 @@
1
+ # encoding: utf-8
2
+ require 'formative'
@@ -0,0 +1,5 @@
1
+ # encoding: utf-8
2
+
3
+ module Formative
4
+ autoload :FormBuilder, "formative/form_builder"
5
+ end
@@ -0,0 +1,70 @@
1
+ # encoding: utf-8
2
+
3
+ module Formative
4
+ class FormBuilder < ::ActionView::Helpers::FormBuilder
5
+
6
+ %w[text_field select collection_select password_field text_area date_select].each do |method_name|
7
+ define_method(method_name) do |field_name, *args|
8
+ content_tag(wrapper(*args), (field_label(field_name, *args) + super(field_name, *args) + unit(*args) + hint(*args)).html_safe, :class => wrapper_class(method_name, field_name))
9
+ end
10
+ end
11
+
12
+ def check_box(field_name, options = {}, checked_value = "1", unchecked_value = "0")
13
+ content_tag(wrapper(options), super + field_label(field_name, options) + unit(options) + hint(options).html_safe, :class => wrapper_class('check_box', field_name))
14
+ end
15
+
16
+ def submit(*args)
17
+ options = filter_custom_options(args.extract_options!)
18
+ super(args, options)
19
+ end
20
+
21
+ private
22
+
23
+ def content_tag(tag, content, *args)
24
+ return content unless tag
25
+ @template.content_tag(tag, content, *args)
26
+ end
27
+
28
+ def field_label(field_name, *args)
29
+ options = args.extract_options!
30
+ return '' if options[:label] == false
31
+ options.reverse_merge!(:required => field_required?(field_name))
32
+ options[:label_class] = 'required' if options[:required]
33
+ label(field_name, options[:label], :class => options[:label_class])
34
+ end
35
+
36
+ def hint(*args)
37
+ options = args.extract_options!
38
+ return '' if options[:hint] == false || options[:hint].blank?
39
+ content_tag(:span, options[:hint], :class => 'hint')
40
+ end
41
+
42
+ def unit(*args)
43
+ options = args.extract_options!
44
+ return '' if options[:unit] == false || options[:unit].blank?
45
+ content_tag(:span, options[:unit], :class => 'unit')
46
+ end
47
+
48
+ def field_required?(field_name)
49
+ object.class.reflect_on_validations_for(field_name).map(&:macro).include?(:validates_presence_of) if object.class.respond_to?(:reflect_on_validations_for)
50
+ end
51
+
52
+ def wrapper(*args)
53
+ options = args.extract_options!
54
+ options[:wrapper] == false ? nil : (options[:wrapper] || :p)
55
+ end
56
+
57
+ def wrapper_class(method_name, field_name)
58
+ "field #{method_name.to_s.dasherize} #{field_name.to_s.dasherize}"
59
+ end
60
+
61
+ def objectify_options(options)
62
+ filter_custom_options(super)
63
+ end
64
+
65
+ def filter_custom_options(options)
66
+ options.except(:label, :required, :label_class, :wrapper, :hint, :unit)
67
+ end
68
+
69
+ end
70
+ end
@@ -0,0 +1,2 @@
1
+ # encoding: utf-8
2
+ require File.expand_path(File.join(File.dirname(__FILE__), "..", "init"))
@@ -0,0 +1,106 @@
1
+ # encoding: utf-8
2
+
3
+ require 'spec_helper'
4
+
5
+ describe Formative::FormBuilder do
6
+
7
+ include FormativeSpecHelper
8
+
9
+ let(:template) { mock_template }
10
+ let(:model) { mock('model', :attribute => 'THE_VALUE') }
11
+
12
+ subject { Formative::FormBuilder.new(:model, model, template, {}, Proc.new {}) }
13
+
14
+ {
15
+ :select => [ [] ],
16
+ :text_field => [],
17
+ :collection_select => [ [Struct.new(:value, :text).new], :value, :text ],
18
+ :password_field => [],
19
+ :text_area => [],
20
+ :check_box => [],
21
+ :submit => []
22
+ }.each_pair do |builder_method, additional_args|
23
+
24
+ describe "##{builder_method}" do
25
+ let(:args) { [builder_method, :attribute].concat additional_args }
26
+
27
+ unless builder_method == :submit
28
+ it 'should output a default wrapper' do
29
+ subject.send(*args).should =~ /^<p.*\/p>$/
30
+ end
31
+
32
+ it 'should output a given wrapper' do
33
+ subject.send(*(args << {:wrapper => :div})).should =~ /^<div.*\/div>$/
34
+ end
35
+
36
+ it 'should add "field <method_name> <field_name>" as class of wrapper' do
37
+ subject.send(*args).should =~ /^<p class="field #{builder_method.to_s.dasherize} attribute"/
38
+ end
39
+
40
+ it 'should output a proper label' do
41
+ subject.send(*args).should =~ /<label for="model_attribute".*\/label>/
42
+ end
43
+
44
+ it 'should output a given unit' do
45
+ subject.send(*(args << {:unit => 'the unit'})).should =~ /<span class="unit">the unit<\/span>/
46
+ end
47
+
48
+ it 'should output a given hint' do
49
+ subject.send(*(args << {:hint => 'additional information'})).should =~ /<span class="hint">additional information<\/span>/
50
+ end
51
+ end
52
+
53
+ context ":wrapper => false" do
54
+ let(:no_wrapper_args) { args << {:wrapper => false} }
55
+
56
+ it 'should not output a wrapper' do
57
+ subject.send(*no_wrapper_args).should_not =~ /^<p/
58
+ subject.send(*no_wrapper_args).should_not =~ /\/p>$/
59
+ end
60
+
61
+ it 'should not output the wrapper option into the tag attributes' do
62
+ subject.send(*no_wrapper_args).should_not =~ /wrapper\s*=/
63
+ end
64
+ end
65
+
66
+ context ":label => false" do
67
+ let(:no_label_args) { args << {:label => false} }
68
+
69
+ it 'should not output a label' do
70
+ subject.send(*no_label_args).should_not =~ /<label/
71
+ subject.send(*no_label_args).should_not =~ /\/label>/
72
+ end
73
+
74
+ it 'should not output the label option into the tag attributes' do
75
+ subject.send(*no_label_args).should_not =~ /label\s*=/
76
+ end
77
+ end
78
+
79
+ context ":hint => false" do
80
+ let(:no_hint_args) { args << {:hint => false} }
81
+
82
+ it 'should not output a hint' do
83
+ subject.send(*no_hint_args).should_not =~ /<\w+ class="hint"/
84
+ end
85
+
86
+ it 'should not output the hint option into the tag attributes' do
87
+ subject.send(*no_hint_args).should_not =~ /hint\s*=/
88
+ end
89
+ end
90
+
91
+ context ":unit => false" do
92
+ let(:no_unit_args) { args << {:unit => false} }
93
+
94
+ it 'should not output a unit' do
95
+ subject.send(*no_unit_args).should_not =~ /<\w+ class="unit"/
96
+ end
97
+
98
+ it 'should not output the unit option into the tag attributes' do
99
+ subject.send(*no_unit_args).should_not =~ /unit\s*=/
100
+ end
101
+ end
102
+ end
103
+
104
+ end
105
+
106
+ end
@@ -0,0 +1,34 @@
1
+ # encoding: utf-8
2
+
3
+ require 'rubygems'
4
+ require 'bundler'
5
+ Bundler.setup
6
+
7
+ require 'action_view'
8
+
9
+ $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
10
+ $LOAD_PATH.unshift(File.dirname(__FILE__))
11
+ require 'formative'
12
+
13
+ # Requires supporting files with custom matchers and macros, etc,
14
+ # in ./support/ and its subdirectories.
15
+ Dir["#{File.dirname(__FILE__)}/support/**/*.rb"].each {|f| require f}
16
+
17
+ RSpec.configure do |config|
18
+ end
19
+
20
+ module FormativeSpecHelper
21
+
22
+ def mock_template
23
+ t = Object.new
24
+
25
+ class << t
26
+ include ActionView::Helpers
27
+ end
28
+
29
+ t
30
+ end
31
+
32
+ end
33
+
34
+ ::ActiveSupport::Deprecation.silenced = false
metadata ADDED
@@ -0,0 +1,164 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: formative
3
+ version: !ruby/object:Gem::Version
4
+ prerelease: false
5
+ segments:
6
+ - 0
7
+ - 0
8
+ - 1
9
+ version: 0.0.1
10
+ platform: ruby
11
+ authors:
12
+ - Martin Rehfeld
13
+ autorequire:
14
+ bindir: bin
15
+ cert_chain: []
16
+
17
+ date: 2011-02-17 00:00:00 +01:00
18
+ default_executable:
19
+ dependencies:
20
+ - !ruby/object:Gem::Dependency
21
+ name: actionpack
22
+ requirement: &id001 !ruby/object:Gem::Requirement
23
+ none: false
24
+ requirements:
25
+ - - ">="
26
+ - !ruby/object:Gem::Version
27
+ segments:
28
+ - 0
29
+ version: "0"
30
+ type: :runtime
31
+ prerelease: false
32
+ version_requirements: *id001
33
+ - !ruby/object:Gem::Dependency
34
+ name: rspec
35
+ requirement: &id002 !ruby/object:Gem::Requirement
36
+ none: false
37
+ requirements:
38
+ - - ~>
39
+ - !ruby/object:Gem::Version
40
+ segments:
41
+ - 2
42
+ - 3
43
+ - 0
44
+ version: 2.3.0
45
+ type: :development
46
+ prerelease: false
47
+ version_requirements: *id002
48
+ - !ruby/object:Gem::Dependency
49
+ name: yard
50
+ requirement: &id003 !ruby/object:Gem::Requirement
51
+ none: false
52
+ requirements:
53
+ - - ~>
54
+ - !ruby/object:Gem::Version
55
+ segments:
56
+ - 0
57
+ - 6
58
+ - 0
59
+ version: 0.6.0
60
+ type: :development
61
+ prerelease: false
62
+ version_requirements: *id003
63
+ - !ruby/object:Gem::Dependency
64
+ name: bundler
65
+ requirement: &id004 !ruby/object:Gem::Requirement
66
+ none: false
67
+ requirements:
68
+ - - ~>
69
+ - !ruby/object:Gem::Version
70
+ segments:
71
+ - 1
72
+ - 0
73
+ - 0
74
+ version: 1.0.0
75
+ type: :development
76
+ prerelease: false
77
+ version_requirements: *id004
78
+ - !ruby/object:Gem::Dependency
79
+ name: jeweler
80
+ requirement: &id005 !ruby/object:Gem::Requirement
81
+ none: false
82
+ requirements:
83
+ - - ~>
84
+ - !ruby/object:Gem::Version
85
+ segments:
86
+ - 1
87
+ - 5
88
+ - 2
89
+ version: 1.5.2
90
+ type: :development
91
+ prerelease: false
92
+ version_requirements: *id005
93
+ - !ruby/object:Gem::Dependency
94
+ name: rcov
95
+ requirement: &id006 !ruby/object:Gem::Requirement
96
+ none: false
97
+ requirements:
98
+ - - ">="
99
+ - !ruby/object:Gem::Version
100
+ segments:
101
+ - 0
102
+ version: "0"
103
+ type: :development
104
+ prerelease: false
105
+ version_requirements: *id006
106
+ description: Formative is an extraction of the custom form builder I used in my last couple of Rails projects. It is the simplest thing that could possibly work for me. YMMV.
107
+ email: martin.rehfeld@glnetworks.de
108
+ executables: []
109
+
110
+ extensions: []
111
+
112
+ extra_rdoc_files:
113
+ - README.rdoc
114
+ files:
115
+ - .document
116
+ - .rspec
117
+ - Gemfile
118
+ - MIT-LICENSE
119
+ - README.rdoc
120
+ - Rakefile
121
+ - VERSION
122
+ - formative.gemspec
123
+ - init.rb
124
+ - lib/formative.rb
125
+ - lib/formative/form_builder.rb
126
+ - rails/init.rb
127
+ - spec/form_builder_spec.rb
128
+ - spec/spec_helper.rb
129
+ has_rdoc: true
130
+ homepage: http://github.com/martinrehfeld/formative
131
+ licenses:
132
+ - MIT
133
+ post_install_message:
134
+ rdoc_options: []
135
+
136
+ require_paths:
137
+ - lib
138
+ required_ruby_version: !ruby/object:Gem::Requirement
139
+ none: false
140
+ requirements:
141
+ - - ">="
142
+ - !ruby/object:Gem::Version
143
+ hash: 4206223225746873947
144
+ segments:
145
+ - 0
146
+ version: "0"
147
+ required_rubygems_version: !ruby/object:Gem::Requirement
148
+ none: false
149
+ requirements:
150
+ - - ">="
151
+ - !ruby/object:Gem::Version
152
+ segments:
153
+ - 0
154
+ version: "0"
155
+ requirements: []
156
+
157
+ rubyforge_project:
158
+ rubygems_version: 1.3.7
159
+ signing_key:
160
+ specification_version: 3
161
+ summary: Simple yet useful form builder for Rails 2 and 3
162
+ test_files:
163
+ - spec/form_builder_spec.rb
164
+ - spec/spec_helper.rb