Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Rails plugin to allow your users to build their own forms in your app.
Ruby JavaScript
branch: master

This branch is 2 commits ahead of tcocca:master

Fetching latest commit…

Cannot retrieve the latest commit at this time

Failed to load latest commit information.
app
generators/dynamic_forms
lib
public
tasks
CHANGELOG.rdoc
MIT-LICENSE
README.rdoc
init.rb

README.rdoc

DynamicForms

Major Updates and refactoring done by Tom Cocca in 2010 Originally Created by Chris Powers, March 19, 2009

Make Your Own Forms

The DynamicForms plugin is an engine that allows your users to create their own forms on your Web app. These forms act like regular Rails forms, using validation, error checking, the works.

Once you've installed the plugin run the generator and all the files have been copied into your app, feel free to customize as you see fit. Here's a few suggestions:

  • You will probably want to add relationships between Forms, FormSubmissions and your creator/submitter models ** See the Section on DynamicForms Relationships

  • You will also probably want to add your login authentication to the FormsController and FormSubmissionsController

  • I tried not to presuppose much in terms of styling, CSS class names, etc., so you will need to significantly alter some of the views to integrate them into your app

For those of you who can make use of this plugin, I hope that this saves you a lot of time!

INSTALLATION

Install as a plugin:

script/plugin install git://github.com/tcocca/dynamic_forms.git

Run the generator:

script/generate dynamic_forms

The generator will generate a migration,a bunch of models, a default locale file (see internationalization section) and a configuration initializer (see configuration section). The model files will just have includes to modules that are in the lib directory of the plugin. The generator also adds a routes definition to the 'config/routes.rb' file as the very top route. You should see:

DynamicForms::Routes.draw(map)

See the section on overriding controllers for more info if you need it.

Install the public assets (only Prototype JS support for now, soon to add jQuery)

rake dynamic_forms:install_assets

The rake task will install JS into 'public/javascripts/dynamic_forms/dynamic_forms_prototype.js' and 1 image for the drag and drop sorting into 'public/images/dynamic_forms/arrow_move.png'.

Also, the rake task only copies the files if they are not already there, so if you have modified the JS but want the original back you must delete the file and then re-run the rake task

Add the JS include tag to your layout (relies on Prototype so include the defaults):

<%= javascript_include_tag :defaults %>
<%= javascript_include_tag :dynamic_forms_prototype %>

Finally, the controllers do add some flash messages but I have not put the flash display on the views so you will most likely have it on your layout files already or you will want to add it somewhere. For Example:

<% flash.each do |key, value| -%>
  <div id="flash_<%= key %>"><%=h value %></div>
<% end -%>

DYNAMIC FORMS RELATIONSHIPS

Creator Relationships

To associate a form with its creator add the active record mixin is_form_creator to that model, ex:

class User < ActiveRecord::Base
  # other stuff

  is_form_creator

  # other stuff
end

This adds the following relationship:

has_many :created_forms, :as => :creator, :class_name => 'Form', :dependent => :nullify

So your user model in this case will have many created_forms and the form belongs to a creator. The :creator relationship is a polymorphic relationship so you can have multiple models that have the is_form_creator mixin.

Submitter Relationships

To associate a form_submission with its submitter add the AR mixin is_form_submitter to that model, ex:

class User < ActiveRecord::Base
  # other stuff

  is_form_submitter

  # other stuff
end

This adds the following relationship:

has_many :form_submissions, :as => :submitter, :dependent => :nullify

So your user model in that case with have many form_submissions and the form_submission belongs to a submitter. Just like the is_form_creator mixin, this mixin adds a polymorphic relationship so multiple models can have form_submissions.

CURRENT FORM OPTIONS

  • Create and edit a form

  • Choose form fields

  • Set validations on the field

  • Set form “instruction text” that appears above the form fields

  • Set form “confirmation text” that appears after a form has been submitted successfully

  • Ability to opt to have an email sent on successful form submission with file uploads as attachments

  • Can set the delivery email on a per form basis

  • On submission the answers are validated

  • File Field uploads are only saved to the file system for a submission that passes validation

  • Ability to see all form submissions with answers

  • Drag and Drop sorting of form fields and form field options

Field Types:

  • Text Field

  • Text Area

  • Check Box

  • Check Box Group

  • Select

    • If the field is not required then a blank option is added

    • If the field is required, the first field option by position (order) is the first option in list (default)

  • File Field

  • Radio Button Select

    • If the field is required make the first form_field_option by position (order) selected by default is the form_submission value for that field is blank

    • If the user chooses a different option and the form submission is invalid the option chose stays selected (this is expected behavior)

  • Time Select

  • Date Select

  • Datetime Select

