<commit_before>h1. Formtastic Sneaky Preview

Formtastic is a Rails FormBuilder DSL (with some other goodies) to make it far easier to create beautiful, semantically rich, syntactically awesome, readily stylable and wonderfully accessible HTML forms in your Rails applications.

h2. The Story

Hacked together forms were easy, but awesome forms with decent semantics, rich mark-up and plenty of CSS hooks were incredibly painful.  I was discouraged from doing things properly because it was too much mark-up and code to write.  One day, I finally had enough, so I opened up my text editor, and wrote a DSL for how I'd like to author forms:

<pre>
  <% semantic_form_for @article do |form| %>
  
    <% form.input_field_set :name => "Basic" do %>
      <%= form.input :title %>                               
      <%= form.input :body %>                                
      <%= form.input :section_id %>                          
      <%= form.input :publication_state_id, :as => :radio %> 
      <%= form.input :author_id, :as => :select %>                           
      <%= form.input :allow_comments, :label => "Allow commenting on this article" %>                      
    <% end %>                                                
  
    <% form.input_field_set :name => "Advanced" do %>
      <%= form.input :keywords, :required => false, :hint => "Example: ruby, rails, forms" %>        
      <%= form.input :extract, :required => false %>
      <%= form.input :description, :required => false %>
      <%= form.input :url_title, :required => false %>                           
    <% end %>

    <% form.button_field_set do %>                                    
      <%= form.cancel_button %>                             
      <%= form.commit_button %>                             
    <% end %>

  <% end %>
</pre>

I also wrote the accompanying HTML output I expected, favoring something very similar to the fieldsets, lists and other semantic elements <NAME> presented in "Learning to Love Forms":http://www.slideshare.net/AaronGustafson/learning-to-love-forms-web-directions-south-07, hacking together enough Ruby to prove it could be done.


h2. Why?

* web apps = lots of forms
* forms are so friggin' boring to code
* semantically rich & accessible forms really are possible
* the "V" is way behind the "M" and "C" in Rails' MVC – it's the ugly sibling
* best practices and common patterns have to start somewhere
* i need a challenge


h2. Opinions

* it should be easier to do things the right way than the wrong way
* sometimes _more mark-up_ is better
* elements and attribute hooks are _gold_ for stylesheet authors
* make the common things we do easy, yet still ensure uncommon things are still possible


h2. The Available Inputs

* :select (a select menu for belongs_to associations) - default for columns ending in '_id'
* :radio (a set of radio inputs for belongs_to associations) - alternative for columns ending in '_id'
* :password (a password input) - default for :string column types with 'password' in the method name
* :text (a textarea) - default for :text column types
* :date (a date select) - default for :date column types
* :datetime (a date and time select) - default for :datetime and :timestamp column types
* :time (a time select) - default for :time column types
* :boolean (a checkbox) - default for :boolean column types
* :boolean_select (a yes/no select box)
* :string (a text field) - default for :string column types
* :numeric (a text field, like string) - default for :integer, :float and :decimal column types

The documentation is pretty good for each of these (what it does, what the output is, etc) so go check it out.


h3. One day...

* calendars and other more humanized date/time selections
* vanilla html file selection to work well with things like ThoughtBot's "Paperclip":http://www.thoughtbot.com/projects/paperclip
* flash-based multi-file selection
* an interface for tagging and other has_many_through style associations

In the meantime, there's nothing stopping you from mixing some old fashioned HTML and ERB for custom widgets in with the Formtastic DLS stuff in your views, and I'd love to hear what others are finding a need for.

h3. Fields without database columns

Formtastic is pretty tightly coupled to ActiveRecord database columns, but it will at least _attempt_ to play nicely with your models other methods (like a virtual column 'full_name' which is split into first_name and last_name in a before save callback), and I'd like this to continue and improve.


h2. Configuration

If you wish, put something like this in config/initializers/formtastic_config.rb:

<pre>
  JustinFrench::Formtastic::SemanticFormBuilder.all_fields_required_by_default = false
  JustinFrench::Formtastic::SemanticFormBuilder.required_string = "(required)"
  JustinFrench::Formtastic::SemanticFormBuilder.optional_string = "(optional)"
</pre>



h2. Status

*THIS IS DEFINITELY NOT PRODUCTION-READY.  THINGS ARE GOING TO CHANGE A LOT.*

It's incredibly opinionated, incomplete, a work in progress, messy around the edges, messy in the middle too, tightly coupled to the database, tightly coupled to "my way" of doing things and also incredibly lacking in unit tests so far, but I hope you try it and offer some suggestions and improvements any way.


h2. Roadmap

* There's plenty of TODOs in the code
* get the basic form_for implementation complete, proven and *well tested* (did I mention how laborious testing form builders is?)
* improve the generic, reusable, stylesheets that prove this stuff works
* probably do a shortcut like <code><%= form.inputs :name, :login, :email, :bio %></code> for those that want the form with zero configuration 


h2. Usage

The smallest example:

<pre>
  <% semantic_form_for @user do |form| %>
    <% form.input_field_set do %>
      <%= form.input :name %>
      <%= form.input :email %>
      <%= form.input :password %>
      <%= form.input :department_id, :as => :radio %>
      <%= form.input :date_of_birth %>
    <% end %>
  <% end %>
</pre>

With an output something like:

<pre>
<form id="new-article-form" action="#" method="post">
  <fieldset>
    <legend><span>Create a new User</span></legend>
    <fieldset class="inputs">
      <ol>
        <li id="user_name_input" class="required string">
          <label for="user_name">Name <abbr title="required">*</abbr></label>
          <input type="text" id="user_name" name="user[name]" size="50" />
        </li>
        <li id="user_email_input" class="required string">
          <label for="user_email">Email <abbr title="required">*</abbr></label>
          <input type="text" id="user_email" name="user[email]" size="50" />
        </li>
      </ol>
    </fieldset>
  </fieldset>
</form>
</pre>


h2. Conventions & Prerequisites

In a few places (like radio or select widgets for belongs_to associations) Formtastic expects your ActiveRecord instances to respond to the <code>to_label</code> method (returning a String).  You can easily add this to your models, for example, a User object might want to return the user's first name, last name and login:

<pre>
class User < ActiveRecord::Base
  #...
  def to_label
    "#{first_name} #{last_name} (#{login})"
  end
end
</pre>


h2. Dependencies

None! But if you have the "ValidationReflection":http://github.com/redinger/validation_reflection plugin is installed, you won't have to specify the :required option (it checks the validations on the model instead).


h2. What about Stylesheets?

A proof-of-concept (very much a work-in-progress) stylesheet is provided which you can include in your layout.  Customisation is best achieved by overriding these styles in an additional stylesheet so that the formtastic styles can be updated without clobbering your changes.

1. Use the generator to copy the formtastic.css and formtastic_changes.css into your public directory

<pre>
./script/generate formtastic_stylesheets
</pre>

2. Add both formtastic.css and formtastic_changes.css to your layout:

<pre>
<%= stylesheet_link_tag "formtastic" %>
<%= stylesheet_link_tag "formtastic_changes" %>
</pre>



h2. Compatibility
<commit_msg>updated the dependencies in the README to cover the test suite<commit_after>h1. Formtastic Sneaky Preview

Formtastic is a Rails FormBuilder DSL (with some other goodies) to make it far easier to create beautiful, semantically rich, syntactically awesome, readily stylable and wonderfully accessible HTML forms in your Rails applications.

h2. The Story

Hacked together forms were easy, but awesome forms with decent semantics, rich mark-up and plenty of CSS hooks were incredibly painful.  I was discouraged from doing things properly because it was too much mark-up and code to write.  One day, I finally had enough, so I opened up my text editor, and wrote a DSL for how I'd like to author forms:

<pre>
  <% semantic_form_for @article do |form| %>
  
    <% form.input_field_set :name => "Basic" do %>
      <%= form.input :title %>                               
      <%= form.input :body %>                                
      <%= form.input :section_id %>                          
      <%= form.input :publication_state_id, :as => :radio %> 
      <%= form.input :author_id, :as => :select %>                           
      <%= form.input :allow_comments, :label => "Allow commenting on this article" %>                      
    <% end %>                                                
  
    <% form.input_field_set :name => "Advanced" do %>
      <%= form.input :keywords, :required => false, :hint => "Example: ruby, rails, forms" %>        
      <%= form.input :extract, :required => false %>
      <%= form.input :description, :required => false %>
      <%= form.input :url_title, :required => false %>                           
    <% end %>

    <% form.button_field_set do %>                                    
      <%= form.cancel_button %>                             
      <%= form.commit_button %>                             
    <% end %>

  <% end %>
</pre>

I also wrote the accompanying HTML output I expected, favoring something very similar to the fieldsets, lists and other semantic elements <NAME> presented in "Learning to Love Forms":http://www.slideshare.net/AaronGustafson/learning-to-love-forms-web-directions-south-07, hacking together enough Ruby to prove it could be done.


h2. Why?

* web apps = lots of forms
* forms are so friggin' boring to code
* semantically rich & accessible forms really are possible
* the "V" is way behind the "M" and "C" in Rails' MVC – it's the ugly sibling
* best practices and common patterns have to start somewhere
* i need a challenge


h2. Opinions

* it should be easier to do things the right way than the wrong way
* sometimes _more mark-up_ is better
* elements and attribute hooks are _gold_ for stylesheet authors
* make the common things we do easy, yet still ensure uncommon things are still possible


h2. The Available Inputs

* :select (a select menu for belongs_to associations) - default for columns ending in '_id'
* :radio (a set of radio inputs for belongs_to associations) - alternative for columns ending in '_id'
* :password (a password input) - default for :string column types with 'password' in the method name
* :text (a textarea) - default for :text column types
* :date (a date select) - default for :date column types
* :datetime (a date and time select) - default for :datetime and :timestamp column types
* :time (a time select) - default for :time column types
* :boolean (a checkbox) - default for :boolean column types
* :boolean_select (a yes/no select box)
* :string (a text field) - default for :string column types
* :numeric (a text field, like string) - default for :integer, :float and :decimal column types

