├── .rspec
├── Gemfile
├── spec
├── spec.opts
├── support
│ ├── output_buffer.rb
│ └── test_environment.rb
├── helpers
│ └── layout_helper_spec.rb
├── defaults_spec.rb
├── error_proc_spec.rb
├── inputs
│ ├── url_input_spec.rb
│ ├── email_input_spec.rb
│ ├── phone_input_spec.rb
│ ├── search_input_spec.rb
│ ├── file_input_spec.rb
│ ├── numeric_input_spec.rb
│ ├── password_input_spec.rb
│ ├── time_zone_input_spec.rb
│ ├── hidden_input_spec.rb
│ ├── date_input_spec.rb
│ ├── country_input_spec.rb
│ ├── text_input_spec.rb
│ ├── boolean_input_spec.rb
│ ├── time_input_spec.rb
│ ├── string_input_spec.rb
│ ├── radio_input_spec.rb
│ ├── datetime_input_spec.rb
│ └── check_boxes_input_spec.rb
├── include_blank_spec.rb
├── custom_builder_spec.rb
├── semantic_fields_for_spec.rb
├── semantic_errors_spec.rb
├── label_spec.rb
├── buttons_spec.rb
├── i18n_spec.rb
├── form_helper_spec.rb
├── errors_spec.rb
├── spec_helper.rb
└── commit_button_spec.rb
├── rails
└── init.rb
├── .gitignore
├── lib
├── generators
│ ├── templates
│ │ ├── _form.html.haml
│ │ ├── _form.html.erb
│ │ ├── formtastic_changes.css
│ │ ├── formtastic.rb
│ │ └── formtastic.css
│ └── formtastic
│ │ ├── install
│ │ └── install_generator.rb
│ │ └── form
│ │ └── form_generator.rb
├── locale
│ └── en.yml
└── formtastic
│ ├── layout_helper.rb
│ ├── railtie.rb
│ ├── i18n.rb
│ └── util.rb
├── init.rb
├── RELEASE_PROCESS
├── generators
├── form
│ ├── USAGE
│ └── form_generator.rb
└── formtastic
│ └── formtastic_generator.rb
├── Rakefile
├── MIT-LICENSE
├── formtastic.gemspec
└── CHANGELOG
/.rspec:
--------------------------------------------------------------------------------
1 | --color
2 | --format=progress
3 |
--------------------------------------------------------------------------------
/Gemfile:
--------------------------------------------------------------------------------
1 | source :rubygems
2 |
3 | gemspec
4 |
--------------------------------------------------------------------------------
/spec/spec.opts:
--------------------------------------------------------------------------------
1 | --color
2 | --format=progress
3 |
--------------------------------------------------------------------------------
/rails/init.rb:
--------------------------------------------------------------------------------
1 | # encoding: utf-8
2 | require File.expand_path(File.join(File.dirname(__FILE__), "..", "init"))
3 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | .DS_Store
2 | .rvmrc
3 | coverage
4 | pkg
5 | *~
6 | *watchr.rb
7 | log/*
8 | .rvmrc
9 | .bundle
10 | Gemfile.lock
11 | /.redcar
--------------------------------------------------------------------------------
/lib/generators/templates/_form.html.haml:
--------------------------------------------------------------------------------
1 | - f.inputs do
2 | <% attributes.each do |attribute| -%>
3 | = f.input :<%= attribute.name %>
4 | <% end -%>
5 |
--------------------------------------------------------------------------------
/spec/support/output_buffer.rb:
--------------------------------------------------------------------------------
1 | # encoding: utf-8
2 |
3 | module ActionView
4 | class OutputBuffer < Formtastic::Util.rails_safe_buffer_class
5 | end
6 | end
7 |
--------------------------------------------------------------------------------
/lib/generators/templates/_form.html.erb:
--------------------------------------------------------------------------------
1 | <%% f.inputs do %>
2 | <% attributes.each do |attribute| -%>
3 | <%%= f.input :<%= attribute.name %> %>
4 | <% end -%>
5 | <%% end %>
6 |
--------------------------------------------------------------------------------
/lib/locale/en.yml:
--------------------------------------------------------------------------------
1 | en:
2 | formtastic:
3 | :yes: 'Yes'
4 | :no: 'No'
5 | :create: 'Create %{model}'
6 | :update: 'Update %{model}'
7 | :required: 'required'
8 |
--------------------------------------------------------------------------------
/init.rb:
--------------------------------------------------------------------------------
1 | # encoding: utf-8
2 | require 'formtastic'
3 | require 'formtastic/layout_helper'
4 | ActionView::Base.send :include, Formtastic::SemanticFormHelper
5 | ActionView::Base.send :include, Formtastic::LayoutHelper
6 |
--------------------------------------------------------------------------------
/lib/formtastic/layout_helper.rb:
--------------------------------------------------------------------------------
1 | # encoding: utf-8
2 |
3 | module Formtastic
4 | module LayoutHelper
5 |
6 | def formtastic_stylesheet_link_tag
7 | stylesheet_link_tag("formtastic") +
8 | stylesheet_link_tag("formtastic_changes")
9 | end
10 |
11 | end
12 | end
13 |
--------------------------------------------------------------------------------
/RELEASE_PROCESS:
--------------------------------------------------------------------------------
1 | # edit gemspec version number, date
2 | git ci formtastic.gemspec -m "new gemspec" # commit changes
3 | git tag X.X.X # tag the new version in the code base too
4 | gem build formtastic.gemspec # build the gem
5 | gem push formtastic-X.X.X.gem # publish the gem
6 | git push && git push --tags # push to remote
7 |
--------------------------------------------------------------------------------
/lib/formtastic/railtie.rb:
--------------------------------------------------------------------------------
1 | # encoding: utf-8
2 |
3 | require 'formtastic'
4 | require 'formtastic/layout_helper'
5 | require 'rails'
6 |
7 | module Formtastic
8 | class Railtie < Rails::Railtie
9 | initializer 'formtastic.initialize', :after => :after_initialize do
10 | ActionView::Base.send :include, Formtastic::SemanticFormHelper
11 | ActionView::Base.send(:include, Formtastic::LayoutHelper)
12 | end
13 | end
14 | end
15 |
--------------------------------------------------------------------------------
/spec/helpers/layout_helper_spec.rb:
--------------------------------------------------------------------------------
1 | # encoding: utf-8
2 | require 'spec_helper'
3 |
4 | describe Formtastic::LayoutHelper do
5 |
6 | include FormtasticSpecHelper
7 | include Formtastic::LayoutHelper
8 |
9 | describe '#formtastic_stylesheet_link_tag' do
10 |
11 | it 'should render a link to formtastic.css' do
12 | formtastic_stylesheet_link_tag.should have_tag("link[@href='/stylesheets/formtastic.css']")
13 | end
14 |
15 | it 'should render a link to formtastic_changes.css' do
16 | formtastic_stylesheet_link_tag.should have_tag("link[@href='/stylesheets/formtastic_changes.css']")
17 | end
18 |
19 | end
20 | end
21 |
22 |
--------------------------------------------------------------------------------
/spec/defaults_spec.rb:
--------------------------------------------------------------------------------
1 | # encoding: utf-8
2 | require 'spec_helper'
3 |
4 | describe 'Formtastic::SemanticFormBuilder-defaults' do
5 |
6 | # Note: This spec might make better sense somewhere else. Just temporary.
7 |
8 | describe "required string" do
9 |
10 | it "should render proc with I18n correctly" do
11 | ::I18n.backend.store_translations :en, :formtastic => {:required => 'Haha!'}
12 |
13 | required_string = Formtastic::SemanticFormBuilder.required_string
14 | required_string = required_string.is_a?(::Proc) ? required_string.call : required_string.to_s
15 | required_string.should == %{*}
16 | end
17 |
18 | end
19 |
20 | end
21 |
--------------------------------------------------------------------------------
/spec/error_proc_spec.rb:
--------------------------------------------------------------------------------
1 | # encoding: utf-8
2 | require 'spec_helper'
3 |
4 | describe 'Rails field_error_proc' do
5 |
6 | include FormtasticSpecHelper
7 |
8 | before do
9 | @output_buffer = ''
10 | mock_everything
11 | end
12 |
13 | it "should not be overridden globally for all form builders" do
14 | current_field_error_proc = ::ActionView::Base.field_error_proc
15 |
16 | semantic_form_for(@new_post) do |builder|
17 | ::ActionView::Base.field_error_proc.should_not == current_field_error_proc
18 | end
19 |
20 | ::ActionView::Base.field_error_proc.should == current_field_error_proc
21 |
22 | form_for(@new_post) do |builder|
23 | ::ActionView::Base.field_error_proc.should == current_field_error_proc
24 | end
25 | end
26 |
27 | end
28 |
--------------------------------------------------------------------------------
/lib/generators/formtastic/install/install_generator.rb:
--------------------------------------------------------------------------------
1 | # encoding: utf-8
2 | module Formtastic
3 | class InstallGenerator < Rails::Generators::Base
4 | desc "Copies formtastic.css and formtastic_changes.css to public/stylesheets/ and a config initializer to config/initializers/formtastic_config.rb"
5 |
6 | source_root File.expand_path('../../../templates', __FILE__)
7 |
8 | def copy_files
9 | empty_directory 'config/initializers'
10 | template 'formtastic.rb', 'config/initializers/formtastic.rb'
11 |
12 | empty_directory 'public/stylesheets'
13 | template 'formtastic.css', 'public/stylesheets/formtastic.css'
14 | template 'formtastic_changes.css', 'public/stylesheets/formtastic_changes.css'
15 | end
16 | end
17 | end
18 |
--------------------------------------------------------------------------------
/lib/generators/templates/formtastic_changes.css:
--------------------------------------------------------------------------------
1 | /* -------------------------------------------------------------------------------------------------
2 |
3 | Load this stylesheet after formtastic.css in your layouts to override the CSS to suit your needs.
4 | This will allow you to update formtastic.css with new releases without clobbering your own changes.
5 |
6 | For example, to make the inline hint paragraphs a little darker in color than the standard #666:
7 |
8 | form.formtastic fieldset > ol > li p.inline-hints { color:#333; }
9 |
10 | HINT:
11 | The following style may be *conditionally* included for improved support on older versions of IE(<8)
12 | form.formtastic fieldset ol li fieldset legend { margin-left: -6px;}
13 |
14 | --------------------------------------------------------------------------------------------------*/
15 |
--------------------------------------------------------------------------------
/spec/support/test_environment.rb:
--------------------------------------------------------------------------------
1 | # encoding: utf-8
2 | require 'rspec_tag_matchers'
3 |
4 | RSpec.configure do |config|
5 | config.include RspecTagMatchers
6 | config.include CustomMacros
7 | config.mock_with :rspec
8 | end
9 |
10 | if Formtastic::Util.rails3?
11 |
12 | require "action_controller/railtie"
13 | require "active_resource/railtie"
14 | require 'active_model'
15 |
16 | # Create a simple rails application for use in testing the viewhelper
17 | module FormtasticTest
18 | class Application < Rails::Application
19 | # Configure the default encoding used in templates for Ruby 1.9.
20 | config.encoding = "utf-8"
21 | config.active_support.deprecation = :stderr
22 | end
23 | end
24 | FormtasticTest::Application.initialize!
25 |
26 | require 'rspec/rails'
27 | end
28 |
29 |
30 |
31 |
32 |
--------------------------------------------------------------------------------
/generators/form/USAGE:
--------------------------------------------------------------------------------
1 | NAME
2 | form - Formtastic form generator.
3 |
4 | DESCRIPTION
5 | Generates formtastic form code based on an existing model. By default the generated code will be printed out directly in the terminal, and also copied to clipboard. Can optionally be saved into partial directly.
6 |
7 | Required:
8 | ExistingModelName - The name of an existing model for which the generator should generate form code.
9 |
10 | Options:
11 | --haml Generate HAML instead of ERB.
12 | --partial Generate a form partial in the model views path, i.e. "_form.html.erb" or _form.html.haml".
13 | --controller PATH Generate for custom controller/view path - in case model and controller namespace is different, i.e. "admin/posts".
14 |
15 | EXAMPLE
16 | ./script/generate form ExistingModelName [--haml] [--partial]
--------------------------------------------------------------------------------
/generators/formtastic/formtastic_generator.rb:
--------------------------------------------------------------------------------
1 | # encoding: utf-8
2 |
3 | class FormtasticGenerator < Rails::Generator::Base
4 |
5 | def manifest
6 | record do |m|
7 | m.directory File.join('config', 'initializers')
8 | m.template 'formtastic.rb', File.join('config', 'initializers', 'formtastic.rb')
9 |
10 | m.directory File.join('public', 'stylesheets')
11 | m.template 'formtastic.css', File.join('public', 'stylesheets', 'formtastic.css')
12 | m.template 'formtastic_changes.css', File.join('public', 'stylesheets', 'formtastic_changes.css')
13 | end
14 | end
15 |
16 | protected
17 |
18 | def banner
19 | %{Usage: #{$0} #{spec.name}\nCopies formtastic.css and formtastic_changes.css to public/stylesheets/ and a config initializer to config/initializers/formtastic.rb}
20 | end
21 |
22 | def source_root
23 | File.expand_path('../../../lib/generators/templates', __FILE__)
24 | end
25 |
26 | end
27 |
--------------------------------------------------------------------------------
/lib/formtastic/i18n.rb:
--------------------------------------------------------------------------------
1 | # encoding: utf-8
2 |
3 | module Formtastic
4 | module I18n
5 |
6 | DEFAULT_SCOPE = [:formtastic].freeze
7 | DEFAULT_VALUES = YAML.load_file(File.expand_path("../../locale/en.yml", __FILE__))["en"]["formtastic"].freeze
8 | SCOPES = [
9 | '%{model}.%{nested_model}.%{action}.%{attribute}',
10 | '%{model}.%{action}.%{attribute}',
11 | '%{model}.%{nested_model}.%{attribute}',
12 | '%{model}.%{attribute}',
13 | '%{nested_model}.%{attribute}',
14 | '%{attribute}'
15 | ]
16 |
17 | class << self
18 |
19 | def translate(*args)
20 | key = args.shift.to_sym
21 | options = args.extract_options!
22 | options.reverse_merge!(:default => DEFAULT_VALUES[key])
23 | options[:scope] = [DEFAULT_SCOPE, options[:scope]].flatten.compact
24 | ::I18n.translate(key, *(args << options))
25 | end
26 | alias :t :translate
27 |
28 | end
29 |
30 | end
31 | end
32 |
--------------------------------------------------------------------------------
/Rakefile:
--------------------------------------------------------------------------------
1 | # encoding: utf-8
2 | require 'rubygems'
3 | require 'rake'
4 | require 'rake/rdoctask'
5 | require 'rspec/core/rake_task'
6 |
7 | desc 'Default: run unit specs.'
8 | task :default => :spec
9 |
10 | desc 'Generate documentation for the formtastic plugin.'
11 | Rake::RDocTask.new(:rdoc) do |rdoc|
12 | rdoc.rdoc_dir = 'rdoc'
13 | rdoc.title = 'Formtastic'
14 | rdoc.options << '--line-numbers' << '--inline-source'
15 | rdoc.rdoc_files.include('README.textile')
16 | rdoc.rdoc_files.include('lib/**/*.rb')
17 | end
18 |
19 | desc 'Test the formtastic plugin.'
20 | RSpec::Core::RakeTask.new('spec') do |t|
21 | t.pattern = FileList['spec/**/*_spec.rb']
22 | end
23 |
24 | desc 'Test the formtastic plugin with specdoc formatting and colors'
25 | RSpec::Core::RakeTask.new('specdoc') do |t|
26 | t.pattern = FileList['spec/**/*_spec.rb']
27 | end
28 |
29 | desc 'Run all examples with RCov'
30 | RSpec::Core::RakeTask.new('examples_with_rcov') do |t|
31 | t.pattern = FileList['spec/**/*_spec.rb']
32 | t.rcov = true
33 | t.rcov_opts = ['--exclude', 'spec,Library']
34 | end
35 |
--------------------------------------------------------------------------------
/MIT-LICENSE:
--------------------------------------------------------------------------------
1 | Copyright (c) 2008-2010 Justin French
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.
21 |
--------------------------------------------------------------------------------
/spec/inputs/url_input_spec.rb:
--------------------------------------------------------------------------------
1 | # encoding: utf-8
2 | require 'spec_helper'
3 |
4 | describe 'url input' do
5 |
6 | include FormtasticSpecHelper
7 |
8 | before do
9 | @output_buffer = ''
10 | mock_everything
11 | end
12 |
13 | describe "when object is provided" do
14 | before do
15 | @form = semantic_form_for(@new_post) do |builder|
16 | concat(builder.input(:url))
17 | end
18 | end
19 |
20 | it_should_have_input_wrapper_with_class(:url)
21 | it_should_have_input_wrapper_with_id("post_url_input")
22 | it_should_have_label_with_text(/Url/)
23 | it_should_have_label_for("post_url")
24 | it_should_have_input_with_id("post_url")
25 | it_should_have_input_with_type(Formtastic::Util.rails3? ? :url : :text)
26 | it_should_have_input_with_name("post[url]")
27 |
28 | end
29 |
30 | describe "when namespace is provided" do
31 |
32 | before do
33 | @form = semantic_form_for(@new_post, :namespace => "context2") do |builder|
34 | concat(builder.input(:url))
35 | end
36 | end
37 |
38 | it_should_have_input_wrapper_with_id("context2_post_url_input")
39 | it_should_have_label_and_input_with_id("context2_post_url")
40 |
41 | end
42 |
43 | end
44 |
45 |
--------------------------------------------------------------------------------
/spec/inputs/email_input_spec.rb:
--------------------------------------------------------------------------------
1 | # encoding: utf-8
2 | require 'spec_helper'
3 |
4 | describe 'email input' do
5 |
6 | include FormtasticSpecHelper
7 |
8 | before do
9 | @output_buffer = ''
10 | mock_everything
11 | end
12 |
13 | describe "when object is provided" do
14 | before do
15 | @form = semantic_form_for(@new_post) do |builder|
16 | concat(builder.input(:email))
17 | end
18 | end
19 |
20 | it_should_have_input_wrapper_with_class(:email)
21 | it_should_have_input_wrapper_with_id("post_email_input")
22 | it_should_have_label_with_text(/Email/)
23 | it_should_have_label_for("post_email")
24 | it_should_have_input_with_id("post_email")
25 | it_should_have_input_with_type(Formtastic::Util.rails3? ? :email : :text)
26 | it_should_have_input_with_name("post[email]")
27 |
28 | end
29 |
30 | describe "when namespace is provided" do
31 |
32 | before do
33 | @form = semantic_form_for(@new_post, :namespace => 'context2') do |builder|
34 | concat(builder.input(:email))
35 | end
36 | end
37 |
38 | it_should_have_input_wrapper_with_id("context2_post_email_input")
39 | it_should_have_label_and_input_with_id("context2_post_email")
40 |
41 | end
42 |
43 | end
44 |
45 |
--------------------------------------------------------------------------------
/spec/inputs/phone_input_spec.rb:
--------------------------------------------------------------------------------
1 | # encoding: utf-8
2 | require 'spec_helper'
3 |
4 | describe 'phone input' do
5 |
6 | include FormtasticSpecHelper
7 |
8 | before do
9 | @output_buffer = ''
10 | mock_everything
11 | end
12 |
13 | describe "when object is provided" do
14 | before do
15 | @form = semantic_form_for(@new_post) do |builder|
16 | concat(builder.input(:phone))
17 | end
18 | end
19 |
20 | it_should_have_input_wrapper_with_class(:phone)
21 | it_should_have_input_wrapper_with_id("post_phone_input")
22 | it_should_have_label_with_text(/Phone/)
23 | it_should_have_label_for("post_phone")
24 | it_should_have_input_with_id("post_phone")
25 | it_should_have_input_with_type(Formtastic::Util.rails3? ? :tel : :text)
26 | it_should_have_input_with_name("post[phone]")
27 |
28 | end
29 |
30 | describe "when namespace is provided" do
31 |
32 | before do
33 | @form = semantic_form_for(@new_post, :namespace => "context2") do |builder|
34 | concat(builder.input(:phone))
35 | end
36 | end
37 |
38 | it_should_have_input_wrapper_with_id("context2_post_phone_input")
39 | it_should_have_label_and_input_with_id("context2_post_phone")
40 |
41 | end
42 |
43 | end
44 |
45 |
--------------------------------------------------------------------------------
/spec/inputs/search_input_spec.rb:
--------------------------------------------------------------------------------
1 | # encoding: utf-8
2 | require 'spec_helper'
3 |
4 | describe 'search input' do
5 |
6 | include FormtasticSpecHelper
7 |
8 | before do
9 | @output_buffer = ''
10 | mock_everything
11 | end
12 |
13 | describe "when object is provided" do
14 | before do
15 | @form = semantic_form_for(@new_post) do |builder|
16 | concat(builder.input(:search))
17 | end
18 | end
19 |
20 | it_should_have_input_wrapper_with_class(:search)
21 | it_should_have_input_wrapper_with_id("post_search_input")
22 | it_should_have_label_with_text(/Search/)
23 | it_should_have_label_for("post_search")
24 | it_should_have_input_with_id("post_search")
25 | it_should_have_input_with_type(Formtastic::Util.rails3? ? :search : :text)
26 | it_should_have_input_with_name("post[search]")
27 |
28 | end
29 |
30 | describe "when namespace is provided" do
31 |
32 | before do
33 | @form = semantic_form_for(@new_post, :namespace => "context2") do |builder|
34 | concat(builder.input(:search))
35 | end
36 | end
37 |
38 | it_should_have_input_wrapper_with_id("context2_post_search_input")
39 | it_should_have_label_and_input_with_id("context2_post_search")
40 |
41 | end
42 |
43 | end
44 |
45 |
--------------------------------------------------------------------------------
/lib/formtastic/util.rb:
--------------------------------------------------------------------------------
1 | # encoding: utf-8
2 |
3 | # Adapted from the rails3 compatibility shim in Haml 2.2
4 | module Formtastic
5 | module Util
6 | extend self
7 | ## Rails XSS Safety
8 |
9 | # Returns the given text, marked as being HTML-safe.
10 | # With older versions of the Rails XSS-safety mechanism,
11 | # this destructively modifies the HTML-safety of `text`.
12 | #
13 | # @param text [String]
14 | # @return [String] `text`, marked as HTML-safe
15 | def html_safe(text)
16 | return text if text.nil?
17 | return text.html_safe if defined?(ActiveSupport::SafeBuffer)
18 | return text.html_safe! if text.respond_to?(:html_safe!)
19 | text
20 | end
21 |
22 | def rails_safe_buffer_class
23 | # It's important that we check ActiveSupport first,
24 | # because in Rails 2.3.6 ActionView::SafeBuffer exists
25 | # but is a deprecated proxy object.
26 | return ActiveSupport::SafeBuffer if defined?(ActiveSupport::SafeBuffer)
27 | return ActionView::SafeBuffer
28 | end
29 |
30 | def rails3?
31 | version=
32 | if defined?(ActionPack::VERSION::MAJOR)
33 | ActionPack::VERSION::MAJOR
34 | end
35 | !version.blank? && version >= 3
36 | end
37 | end
38 | end
39 |
--------------------------------------------------------------------------------
/spec/inputs/file_input_spec.rb:
--------------------------------------------------------------------------------
1 | # encoding: utf-8
2 | require 'spec_helper'
3 |
4 | describe 'file input' do
5 |
6 | include FormtasticSpecHelper
7 |
8 | before do
9 | @output_buffer = ''
10 | mock_everything
11 |
12 | @form = semantic_form_for(@new_post) do |builder|
13 | concat(builder.input(:body, :as => :file))
14 | end
15 | end
16 |
17 | it_should_have_input_wrapper_with_class("file")
18 | it_should_have_input_wrapper_with_id("post_body_input")
19 | it_should_have_label_with_text(/Body/)
20 | it_should_have_label_for("post_body")
21 | it_should_have_input_with_id("post_body")
22 | it_should_have_input_with_name("post[body]")
23 | it_should_apply_error_logic_for_input_type(:file)
24 |
25 | it 'should use input_html to style inputs' do
26 | form = semantic_form_for(@new_post) do |builder|
27 | concat(builder.input(:title, :as => :file, :input_html => { :class => 'myclass' }))
28 | end
29 | output_buffer.concat(form) if Formtastic::Util.rails3?
30 | output_buffer.should have_tag("form li input.myclass")
31 | end
32 |
33 | describe "when namespace is provided" do
34 |
35 | before do
36 | @output_buffer = ''
37 | mock_everything
38 |
39 | @form = semantic_form_for(@new_post, :namespace => 'context2') do |builder|
40 | concat(builder.input(:body, :as => :file))
41 | end
42 | end
43 |
44 | it_should_have_input_wrapper_with_id("context2_post_body_input")
45 | it_should_have_label_and_input_with_id("context2_post_body")
46 |
47 | end
48 |
49 | end
50 |
51 |
--------------------------------------------------------------------------------
/spec/inputs/numeric_input_spec.rb:
--------------------------------------------------------------------------------
1 | # encoding: utf-8
2 | require 'spec_helper'
3 |
4 | describe 'numeric input' do
5 |
6 | include FormtasticSpecHelper
7 |
8 | before do
9 | @output_buffer = ''
10 | mock_everything
11 |
12 | @form = semantic_form_for(@new_post) do |builder|
13 | concat(builder.input(:title, :as => :numeric))
14 | end
15 | end
16 |
17 | it_should_have_input_wrapper_with_class(:numeric)
18 | it_should_have_input_wrapper_with_id("post_title_input")
19 | it_should_have_label_with_text(/Title/)
20 | it_should_have_label_for("post_title")
21 | it_should_have_input_with_id("post_title")
22 | it_should_have_input_with_type(:text)
23 | it_should_have_input_with_name("post[title]")
24 | it_should_use_default_text_field_size_when_not_nil(:string)
25 | it_should_not_use_default_text_field_size_when_nil(:string)
26 | it_should_apply_custom_input_attributes_when_input_html_provided(:string)
27 | it_should_apply_custom_for_to_label_when_input_html_id_provided(:string)
28 | it_should_apply_error_logic_for_input_type(:numeric)
29 |
30 | describe "when no object is provided" do
31 | before do
32 | @form = semantic_form_for(:project, :url => 'http://test.host/') do |builder|
33 | concat(builder.input(:title, :as => :numeric))
34 | end
35 | end
36 |
37 | it_should_have_label_with_text(/Title/)
38 | it_should_have_label_for("project_title")
39 | it_should_have_input_with_id("project_title")
40 | it_should_have_input_with_type(:text)
41 | it_should_have_input_with_name("project[title]")
42 | end
43 |
44 | describe "when namespace provided" do
45 | before do
46 | @form = semantic_form_for(@new_post, :namespace => :context2) do |builder|
47 | concat(builder.input(:title, :as => :numeric))
48 | end
49 | end
50 |
51 | it_should_have_input_wrapper_with_id("context2_post_title_input")
52 | it_should_have_label_and_input_with_id("context2_post_title")
53 | end
54 |
55 | end
56 |
57 |
--------------------------------------------------------------------------------
/spec/inputs/password_input_spec.rb:
--------------------------------------------------------------------------------
1 | # encoding: utf-8
2 | require 'spec_helper'
3 |
4 | describe 'password input' do
5 |
6 | include FormtasticSpecHelper
7 |
8 | before do
9 | @output_buffer = ''
10 | mock_everything
11 |
12 | @form = semantic_form_for(@new_post) do |builder|
13 | concat(builder.input(:title, :as => :password))
14 | end
15 | end
16 |
17 | it_should_have_input_wrapper_with_class(:password)
18 | it_should_have_input_wrapper_with_id("post_title_input")
19 | it_should_have_label_with_text(/Title/)
20 | it_should_have_label_for("post_title")
21 | it_should_have_input_with_id("post_title")
22 | it_should_have_input_with_type(:password)
23 | it_should_have_input_with_name("post[title]")
24 | it_should_have_maxlength_matching_column_limit
25 | it_should_use_default_text_field_size_when_not_nil(:string)
26 | it_should_not_use_default_text_field_size_when_nil(:string)
27 | it_should_apply_custom_input_attributes_when_input_html_provided(:string)
28 | it_should_apply_custom_for_to_label_when_input_html_id_provided(:string)
29 | it_should_apply_error_logic_for_input_type(:password)
30 |
31 | describe "when no object is provided" do
32 | before do
33 | @form = semantic_form_for(:project, :url => 'http://test.host/') do |builder|
34 | concat(builder.input(:title, :as => :password))
35 | end
36 | end
37 |
38 | it_should_have_label_with_text(/Title/)
39 | it_should_have_label_for("project_title")
40 | it_should_have_input_with_id("project_title")
41 | it_should_have_input_with_type(:password)
42 | it_should_have_input_with_name("project[title]")
43 | end
44 |
45 | describe "when namespace is provided" do
46 |
47 | before do
48 | @form = semantic_form_for(@new_post, :namespace => "context2") do |builder|
49 | concat(builder.input(:title, :as => :password))
50 | end
51 | end
52 |
53 | it_should_have_input_wrapper_with_id("context2_post_title_input")
54 | it_should_have_label_and_input_with_id("context2_post_title")
55 |
56 | end
57 |
58 | end
59 |
--------------------------------------------------------------------------------
/formtastic.gemspec:
--------------------------------------------------------------------------------
1 | # encoding: utf-8
2 |
3 | Gem::Specification.new do |s|
4 | s.name = %q{formtastic}
5 | s.version = "1.2.1"
6 | s.date = %q{2010-11-22}
7 |
8 | s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
9 | s.authors = ["Justin French"]
10 | s.description = %q{A Rails form builder plugin/gem with semantically rich and accessible markup}
11 | s.summary = %q{A Rails form builder plugin/gem with semantically rich and accessible markup}
12 | s.email = %q{justin@indent.com.au}
13 | s.extra_rdoc_files = ["README.textile"]
14 | s.files = Dir.glob("generators/**/*") + Dir.glob("lib/**/*") + Dir.glob("rails/*") + %w(MIT-LICENSE README.textile init.rb)
15 | s.homepage = %q{http://github.com/justinfrench/formtastic/tree/master}
16 | s.post_install_message = %q{
17 | ========================================================================
18 | Thanks for installing Formtastic!
19 | ------------------------------------------------------------------------
20 | You can now (optionally) run the generator to copy some stylesheets and
21 | a config initializer into your application:
22 | rails generate formtastic:install # Rails 3
23 | ./script/generate formtastic # Rails 2
24 |
25 | To generate some semantic form markup for your existing models, just run:
26 | rails generate formtastic:form MODEL_NAME # Rails 3
27 | ./script/generate form MODEL_NAME # Rails 2
28 |
29 | Find out more and get involved:
30 | http://github.com/justinfrench/formtastic
31 | http://groups.google.com.au/group/formtastic
32 | ========================================================================
33 | }
34 | s.rdoc_options = ["--charset=UTF-8"]
35 | s.require_paths = ["lib"]
36 | s.rubygems_version = %q{1.3.6}
37 |
38 | s.add_dependency(%q, [">= 2.3.7"])
39 | s.add_dependency(%q, [">= 2.3.7"])
40 | s.add_dependency(%q, [">= 0.4.0"])
41 |
42 | if ENV['RAILS_2']
43 | s.add_development_dependency(%q, ["~> 2.3.8"])
44 | else
45 | s.add_development_dependency(%q, [">= 3.0.0"])
46 | end
47 | s.add_development_dependency(%q, ["~> 2.0.0"])
48 | s.add_development_dependency(%q, [">= 1.0.0"])
49 | s.add_development_dependency(%q, ["~> 0.8.3"])
50 |
51 | end
52 |
--------------------------------------------------------------------------------
/spec/include_blank_spec.rb:
--------------------------------------------------------------------------------
1 | # encoding: utf-8
2 | require 'spec_helper'
3 |
4 | describe "*select: options[:include_blank]" do
5 |
6 | include FormtasticSpecHelper
7 |
8 | before do
9 | @output_buffer = ''
10 | mock_everything
11 |
12 | @new_post.stub!(:author_id).and_return(nil)
13 | @new_post.stub!(:publish_at).and_return(nil)
14 |
15 | @select_input_types = {
16 | :select => :author,
17 | :datetime => :publish_at,
18 | :date => :publish_at,
19 | :time => :publish_at
20 | }
21 | end
22 |
23 | describe 'when :include_blank is not set' do
24 | it 'blank value should be included if the default value specified in config is true' do
25 | ::Formtastic::SemanticFormBuilder.include_blank_for_select_by_default = true
26 | @select_input_types.each do |as, attribute|
27 | form = semantic_form_for(@new_post) do |builder|
28 | concat(builder.input(attribute, :as => as))
29 | end
30 | output_buffer.concat(form) if Formtastic::Util.rails3?
31 | output_buffer.should have_tag("form li select option[@value='']", "")
32 | end
33 | end
34 |
35 | it 'blank value should not be included if the default value specified in config is false' do
36 | ::Formtastic::SemanticFormBuilder.include_blank_for_select_by_default = false
37 | @select_input_types.each do |as, attribute|
38 | form = semantic_form_for(@new_post) do |builder|
39 | concat(builder.input(attribute, :as => as))
40 | end
41 | output_buffer.concat(form) if Formtastic::Util.rails3?
42 | output_buffer.should_not have_tag("form li select option[@value='']", "")
43 | end
44 | end
45 |
46 | after do
47 | ::Formtastic::SemanticFormBuilder.include_blank_for_select_by_default = true
48 | end
49 | end
50 |
51 | describe 'when :include_blank is set to false' do
52 | it 'should not have a blank option' do
53 | @select_input_types.each do |as, attribute|
54 | form = semantic_form_for(@new_post) do |builder|
55 | concat(builder.input(attribute, :as => as, :include_blank => false))
56 | end
57 | output_buffer.concat(form) if Formtastic::Util.rails3?
58 | output_buffer.should_not have_tag("form li select option[@value='']", "")
59 | end
60 | end
61 | end
62 |
63 | describe 'when :include_blank => true is set' do
64 | it 'should have a blank select option' do
65 | @select_input_types.each do |as, attribute|
66 | form = semantic_form_for(@new_post) do |builder|
67 | concat(builder.input(attribute, :as => as, :include_blank => true))
68 | end
69 | output_buffer.concat(form) if Formtastic::Util.rails3?
70 | output_buffer.should have_tag("form li select option[@value='']", "")
71 | end
72 | end
73 | end
74 | end
75 |
--------------------------------------------------------------------------------
/spec/inputs/time_zone_input_spec.rb:
--------------------------------------------------------------------------------
1 | # encoding: utf-8
2 | require 'spec_helper'
3 |
4 | describe 'time_zone input' do
5 |
6 | include FormtasticSpecHelper
7 |
8 | before do
9 | @output_buffer = ''
10 | mock_everything
11 |
12 | @form = semantic_form_for(@new_post) do |builder|
13 | concat(builder.input(:time_zone))
14 | end
15 | end
16 |
17 | it_should_have_input_wrapper_with_class("time_zone")
18 | it_should_have_input_wrapper_with_id("post_time_zone_input")
19 | it_should_apply_error_logic_for_input_type(:time_zone)
20 |
21 | it 'should generate a label for the input' do
22 | output_buffer.concat(@form) if Formtastic::Util.rails3?
23 | output_buffer.should have_tag('form li label')
24 | output_buffer.should have_tag('form li label[@for="post_time_zone"]')
25 | output_buffer.should have_tag('form li label', /Time zone/)
26 | end
27 |
28 | it "should generate a select" do
29 | output_buffer.concat(@form) if Formtastic::Util.rails3?
30 | output_buffer.should have_tag("form li select")
31 | output_buffer.should have_tag("form li select#post_time_zone")
32 | output_buffer.should have_tag("form li select[@name=\"post[time_zone]\"]")
33 | end
34 |
35 | it 'should use input_html to style inputs' do
36 | form = semantic_form_for(@new_post) do |builder|
37 | concat(builder.input(:time_zone, :input_html => { :class => 'myclass' }))
38 | end
39 | output_buffer.concat(form) if Formtastic::Util.rails3?
40 | output_buffer.should have_tag("form li select.myclass")
41 | end
42 |
43 | describe "when namespace is provided" do
44 |
45 | before do
46 | @output_buffer = ''
47 | mock_everything
48 |
49 | @form = semantic_form_for(@new_post, :namespace => 'context2') do |builder|
50 | concat(builder.input(:time_zone))
51 | end
52 | end
53 |
54 | it_should_have_input_wrapper_with_id("context2_post_time_zone_input")
55 | it_should_have_select_with_id("context2_post_time_zone")
56 | it_should_have_label_for("context2_post_time_zone")
57 |
58 | end
59 |
60 | describe 'when no object is given' do
61 | before(:each) do
62 | @form = semantic_form_for(:project, :url => 'http://test.host/') do |builder|
63 | concat(builder.input(:time_zone, :as => :time_zone))
64 | end
65 | end
66 |
67 | it 'should generate labels' do
68 | output_buffer.concat(@form) if Formtastic::Util.rails3?
69 | output_buffer.should have_tag('form li label')
70 | output_buffer.should have_tag('form li label[@for="project_time_zone"]')
71 | output_buffer.should have_tag('form li label', /Time zone/)
72 | end
73 |
74 | it 'should generate select inputs' do
75 | output_buffer.concat(@form) if Formtastic::Util.rails3?
76 | output_buffer.should have_tag("form li select")
77 | output_buffer.should have_tag("form li select#project_time_zone")
78 | output_buffer.should have_tag("form li select[@name=\"project[time_zone]\"]")
79 | end
80 | end
81 |
82 | end
83 |
--------------------------------------------------------------------------------
/spec/custom_builder_spec.rb:
--------------------------------------------------------------------------------
1 | # encoding: utf-8
2 | require 'spec_helper'
3 |
4 | describe 'Formtastic::SemanticFormHelper.builder' do
5 |
6 | include FormtasticSpecHelper
7 |
8 | class MyCustomFormBuilder < ::Formtastic::SemanticFormBuilder
9 | def awesome_input(method, options)
10 | self.text_field(method)
11 | end
12 | end
13 |
14 | before do
15 | @output_buffer = ''
16 | mock_everything
17 | end
18 |
19 | it 'is the Formtastic::SemanticFormBuilder by default' do
20 | ::Formtastic::SemanticFormHelper.builder.should == ::Formtastic::SemanticFormBuilder
21 | end
22 |
23 | it 'can be configured to use your own custom form builder' do
24 | # Set it to a custom builder class
25 | ::Formtastic::SemanticFormHelper.builder = MyCustomFormBuilder
26 | ::Formtastic::SemanticFormHelper.builder.should == MyCustomFormBuilder
27 |
28 | # Reset it to the default
29 | ::Formtastic::SemanticFormHelper.builder = ::Formtastic::SemanticFormBuilder
30 | ::Formtastic::SemanticFormHelper.builder.should == ::Formtastic::SemanticFormBuilder
31 | end
32 |
33 | it 'should allow custom settings per form builder subclass' do
34 | with_config(:all_fields_required_by_default, true) do
35 | MyCustomFormBuilder.all_fields_required_by_default = false
36 |
37 | MyCustomFormBuilder.all_fields_required_by_default.should be_false
38 | ::Formtastic::SemanticFormBuilder.all_fields_required_by_default.should be_true
39 | end
40 | end
41 |
42 | describe "when using a custom builder" do
43 |
44 | before do
45 | @new_post.stub!(:title)
46 | ::Formtastic::SemanticFormHelper.builder = MyCustomFormBuilder
47 | end
48 |
49 | after do
50 | ::Formtastic::SemanticFormHelper.builder = ::Formtastic::SemanticFormBuilder
51 | end
52 |
53 | describe "semantic_form_for" do
54 |
55 | it "should yield an instance of the custom builder" do
56 | semantic_form_for(@new_post) do |builder|
57 | builder.class.should == MyCustomFormBuilder
58 | end
59 | end
60 |
61 | it "should allow me to call my custom input" do
62 | semantic_form_for(@new_post) do |builder|
63 | concat(builder.input(:title, :as => :awesome))
64 | end
65 | end
66 |
67 | end
68 |
69 | describe "semantic_fields_for" do
70 |
71 | it "should yield an instance of the parent form builder" do
72 | semantic_form_for(@new_post) do |builder|
73 | builder.semantic_fields_for(:author) do |nested_builder|
74 | nested_builder.class.should == MyCustomFormBuilder
75 | end
76 | end
77 | end
78 |
79 | end
80 |
81 | end
82 |
83 | describe "when using a builder passed to form options" do
84 |
85 | describe "semantic_fields_for" do
86 |
87 | it "should yield an instance of the parent form builder" do
88 | semantic_form_for(@new_post, :builder => MyCustomFormBuilder) do |builder|
89 | builder.semantic_fields_for(:author) do |nested_builder|
90 | nested_builder.class.should == MyCustomFormBuilder
91 | end
92 | end
93 | end
94 |
95 | end
96 |
97 | end
98 | end
99 |
--------------------------------------------------------------------------------
/spec/semantic_fields_for_spec.rb:
--------------------------------------------------------------------------------
1 | # encoding: utf-8
2 | require 'spec_helper'
3 |
4 | describe 'SemanticFormBuilder#semantic_fields_for' do
5 |
6 | include FormtasticSpecHelper
7 |
8 | before do
9 | @output_buffer = ''
10 | mock_everything
11 | @new_post.stub!(:author).and_return(::Author.new)
12 | end
13 |
14 | it 'yields an instance of SemanticFormHelper.builder' do
15 | semantic_form_for(@new_post) do |builder|
16 | builder.semantic_fields_for(:author) do |nested_builder|
17 | nested_builder.class.should == ::Formtastic::SemanticFormHelper.builder
18 | end
19 | end
20 | end
21 |
22 | it 'nests the object name' do
23 | semantic_form_for(@new_post) do |builder|
24 | builder.semantic_fields_for(@bob) do |nested_builder|
25 | nested_builder.object_name.should == 'post[author]'
26 | end
27 | end
28 | end
29 |
30 | it 'should sanitize html id for li tag' do
31 | @bob.stub!(:column_for_attribute).and_return(mock('column', :type => :string, :limit => 255))
32 | form = semantic_form_for(@new_post) do |builder|
33 | concat(builder.semantic_fields_for(@bob, :index => 1) do |nested_builder|
34 | concat(nested_builder.inputs(:login))
35 | end)
36 | end
37 | output_buffer.concat(form) if Formtastic::Util.rails3?
38 | output_buffer.should have_tag('form fieldset.inputs #post_author_1_login_input')
39 | # Not valid selector, so using good ol' regex
40 | output_buffer.should_not =~ /id="post\[author\]_1_login_input"/
41 | # <=> output_buffer.should_not have_tag('form fieldset.inputs #post[author]_1_login_input')
42 | end
43 |
44 | it 'should use namespace provided in nested fields' do
45 | @bob.stub!(:column_for_attribute).and_return(mock('column', :type => :string, :limit => 255))
46 | form = semantic_form_for(@new_post, :namespace => 'context2') do |builder|
47 | concat(builder.semantic_fields_for(@bob, :index => 1) do |nested_builder|
48 | concat(nested_builder.inputs(:login))
49 | end)
50 | end
51 | output_buffer.concat(form) if Formtastic::Util.rails3?
52 | output_buffer.should have_tag('form fieldset.inputs #context2_post_author_1_login_input')
53 | end
54 |
55 | context "when I rendered my own hidden id input" do
56 |
57 | before do
58 | output_buffer.replace ''
59 |
60 | @fred.posts.size.should == 1
61 | @fred.posts.first.stub!(:persisted?).and_return(true)
62 | @fred.stub!(:posts_attributes=)
63 |
64 | form = semantic_form_for(@fred) do |builder|
65 | concat(builder.semantic_fields_for(:posts) do |nested_builder|
66 | concat(nested_builder.input(:id, :as => :hidden))
67 | concat(nested_builder.input(:title))
68 | end)
69 | end
70 | output_buffer.concat(form) if Formtastic::Util.rails3?
71 | end
72 |
73 | it "should only render one hidden input (my one)" do
74 | output_buffer.should have_tag 'input#author_posts_attributes_0_id', :count => 1
75 | end
76 |
77 | it "should render the hidden input inside an li.hidden" do
78 | output_buffer.should have_tag 'li.hidden input#author_posts_attributes_0_id'
79 | end
80 | end
81 |
82 | end
83 |
84 |
--------------------------------------------------------------------------------
/lib/generators/formtastic/form/form_generator.rb:
--------------------------------------------------------------------------------
1 | # encoding: utf-8
2 | module Formtastic
3 | class FormGenerator < Rails::Generators::NamedBase
4 | desc "Generates formtastic form code based on an existing model. By default the " <<
5 | "generated code will be printed out directly in the terminal, and also copied " <<
6 | "to clipboard. Can optionally be saved into partial directly."
7 |
8 | argument :name, :type => :string, :required => true, :banner => 'ExistingModelName'
9 | argument :attributes, :type => :array, :default => [], :banner => 'field:type field:type'
10 |
11 | class_option :haml, :type => :boolean, :default => false, :group => :formtastic,
12 | :desc => "Generate HAML instead of ERB"
13 |
14 | class_option :partial, :type => :boolean, :default => false, :group => :formtastic,
15 | :desc => 'Generate a form partial in the model views path, i.e. "_form.html.erb" or "_form.html.haml"'
16 |
17 | class_option :controller, :type => :string, :default => false, :group => :formtastic,
18 | :desc => 'Generate for custom controller/view path - in case model and controller namespace is different, i.e. "admin/posts"'
19 |
20 | source_root File.expand_path('../../../templates', __FILE__)
21 |
22 | def create_or_show
23 | @attributes = self.columns if @attributes.empty?
24 |
25 | if options[:partial]
26 | empty_directory "app/views/#{controller_path}"
27 | template "_form.html.#{template_type}", "app/views/#{controller_path}/_form.html.#{template_type}"
28 | else
29 | template = File.read("#{self.class.source_root}/_form.html.#{template_type}")
30 | erb = ERB.new(template, nil, '-')
31 | generated_code = erb.result(binding).strip rescue nil
32 |
33 | puts "# ---------------------------------------------------------"
34 | puts "# GENERATED FORMTASTIC CODE"
35 | puts "# ---------------------------------------------------------"
36 | puts
37 | puts generated_code || "Nothing could be generated - model exists?"
38 | puts
39 | puts "# ---------------------------------------------------------"
40 | puts "Copied to clipboard - just paste it!" if save_to_clipboard(generated_code)
41 | end
42 | end
43 |
44 | protected
45 |
46 | IGNORED_COLUMNS = [:updated_at, :created_at].freeze
47 |
48 | def template_type
49 | @template_type ||= options[:haml] ? :haml : :erb
50 | end
51 |
52 | def controller_path
53 | @controller_path ||= if options[:controller]
54 | options[:controller].underscore
55 | else
56 | name.underscore.pluralize
57 | end
58 | end
59 |
60 | def columns
61 | @columns ||= self.name.camelize.constantize.content_columns.reject { |column| IGNORED_COLUMNS.include?(column.name.to_sym) }
62 | end
63 |
64 | def save_to_clipboard(data)
65 | return unless data
66 |
67 | begin
68 | case RUBY_PLATFORM
69 | when /win32/
70 | require 'win32/clipboard'
71 | ::Win32::Clipboard.data = data
72 | when /darwin/ # mac
73 | `echo "#{data}" | pbcopy`
74 | else # linux/unix
75 | `echo "#{data}" | xsel --clipboard` || `echo "#{data}" | xclip`
76 | end
77 | rescue LoadError
78 | false
79 | else
80 | true
81 | end
82 | end
83 | end
84 | end
85 |
--------------------------------------------------------------------------------
/spec/semantic_errors_spec.rb:
--------------------------------------------------------------------------------
1 | # encoding: utf-8
2 | require 'spec_helper'
3 |
4 | describe 'SemanticFormBuilder#semantic_errors' do
5 |
6 | include FormtasticSpecHelper
7 |
8 | before do
9 | @output_buffer = ''
10 | mock_everything
11 | @title_errors = ['must not be blank', 'must be awesome']
12 | @base_errors = ['base error message', 'nasty error']
13 | @base_error = 'one base error'
14 | @errors = mock('errors')
15 | @new_post.stub!(:errors).and_return(@errors)
16 | end
17 |
18 | describe 'when there is only one error on base' do
19 | before do
20 | @errors.stub!(:[]).with(:base).and_return(@base_error)
21 | end
22 |
23 | it 'should render an unordered list' do
24 | semantic_form_for(@new_post) do |builder|
25 | builder.semantic_errors.should have_tag('ul.errors li', @base_error)
26 | end
27 | end
28 | end
29 |
30 | describe 'when there is more than one error on base' do
31 | before do
32 | @errors.stub!(:[]).with(:base).and_return(@base_errors)
33 | end
34 |
35 | it 'should render an unordered list' do
36 | semantic_form_for(@new_post) do |builder|
37 | builder.semantic_errors.should have_tag('ul.errors')
38 | @base_errors.each do |error|
39 | builder.semantic_errors.should have_tag('ul.errors li', error)
40 | end
41 | end
42 | end
43 | end
44 |
45 | describe 'when there are errors on title' do
46 | before do
47 | @errors.stub!(:[]).with(:title).and_return(@title_errors)
48 | @errors.stub!(:[]).with(:base).and_return([])
49 | end
50 |
51 | it 'should render an unordered list' do
52 | semantic_form_for(@new_post) do |builder|
53 | title_name = builder.send(:localized_string, :title, :title, :label) || builder.send(:humanized_attribute_name, :title)
54 | builder.semantic_errors(:title).should have_tag('ul.errors li', title_name << " " << @title_errors.to_sentence)
55 | end
56 | end
57 | end
58 |
59 | describe 'when there are errors on title and base' do
60 | before do
61 | @errors.stub!(:[]).with(:title).and_return(@title_errors)
62 | @errors.stub!(:[]).with(:base).and_return(@base_error)
63 | end
64 |
65 | it 'should render an unordered list' do
66 | semantic_form_for(@new_post) do |builder|
67 | title_name = builder.send(:localized_string, :title, :title, :label) || builder.send(:humanized_attribute_name, :title)
68 | builder.semantic_errors(:title).should have_tag('ul.errors li', title_name << " " << @title_errors.to_sentence)
69 | builder.semantic_errors(:title).should have_tag('ul.errors li', @base_error)
70 | end
71 | end
72 | end
73 |
74 | describe 'when there are no errors' do
75 | before do
76 | @errors.stub!(:[]).with(:title).and_return(nil)
77 | @errors.stub!(:[]).with(:base).and_return(nil)
78 | end
79 |
80 | it 'should return nil' do
81 | semantic_form_for(@new_post) do |builder|
82 | builder.semantic_errors(:title).should be_nil
83 | end
84 | end
85 | end
86 |
87 | describe 'when there is one error on base and options with class is passed' do
88 | before do
89 | @errors.stub!(:[]).with(:base).and_return(@base_error)
90 | end
91 |
92 | it 'should render an unordered list with given class' do
93 | semantic_form_for(@new_post) do |builder|
94 | builder.semantic_errors(:class => "awesome").should have_tag('ul.awesome li', @base_error)
95 | end
96 | end
97 | end
98 | end
99 |
--------------------------------------------------------------------------------
/spec/label_spec.rb:
--------------------------------------------------------------------------------
1 | # encoding: utf-8
2 | require 'spec_helper'
3 |
4 | describe 'SemanticFormBuilder#label' do
5 |
6 | include FormtasticSpecHelper
7 |
8 | before do
9 | @output_buffer = ''
10 | mock_everything
11 | end
12 |
13 | it 'should humanize the given attribute' do
14 | semantic_form_for(@new_post) do |builder|
15 | builder.label(:login).should have_tag('label', :with => /Login/)
16 | end
17 | end
18 |
19 | describe 'when required is given' do
20 | it 'should append a required note' do
21 | semantic_form_for(@new_post) do |builder|
22 | builder.label(:login, nil, :required => true).should have_tag('label abbr')
23 | end
24 | end
25 |
26 | it 'should allow require option to be given as second argument' do
27 | semantic_form_for(@new_post) do |builder|
28 | builder.label(:login, :required => true).should have_tag('label abbr')
29 | end
30 | end
31 | end
32 |
33 | describe 'when a collection is given' do
34 | it 'should use a supplied label_method for simple collections' do
35 | form = semantic_form_for(:project, :url => 'http://test.host') do |builder|
36 | concat(builder.input(:author_id, :as => :check_boxes, :collection => [:a, :b, :c], :value_method => :to_s, :label_method => proc {|f| ('Label_%s' % [f])}))
37 | end
38 | output_buffer.concat(form) if Formtastic::Util.rails3?
39 | output_buffer.should have_tag('form li fieldset ol li label', :with => /Label_[abc]/, :count => 3)
40 | end
41 |
42 | it 'should use a supplied value_method for simple collections' do
43 | form = semantic_form_for(:project, :url => 'http://test.host') do |builder|
44 | concat(builder.input(:author_id, :as => :check_boxes, :collection => [:a, :b, :c], :value_method => proc {|f| ('Value_%s' % [f.to_s])}))
45 | end
46 | output_buffer.concat(form) if Formtastic::Util.rails3?
47 | output_buffer.should have_tag('form li fieldset ol li label input[value="Value_a"]')
48 | output_buffer.should have_tag('form li fieldset ol li label input[value="Value_b"]')
49 | output_buffer.should have_tag('form li fieldset ol li label input[value="Value_c"]')
50 | end
51 | end
52 |
53 | describe 'when label is given' do
54 | it 'should allow the text to be given as label option' do
55 | semantic_form_for(@new_post) do |builder|
56 | builder.label(:login, :required => true, :label => 'My label').should have_tag('label', :with => /My label/)
57 | end
58 | end
59 |
60 | it 'should return nil if label is false' do
61 | semantic_form_for(@new_post) do |builder|
62 | builder.label(:login, :label => false).should be_blank
63 | end
64 | end
65 |
66 | it 'should html escape the label string by default' do
67 | semantic_form_for(@new_post) do |builder|
68 | builder.label(:login, :required => false, :label => 'My label').should == ""
69 | end
70 | end
71 |
72 | it 'should not html escape the label if configured that way' do
73 | ::Formtastic::SemanticFormBuilder.escape_html_entities_in_hints_and_labels = false
74 | semantic_form_for(@new_post) do |builder|
75 | builder.label(:login, :required => false, :label => 'My label').should == ""
76 | end
77 | end
78 |
79 | it 'should not html escape the label string for html_safe strings' do
80 | ::Formtastic::SemanticFormBuilder.escape_html_entities_in_hints_and_labels = true
81 | semantic_form_for(@new_post) do |builder|
82 | builder.label(:login, :required => false, :label => 'My label'.html_safe).should == ""
83 | end
84 | end
85 |
86 | end
87 |
88 | end
89 |
90 |
--------------------------------------------------------------------------------
/lib/generators/templates/formtastic.rb:
--------------------------------------------------------------------------------
1 | # encoding: utf-8
2 |
3 | # Set the default text field size when input is a string. Default is nil.
4 | # Formtastic::SemanticFormBuilder.default_text_field_size = 50
5 |
6 | # Set the default text area height when input is a text. Default is 20.
7 | # Formtastic::SemanticFormBuilder.default_text_area_height = 5
8 |
9 | # Set the default text area width when input is a text. Default is nil.
10 | # Formtastic::SemanticFormBuilder.default_text_area_width = 50
11 |
12 | # Should all fields be considered "required" by default?
13 | # Rails 2 only, ignored by Rails 3 because it will never fall back to this default.
14 | # Defaults to true.
15 | # Formtastic::SemanticFormBuilder.all_fields_required_by_default = true
16 |
17 | # Should select fields have a blank option/prompt by default?
18 | # Defaults to true.
19 | # Formtastic::SemanticFormBuilder.include_blank_for_select_by_default = true
20 |
21 | # Set the string that will be appended to the labels/fieldsets which are required
22 | # It accepts string or procs and the default is a localized version of
23 | # '*'. In other words, if you configure formtastic.required
24 | # in your locale, it will replace the abbr title properly. But if you don't want to use
25 | # abbr tag, you can simply give a string as below
26 | # Formtastic::SemanticFormBuilder.required_string = "(required)"
27 |
28 | # Set the string that will be appended to the labels/fieldsets which are optional
29 | # Defaults to an empty string ("") and also accepts procs (see required_string above)
30 | # Formtastic::SemanticFormBuilder.optional_string = "(optional)"
31 |
32 | # Set the way inline errors will be displayed.
33 | # Defaults to :sentence, valid options are :sentence, :list, :first and :none
34 | # Formtastic::SemanticFormBuilder.inline_errors = :sentence
35 | # Formtastic uses the following classes as default for hints, inline_errors and error list
36 |
37 | # If you override the class here, please ensure to override it in your formtastic_changes.css stylesheet as well
38 | # Formtastic::SemanticFormBuilder.default_hint_class = "inline-hints"
39 | # Formtastic::SemanticFormBuilder.default_inline_error_class = "inline-errors"
40 | # Formtastic::SemanticFormBuilder.default_error_list_class = "errors"
41 |
42 | # Set the method to call on label text to transform or format it for human-friendly
43 | # reading when formtastic is used without object. Defaults to :humanize.
44 | # Formtastic::SemanticFormBuilder.label_str_method = :humanize
45 |
46 | # Set the array of methods to try calling on parent objects in :select and :radio inputs
47 | # for the text inside each @