wheelhouse-forms 1.0 → 1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (30) hide show
  1. data/README.md +19 -0
  2. data/app/assets/images/wheelhouse-forms/not-spam-small.png +0 -0
  3. data/app/assets/images/wheelhouse-forms/not-spam.png +0 -0
  4. data/app/assets/images/wheelhouse-forms/spam-small.png +0 -0
  5. data/app/assets/images/wheelhouse-forms/spam.png +0 -0
  6. data/app/assets/images/wheelhouse-forms/submissions.png +0 -0
  7. data/app/assets/javascripts/wheelhouse-forms/{admin.js → designer.js} +0 -0
  8. data/app/assets/javascripts/wheelhouse-forms/jquery.options.js +10 -3
  9. data/app/assets/javascripts/wheelhouse-forms/submissions.js +56 -0
  10. data/app/assets/stylesheets/wheelhouse-forms/admin.css.sass +15 -3
  11. data/app/controllers/forms/forms_controller.rb +13 -0
  12. data/app/controllers/forms/submissions_controller.rb +6 -1
  13. data/app/handlers/forms/form_handler.rb +1 -1
  14. data/app/helpers/forms/mailer_helper.rb +1 -1
  15. data/app/helpers/forms/spam_helper.rb +21 -0
  16. data/app/helpers/forms/submissions_helper.rb +1 -1
  17. data/app/models/forms/form.rb +7 -6
  18. data/app/models/forms/submission.rb +11 -24
  19. data/app/models/forms/submission/parameters.rb +24 -0
  20. data/app/views/forms/forms/{_submissions.haml → _submissions.html.haml} +6 -9
  21. data/app/views/forms/forms/designer.haml +1 -1
  22. data/app/views/forms/forms/edit.html.haml +1 -1
  23. data/app/views/forms/forms/form.haml +13 -2
  24. data/app/views/forms/forms/spam.html.haml +5 -0
  25. data/app/views/forms/submissions/form.haml +10 -0
  26. data/config/routes.rb +4 -0
  27. data/lib/forms/akismet_filter.rb +36 -0
  28. data/lib/forms/null_filter.rb +9 -0
  29. data/lib/wheelhouse-forms.rb +15 -1
  30. metadata +15 -5
data/README.md CHANGED
@@ -23,6 +23,7 @@ Other features include:
23
23
 
24
24
  - server-side and HTML5 form validation
25
25
  - CSV export of submissions
26
+ - optional spam filtering (via Akismet)
26
27
 
27
28
 
28
29
  Installation & Usage
@@ -37,3 +38,21 @@ Then run `bundle install`.
37
38
  **2. Create a new form from the New Page dropdown.**
38
39
 
39
40
  **3. To customize, copy the `form.html.haml` template from `app/templates` to your theme templates folder.**