The documentation is pretty good for each of these (what it does, what the output is, etc) so go check it out.


h3. One day...

* calendars and other more humanized date/time selections
* vanilla html file selection to work well with things like ThoughtBot's "Paperclip":http://www.thoughtbot.com/projects/paperclip
* flash-based multi-file selection
* an interface for tagging and other has_many_through style associations

In the meantime, there's nothing stopping you from mixing some old fashioned HTML and ERB for custom widgets in with the Formtastic DLS stuff in your views, and I'd love to hear what others are finding a need for.

h3. Fields without database columns

Formtastic is pretty tightly coupled to ActiveRecord database columns, but it will at least _attempt_ to play nicely with your models other methods (like a virtual column 'full_name' which is split into first_name and last_name in a before save callback), and I'd like this to continue and improve.


h2. Configuration

If you wish, put something like this in config/initializers/formtastic_config.rb:

<pre>
  JustinFrench::Formtastic::SemanticFormBuilder.all_fields_required_by_default = false
  JustinFrench::Formtastic::SemanticFormBuilder.required_string = "(required)"
  JustinFrench::Formtastic::SemanticFormBuilder.optional_string = "(optional)"
</pre>



h2. Status

*THIS IS DEFINITELY NOT PRODUCTION-READY.  THINGS ARE GOING TO CHANGE A LOT.*

It's incredibly opinionated, incomplete, a work in progress, messy around the edges, messy in the middle too, tightly coupled to the database, tightly coupled to "my way" of doing things and also incredibly lacking in unit tests so far, but I hope you try it and offer some suggestions and improvements any way.


h2. Roadmap

* There's plenty of TODOs in the code
* get the basic form_for implementation complete, proven and *well tested* (did I mention how laborious testing form builders is?)
* improve the generic, reusable, stylesheets that prove this stuff works
* probably do a shortcut like <code><%= form.inputs :name, :login, :email, :bio %></code> for those that want the form with zero configuration 


h2. Usage

The smallest example:

<pre>
  <% semantic_form_for @user do |form| %>
    <% form.input_field_set do %>
      <%= form.input :name %>
      <%= form.input :email %>
      <%= form.input :password %>
      <%= form.input :department_id, :as => :radio %>
      <%= form.input :date_of_birth %>
    <% end %>
  <% end %>
</pre>

With an output something like:

<pre>
<form id="new-article-form" action="#" method="post">
  <fieldset>
    <legend><span>Create a new User</span></legend>
    <fieldset class="inputs">
      <ol>
        <li id="user_name_input" class="required string">
          <label for="user_name">Name <abbr title="required">*</abbr></label>
          <input type="text" id="user_name" name="user[name]" size="50" />
        </li>
        <li id="user_email_input" class="required string">
          <label for="user_email">Email <abbr title="required">*</abbr></label>
          <input type="text" id="user_email" name="user[email]" size="50" />
        </li>
      </ol>
    </fieldset>
  </fieldset>
</form>
</pre>


h2. Conventions & Prerequisites

In a few places (like radio or select widgets for belongs_to associations) Formtastic expects your ActiveRecord instances to respond to the <code>to_label</code> method (returning a String).  You can easily add this to your models, for example, a User object might want to return the user's first name, last name and login:

<pre>
class User < ActiveRecord::Base
  #...
  def to_label
    "#{first_name} #{last_name} (#{login})"
  end
end
</pre>


h2. Dependencies

There are none, but...

* if you have the "ValidationReflection":http://github.com/redinger/validation_reflection plugin is installed, you won't have to specify the :required option (it checks the validations on the model instead)
* rspec, rspec_hpricot_matchers and rcov gems (plus any of their own dependencies) are required for the test suite


h2. What about Stylesheets?

A proof-of-concept (very much a work-in-progress) stylesheet is provided which you can include in your layout.  Customisation is best achieved by overriding these styles in an additional stylesheet so that the formtastic styles can be updated without clobbering your changes.

1. Use the generator to copy the formtastic.css and formtastic_changes.css into your public directory

<pre>
./script/generate formtastic_stylesheets
</pre>

2. Add both formtastic.css and formtastic_changes.css to your layout:

<pre>
<%= stylesheet_link_tag "formtastic" %>
<%= stylesheet_link_tag "formtastic_changes" %>
</pre>



h2. Compatibility

{'fraction_non_alphanumeric': 0.09281600484995453, 'fraction_numerical': 0.0027887238557138525, 'mean_word_length': 3.3559545814628993, 'pattern_counts': {'":': 6, '<': 159, '<?xml version=': 0, '>': 179, 'https://': 0, 'lorem ipsum': 0, 'www.': 4, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 6, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '1146238', 'n_tokens_mistral': 4794, 'n_tokens_neox': 4467, 'n_words': 1963}