Validations:

(Field Types applicable in ())

  • Required (Text Field, Text Area, File Field, Select, Check Box Group, Radio Button Select, Time Select, Date Select, Datetime Select)

  • Phone Number (Text Field)

  • Email Address (Text Field)

  • Zip Code (Text Field)

  • URL (Text Field)

  • Min Characters (Text Field, Text Area)

  • Max Characters (Text Field, Text Area)

  • Number (Text Field)

  • Mime Types (File Field) - if this option is left blank it will use a default set of mime types so there is always validation on a file upload

  • Confirmed (Check Box) - checkbox must be checked, useful for “you agree” type of questions

  • Time (Time Select) - automatically validates to check for a valid time format

  • Date (Date Select) - automatically validates to check for a valid date format

  • Datetime (Datetime Select) - automatically validates to check for a valid datetime format

INTERNATIONALIZATION

The generator command creates a default locale file at config/locales/dynamic_forms.yml

You can modify the file to you liking and add additional language support.

Not only does this add the benefit of supporting internationalization but it also makes it much easier to change the default values for flash messages and validations, etc …

CONFIGURATION

The generator creates a config initializer at config/initializers/dynamic_forms.rb that contains documentation on all the options with the default values

There are 4 configuration options

mailer_sender: the email address that the email notifications come from

field_types: the field types that your users can choose from, defaults to all available fields. If you want to add a new field type or remove a field type just edit this array

validation_types: the available validations, defaults to all available. The remove options or add a new custom validation just edit the array.

valid_mime_types: for file fields this is the default list of mimetypes that are valid. These can be customized on a per field basis or edit the default array.

OVERRIDING FUNCTIONALITY

Controllers

The generator added a routes definition:

DynamicForms::Routes.draw(map)

which defines the following:

map.resources :forms, :controller => 'dynamic_forms/forms' do |forms|
  forms.resources :form_submissions,
    :controller => "dynamic_forms/form_submissions",
    :only => [:index, :show, :new, :create]
end

You can see that the controllers are in the DynamicForms namespace. This means overriding them is pretty easy. All you need to do is create a new controller that is a subclass of a DynamicForms controller. For Example:

class FormsController < DynamicForms::FormsController
  def new
    @form = ::Form.new(:submit_label => 'Submit')
    @form.creator = current_user #set the creator of the form
    render :template => "forms/new"
  end
end

And then you must add a new route definition above the dynamic forms generated route in your routes file as any routes defined first take precedence.

map.resources :forms, :controller => 'forms'
DynamicForms::Routes.draw(map)

You will most likely be doing this controller overriding so that you can set creator and submitter values for forms and form_submissions (see the section on relationships) as I have not presupposed any of this functionality, I have made it easier though with polymorphic associations so you can you any models you would like. The good news is that you only need to have the actions that you need to override in your subclassed controller.

Views

To change the views (which will need to happen in almost every case), just copy the view folder that you want out of vendor/plugins/dynamic_forms/app/views and put it in app/views.

You don't have to change every view either, you could only copy the views that you plan on changing.

  • Eventually I will build a generator to do the copying of the views directory for you, this is on the roadmap, just not done yet.

Models

The models that are generated have all of the functionality included in through a module. This means that to change functionality should just be a matter of overriding that method in the generated model file. For example, if you always want to include a blank option on a select no matter if the field is required or not you could do the following:

class FormField::Select < FormField
  include DynamicForms::Models::FieldTypes::Select

  def field_helper_options
    {:include_blank => true}
  end

end

TODO

  • Better Documentation

  • Shoulda and Cucumber Tests

  • Make Javascript Unobtrusive

    • Default Javascript Files

    • Be able to support both Prototype and JQuery

      • Currently support Prototype only

  • Default Stylesheet

  • Add a helper method to include the dynamic_forms public assets in the template

    • Have stylesheet and JS tags (multiple tags for the different JS lib files)

  • More Field Choices

  • Add a nice JS date/time picker but need a way to support both Prototype and JQuery

  • Be able to set the following field options

    • Select: Size (for multiselect)

    • Check Box: Checked? (whether to check the box by default)

    • Check Box Group: Checked? (whether to check the box by default)

  • Add a new meta field option to check box fields: Terms and Conditions

    • Be able to add a Terms and Conditions checkbox above the checkbox, the answer will be the agreement to the terms (checking the box)

    • The Terms and Conditions will be in a READ ONLY text area field with the checkbox below

    • use the new confirmed? validation to make people agree to the terms

  • Views copy generator

Copyright © 2010 Tom Cocca (Original Work done in 2009 by Chris Powers), released under the MIT license

Something went wrong with that request. Please try again.