41
+
42
+
43
+ ### Spam Filtering with Akismet
44
+
45
+ Spam filtering support requires an Akismet API key. Sign up for one at <https://akismet.com/signup/>.
46
+
47
+ **1. Add `rakismet` to your Gemfile:**
48
+
49
+ gem "rakismet"
50
+
51
+ Then run `bundle install`.
52
+
53
+ **2. Add your Akismet API key and web site URL to `config/application.rb`.**
54
+
55
+ config.rakismet.key = "1234abcd1234"
56
+ config.rakismet.url = "http://www.example.com/"
57
+
58
+ **3. Restart your Rails server. The forms plugin will automatically use Rakismet if it is configured.**
@@ -1,10 +1,18 @@
1
1
  $.fn.options = function() {
2
+ function addField(li) {
3
+ var next = li.clone().find('div').remove().end().insertAfter(li);
4
+ next.find('input').val('').width('auto').autoGrowInput().focus();
5
+ }
6
+
2
7
  return $(this).each(function() {
3
8
  $(this).delegate("li input", "blur", function() {
4
9
  var li = $(this).parent();
10
+ var value = $(this).val();
5
11
 
6
- if ($(this).val() == "" && !li.is(":last-child")) {
12
+ if (value == "" && !li.is(":last-child")) {
7
13
  li.remove();
14
+ } else if (value != "" && li.is(":last-child")) {
15
+ addField(li);
8
16
  }
9
17
  });
10
18
 
@@ -14,8 +22,7 @@ $.fn.options = function() {
14
22
  e.preventDefault();
15
23
 
16
24
  var li = $(this).parent();
17
- var next = li.clone().find('div').remove().end().insertAfter(li);
18
- next.find('input').val('').width('auto').autoGrowInput().focus();
25
+ addField(li);
19
26
  }
20
27
  });
21
28
 
@@ -0,0 +1,56 @@
1
+ $(function() {
2
+
3
+ function updateSubmission(url, spam, callback) {
4
+ $.ajax({
5
+ type: 'PUT',
6
+ url: url,
7
+ data: { spam: spam },
8
+ dataType: 'json',
9
+ success: function() {
10
+ Wheelhouse.Flash.message("Submission updated.");
11
+ callback();
12
+ }
13
+ });
14
+
15
+ Wheelhouse.Flash.loading("Updating submission.");
16
+ }
17
+
18
+ function clickHandler(spam) {
19
+ return function() {
20
+ var url = $(this).attr('href');
21
+ var row = $(this).closest('tr');
22
+
23
+ updateSubmission(url, spam, function() {
24
+ row.remove();
25
+ });
26
+
27
+ return false;
28
+ }
29
+ }
30
+
31
+ $('#submissions').on('click', 'a.mark-spam', clickHandler(true));
32
+ $('#submissions').on('click', 'a.not-spam', clickHandler(false));
33
+
34
+ $('button.mark-spam').click(function() {
35
+ var url = $(this).closest('form').attr('action');
36
+
37
+ updateSubmission(url, true, function() {
38
+ $('button.mark-spam').hide();
39
+ $('button.not-spam').show();
40
+ });
41
+
42
+ return false;
43
+ });
44
+
45
+ $('button.not-spam').click(function() {
46
+ var url = $(this).closest('form').attr('action');
47
+
48
+ updateSubmission(url, false, function() {
49
+ $('button.not-spam').hide();
50
+ $('button.mark-spam').show();
51
+ });
52
+
53
+ return false;
54
+ });
55
+
56
+ });
@@ -225,9 +225,21 @@
225
225
  &.custom-field a
226
226
  background-image: image-url("wheelhouse-forms/custom.png")
227
227
 
228
- .sidebar li a.export-csv
229
- background-image: image-url("wheelhouse-forms/csv.png")
230
- padding-left: 40px
228
+ .sidebar
229
+ a.spam-submissions
230
+ background-image: image-url("wheelhouse-forms/spam-small.png")
231
+ padding-left: 40px
232
+
233
+ a.latest-submissions
234
+ background-image: image-url("wheelhouse-forms/submissions.png")
235
+ padding-left: 40px
236
+
237
+ a.export-csv
238
+ background-image: image-url("wheelhouse-forms/csv.png")
239
+ padding-left: 40px
240
+
241
+ button.mark-spam, button.not-spam
242
+ width: 222px
231
243
 
232
244
  .field
233
245
  li
@@ -2,6 +2,19 @@ class Forms::FormsController < Wheelhouse::ResourceController
2
2
  self.resource_class = Forms::Form
3
3
  manage_site_breadcrumb
4
4
 
5
+ helper Forms::SpamHelper
6
+
7
+ def show
8
+ super do
9
+ @submissions = resource.submissions.not_spam.paginate(:page => params[:p])
10
+ end
11
+ end
12
+
13
+ def spam
14
+ @form = resource
15
+ @submissions = resource.submissions.spam.paginate(:page => params[:p])
16
+ end
17
+
5
18
  def version
6
19
  resource.revert_to(params[:version].to_i)
7
20
  render :edit
@@ -7,7 +7,7 @@ class Forms::SubmissionsController < Wheelhouse::ResourceController
7
7
  manage_site_breadcrumb
8
8
  breadcrumb { [parent.label, parent] }
9
9
 
10
- actions :show, :destroy
10
+ actions :show, :destroy, :update
11
11
 
12
12
  respond_to :csv
13
13
 
@@ -16,4 +16,9 @@ class Forms::SubmissionsController < Wheelhouse::ResourceController
16
16
  format.csv { render :text => Forms::CsvExporter.new(parent).to_csv }
17
17
  end
18
18
  end
19
+
20
+ def update
21
+ resource.spam!(params[:spam])
22
+ respond_with(resource)
23
+ end
19
24
  end
@@ -7,7 +7,7 @@ class Forms::FormHandler < Wheelhouse::ResourceHandler
7
7
  end
8
8
 
9
9
  post do
10
- @form.submit(params[:submission])
10
+ @form.submit(params[:submission], request)
11
11
  end
12
12
 
13
13
  private
@@ -7,7 +7,7 @@ module Forms::MailerHelper
7
7
  render_custom_field(field)
8
8
  when Forms::Fields::Checkboxes
9
9
  render_array(field, @submission.value_for(field) || ["None given"])
10
- when Forms::Fields::ContentField
10
+ when Forms::Fields::ContentField, Forms::Fields::SubmitButton
11
11
  # Nothing
12
12
  else
13
13
  render_text_field(field, @submission.value_for(field))
@@ -0,0 +1,21 @@
1
+ module Forms::SpamHelper
2
+ def spam_icon
3
+ icon("wheelhouse-forms/spam.png", :alt => "Mark as spam", :title => "Click to mark submission as spam")
4
+ end
5
+
6
+ def not_spam_icon
7
+ icon("wheelhouse-forms/not-spam.png", :alt => "Mark as not spam", :title => "Click to mark submission as not spam")
8
+ end
9
+
10
+ def toggle_spam_link(submission, path)
11
+ if submission.spam?
12
+ link_to not_spam_icon, path, :class => "not-spam"
13
+ else
14
+ link_to spam_icon, path, :class => "mark-spam"
15
+ end
16
+ end
17
+
18
+ def listing_spam?
19
+ controller.action_name == "spam"
20
+ end
21
+ end
@@ -15,7 +15,7 @@ module Forms::SubmissionsHelper
15
15
  value = @submission.value_for(field)
16
16
  form.text_area field.label, :value => value || "", :readonly => true, :rows => 5
17
17
  end
18
- when Forms::Fields::ContentField
18
+ when Forms::Fields::ContentField, Forms::Fields::SubmitButton
19
19
  # Nothing
20
20
  else
21
21
  labelled_field(field) do
@@ -18,7 +18,7 @@ class Forms::Form < Wheelhouse::Resource
18
18
 
19
19
  icon "wheelhouse-forms/form.png"
20
20
 
21
- attr_accessor :view_context, :current_submission
21
+ attr_accessor :view_context, :current_submission, :success
22
22
 
23
23
  def to_s
24
24
  render(view_context)
@@ -28,15 +28,16 @@ class Forms::Form < Wheelhouse::Resource
28
28
  Forms::FormRenderer.new(self, current_submission, template).render
29
29
  end
30
30
 
31
- def submit(params)
32
- submission = submissions.build(:params => params)
31
+ def submit(params, request)
32
+ submission = submissions.build(:params => params, :ip_address => request.remote_ip)
33
+ Forms::Plugin.config.wheelhouse.forms.spam_filter.check(submission)
33
34
 
34
35
  if submission.save
35
- deliver(submission)
36
- @success = true
36
+ deliver(submission) unless submission.spam?
37
+ self.success = true
37
38
  else
38
39
  self.current_submission = submission
39
- @success = false
40
+ self.success = false
40
41
  end
41
42
  end
42
43
 
@@ -1,36 +1,18 @@
1
1
  class Forms::Submission < Wheelhouse::BasicResource
2
- class Parameters < Hash
3
- def to_mongo
4
- result = []
5
- each do |key, value|
6
- result << [key, value]
7
- end
8
- result
9
- end
10
-
11
- def self.cast(params)
12
- case params
13
- when Hash
14
- self[params]
15
- when Array
16
- params.each_with_object({}) { |v, hash| hash[v[0]] = v[1] }
17
- end
18
- end
19
-
20
- def self.from_mongo(params)
21
- cast(params)
22
- end
23
- end
24
-
25
2
  include Wheelhouse::Resource::AdminPath
26
3
 
27
4
  property :params, Parameters
5
+ property :ip_address, String
6
+ property :spam, Boolean, :default => false, :protected => true
28
7
  timestamps!
29
8
 
30
9
  belongs_to :form, :class => "Forms::Form"
31
10
 
32
11
  default_scope order(:created_at.desc)
33
12
 
13
+ scope :spam, where(:spam => true)
14
+ scope :not_spam, where(:spam.ne => true)
15
+
34
16
  validate do
35
17
  form.fields.flatten.each do |field|
36
18
  if field.required? && value_for(field).blank?
@@ -39,8 +21,13 @@ class Forms::Submission < Wheelhouse::BasicResource
39
21
  end
40
22
  end
41
23
 
24
+ def spam!(is_spam)
25
+ Forms::Plugin.config.wheelhouse.forms.spam_filter.train(self, is_spam)
26
+ update_attribute(:spam, is_spam)
27
+ end
28
+
42
29
  def value_for(field)
43
- params[field.label]
30
+ params[field.label] if field.respond_to?(:label)
44
31
  end
45
32
 
46
33
  def admin_path
@@ -0,0 +1,24 @@
1
+ class Forms::Submission
2
+ class Parameters < Hash
3
+ def to_mongo
4
+ result = []
5
+ each do |key, value|
6
+ result << [key, value]
7
+ end
8
+ result
9
+ end
10
+
11
+ def self.cast(params)
12
+ case params
13
+ when Hash
14
+ self[params]
15
+ when Array
16
+ params.each_with_object({}) { |v, hash| hash[v[0]] = v[1] }
17
+ end
18
+ end
19
+
20
+ def self.from_mongo(params)
21
+ cast(params)
22
+ end
23
+ end
24
+ end
@@ -1,19 +1,16 @@
1
- - @submissions = resource.submissions.paginate(:page => params[:p])
2
-
3
- %h2 Latest Submissions
4
-
5
- = table_for Forms::Submission do |table|
1
+ = table_for Forms::Submission, :id => "submissions" do |table|
6
2
  - table.rows(@submissions) do |row, submission|
7
3
  - row.resource = [@form, submission]
8
-
4
+
9
5
  - if resource.first_content_field
10
6
  = row.column(resource.first_content_field.label) { submission.value_for(resource.first_content_field) }
11
-
7
+
12
8
  = row.column(:submitted_at) { submission.created_at.in_time_zone.to_s(:long) }
13
-
9
+
14
10
  = row.controls do |c|
11
+ = toggle_spam_link(submission, form_submission_path(@form, submission))
15
12
  = c.delete
16
-
13
+
17
14
  - table.empty do
18
15
  No submissions have been posted.
19
16
 
@@ -53,4 +53,4 @@
53
53
  = stylesheet_link_tag "wheelhouse-forms/admin"
54
54
 
55
55
  - content_for(:javascript) do
56
- = javascript_include_tag "wheelhouse-forms/admin"
56
+ = javascript_include_tag "wheelhouse-forms/designer"
@@ -1,5 +1,5 @@
1
1
  - title "Editing Form"
2
- - breadcrumb @form.label, form_path(@form)
2
+ - breadcrumb @form.label, @form
3
3
  - breadcrumb "Editing Form"
4
4
 
5
5
  = render_form "designer"
@@ -1,4 +1,6 @@
1
- - tab :submissions => "submissions"
1
+ - tab :submissions do
2
+ %h2 #{listing_spam? ? "Spam" : "Latest"} Submissions
3
+ = render "submissions"
2
4
 
3
5
  - sidebar do
4
6
  .buttons
@@ -7,7 +9,12 @@
7
9
  %hr
8
10
 
9
11
  %ul
10
- %li= link_to "Export results as CSV", form_submissions_path(@form, :format => :csv), :class => "export-csv"
12
+ - if listing_spam?
13
+ %li= link_to "View Latest Submissions", form_path(@form), :class => "latest-submissions"
14
+ - else
15
+ %li= link_to "View Spam Submissions", spam_form_path(@form), :class => "spam-submissions"
16
+
17
+ %li= link_to "Export Results as CSV", form_submissions_path(@form, :format => :csv), :class => "export-csv"
11
18
 
12
19
  %hr
13
20
 
@@ -20,3 +27,7 @@
20
27
 
21
28
  - content_for(:head) do
22
29
  = stylesheet_link_tag "wheelhouse-forms/admin"
30
+
31
+ - content_for(:javascript) do
32
+ = javascript_include_tag "wheelhouse-forms/submissions"
33
+
@@ -0,0 +1,5 @@
1
+ - title @form.label
2
+ - breadcrumb @form.label, @form
3
+ - breadcrumb "Spam Submissions"
4
+
5
+ = render_form
@@ -7,10 +7,20 @@
7
7
  - sidebar do
8
8
  .buttons
9
9
  = button "Back to list", :url => @form
10
+
11
+ = button "Mark submission as spam", :class => "secondary dark mark-spam", :icon => "wheelhouse-forms/spam-small.png", :style => @submission.spam? ? "display: none" : ""
12
+ = button "Submission is not spam", :class => "secondary not-spam", :icon => "wheelhouse-forms/not-spam-small.png", :style => !@submission.spam? ? "display: none" : ""
10
13
 
11
14
  %hr
12
15
 
13
16
  %p.owner Submitted: #{timestamp(@submission.created_at)}
17
+ - if @submission.ip_address?
18
+ %p.owner IP Address: #{@submission.ip_address}
19
+
20
+ %hr
14
21
 
15
22
  - content_for(:head) do
16
23
  = stylesheet_link_tag "wheelhouse-forms/admin"
24
+
25
+ - content_for(:javascript) do
26
+ = javascript_include_tag "wheelhouse-forms/submissions"
data/config/routes.rb CHANGED
@@ -2,6 +2,10 @@ Forms::Plugin.routes.draw do
2
2
  extend Wheelhouse::RouteExtensions
3
3
 
4
4
  resources :forms do
5
+ member do
6
+ get :spam
7
+ end
8
+
5
9
  resources :submissions
6
10
  end
7
11
  end
@@ -0,0 +1,36 @@
1
+ module Forms
2
+ class AkismetFilter
3
+ include Rakismet::Model
4
+
5
+ def self.check(submission)
6
+ filter = new(submission)
7
+ submission.spam = true if filter.spam?
8
+ end
9
+
10
+ def self.train(submission, is_spam)
11
+ filter = new(submission)
12
+ is_spam ? filter.spam! : filter.ham!
13
+ end
14
+
15
+ def initialize(submission)
16
+ @submission = submission
17
+ end
18
+
19
+ def user_ip
20
+ @submission.ip_address
21
+ end
22
+
23
+ def content
24
+ responses.join("\n")
25
+ end
26
+
27
+ private
28
+ def responses
29
+ fields.map { |field| @submission.value_for(field) }
30
+ end
31
+
32
+ def fields
33
+ @submission.form.fields.flatten
34
+ end
35
+ end
36
+ end
@@ -0,0 +1,9 @@
1
+ module Forms
2
+ class NullFilter
3
+ def self.check(submission)
4
+ end
5
+
6
+ def self.train(submission, is_spam)
7
+ end
8
+ end
9
+ end
@@ -1,12 +1,26 @@
1
1
  require "wheelhouse"
2
2
 
3
+ begin
4
+ require "rakismet"
5
+ rescue LoadError
6
+ # Rakismet not available
7
+ end
8
+
3
9
  module Forms
10
+ extend ActiveSupport::Autoload
11
+
12
+ autoload :AkismetFilter
13
+ autoload :NullFilter
14
+
4
15
  class Plugin < Wheelhouse::Plugin
5
16
  config.wheelhouse.forms = ActiveSupport::OrderedOptions.new
6
17
 
7
18
  # Disable custom fields by default
8
19
  config.wheelhouse.forms.custom_fields = false
9
20
 
21
+ # Set default spam filter
22
+ config.wheelhouse.forms.spam_filter = defined?(Rakismet) ? AkismetFilter : NullFilter
23
+
10
24
  isolate_namespace Forms
11
25
 
12
26
  resource { Form }
@@ -16,7 +30,7 @@ module Forms
16
30
  end
17
31
 
18
32
  initializer :precompile_assets do |app|
19
- app.config.assets.precompile += %w(wheelhouse-forms/admin.*)
33
+ app.config.assets.precompile += %w(wheelhouse-forms/admin.* wheelhouse-forms/designer.js wheelhouse-forms/submissions.js)
20
34
  end
21
35
 
22
36
  def self.load_yaml(file)
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: wheelhouse-forms
3
3
  version: !ruby/object:Gem::Version
4
- version: '1.0'
4
+ version: '1.1'
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2012-12-04 00:00:00.000000000 Z
12
+ date: 2013-06-12 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: wheelhouse
@@ -42,21 +42,28 @@ files:
42
42
  - app/assets/images/wheelhouse-forms/drag.png
43
43
  - app/assets/images/wheelhouse-forms/field-set.png
44
44
  - app/assets/images/wheelhouse-forms/form.png
45
+ - app/assets/images/wheelhouse-forms/not-spam-small.png
46
+ - app/assets/images/wheelhouse-forms/not-spam.png
45
47
  - app/assets/images/wheelhouse-forms/radio-buttons.png
46
48
  - app/assets/images/wheelhouse-forms/select.png
49
+ - app/assets/images/wheelhouse-forms/spam-small.png
50
+ - app/assets/images/wheelhouse-forms/spam.png
47
51
  - app/assets/images/wheelhouse-forms/states.png
52
+ - app/assets/images/wheelhouse-forms/submissions.png
48
53
  - app/assets/images/wheelhouse-forms/submit-button.png
49
54
  - app/assets/images/wheelhouse-forms/text-area.png
50
55
  - app/assets/images/wheelhouse-forms/text-field.png
51
- - app/assets/javascripts/wheelhouse-forms/admin.js
56
+ - app/assets/javascripts/wheelhouse-forms/designer.js
52
57
  - app/assets/javascripts/wheelhouse-forms/jquery.autogrow.js
53
58
  - app/assets/javascripts/wheelhouse-forms/jquery.options.js
59
+ - app/assets/javascripts/wheelhouse-forms/submissions.js
54
60
  - app/assets/stylesheets/wheelhouse-forms/admin.css.sass
55
61
  - app/controllers/forms/forms_controller.rb
56
62
  - app/controllers/forms/submissions_controller.rb
57
63
  - app/handlers/forms/form_handler.rb
58
64
  - app/helpers/forms/forms_helper.rb
59
65
  - app/helpers/forms/mailer_helper.rb
66
+ - app/helpers/forms/spam_helper.rb
60
67
  - app/helpers/forms/submissions_helper.rb
61
68
  - app/mailers/forms/mailer.rb
62
69
  - app/models/forms/field_collection.rb
@@ -75,6 +82,7 @@ files:
75
82
  - app/models/forms/fields/text_area.rb
76
83
  - app/models/forms/fields/text_field.rb
77
84
  - app/models/forms/form.rb
85
+ - app/models/forms/submission/parameters.rb
78
86
  - app/models/forms/submission.rb
79
87
  - app/renderers/forms/checkbox_renderer.rb
80
88
  - app/renderers/forms/checkboxes_renderer.rb
@@ -102,7 +110,7 @@ files:
102
110
  - app/views/forms/forms/_radio_buttons.haml
103
111
  - app/views/forms/forms/_select_field.haml
104
112
  - app/views/forms/forms/_states_dropdown.haml
105
- - app/views/forms/forms/_submissions.haml
113
+ - app/views/forms/forms/_submissions.html.haml
106
114
  - app/views/forms/forms/_submit_button.haml
107
115
  - app/views/forms/forms/_text_area.haml
108
116
  - app/views/forms/forms/_text_field.haml
@@ -111,13 +119,16 @@ files:
111
119
  - app/views/forms/forms/form.haml
112
120
  - app/views/forms/forms/new.html.haml
113
121
  - app/views/forms/forms/show.html.haml
122
+ - app/views/forms/forms/spam.html.haml
114
123
  - app/views/forms/submissions/form.haml
115
124
  - app/views/forms/submissions/show.html.haml
116
125
  - config/countries.yml
117
126
  - config/locales/en.yml
118
127
  - config/routes.rb
119
128
  - config/states.yml
129
+ - lib/forms/akismet_filter.rb
120
130
  - lib/forms/csv_exporter.rb
131
+ - lib/forms/null_filter.rb
121
132
  - lib/wheelhouse-forms.rb
122
133
  - README.md
123
134
  - LICENSE
@@ -146,4 +157,3 @@ signing_key:
146
157
  specification_version: 3
147
158
  summary: Wheelhouse CMS Forms Plugin
148
159
  test_files: []
149
- has_rdoc: