formbuilder-rb 0.0.4 → 0.2.0

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 (127) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +11 -0
  3. data/.rspec +2 -0
  4. data/.ruby-gemset +1 -0
  5. data/.ruby-version +1 -0
  6. data/Gemfile +14 -0
  7. data/Gemfile.lock +219 -0
  8. data/Guardfile +17 -0
  9. data/{MIT-LICENSE → LICENSE.md} +1 -1
  10. data/README.md +86 -0
  11. data/app/controllers/formbuilder/concerns/forms_controller.rb +59 -0
  12. data/app/models/formbuilder/entry_attachment.rb +2 -8
  13. data/app/models/formbuilder/form.rb +53 -0
  14. data/app/models/formbuilder/response_field.rb +23 -10
  15. data/app/models/formbuilder/response_field_address.rb +12 -1
  16. data/app/models/formbuilder/response_field_checkboxes.rb +38 -0
  17. data/app/models/formbuilder/response_field_date.rb +7 -1
  18. data/app/models/formbuilder/response_field_dropdown.rb +2 -1
  19. data/app/models/formbuilder/response_field_email.rb +14 -2
  20. data/app/models/formbuilder/response_field_file.rb +75 -20
  21. data/app/models/formbuilder/response_field_number.rb +9 -2
  22. data/app/models/formbuilder/response_field_page_break.rb +13 -0
  23. data/app/models/formbuilder/response_field_paragraph.rb +19 -3
  24. data/app/models/formbuilder/response_field_price.rb +10 -6
  25. data/app/models/formbuilder/response_field_radio.rb +11 -2
  26. data/app/models/formbuilder/response_field_section_break.rb +12 -2
  27. data/app/models/formbuilder/response_field_table.rb +222 -0
  28. data/app/models/formbuilder/response_field_text.rb +9 -2
  29. data/app/models/formbuilder/response_field_time.rb +8 -1
  30. data/app/models/formbuilder/response_field_website.rb +26 -2
  31. data/app/uploaders/formbuilder/entry_attachment_uploader.rb +11 -1
  32. data/bin/rails +8 -0
  33. data/circle.yml +9 -0
  34. data/config/spring.rb +1 -0
  35. data/db/migrate/20130924185815_create_formbuilder_entry_attachments.rb +1 -0
  36. data/formbuilder-rb.gemspec +41 -0
  37. data/formbuilder-rb.sublime-project +20 -0
  38. data/lib/formbuilder.rb +8 -3
  39. data/lib/formbuilder/entry.rb +102 -159
  40. data/lib/formbuilder/entry_validator.rb +13 -6
  41. data/lib/formbuilder/version.rb +1 -1
  42. data/lib/formbuilder/views/entry_dl.rb +56 -0
  43. data/lib/formbuilder/views/form.rb +81 -0
  44. data/lib/formbuilder/views/form_field.rb +45 -0
  45. data/spec/controllers/formbuilder/forms_controller_spec.rb +40 -0
  46. data/spec/dummy/.ruby-gemset +1 -0
  47. data/spec/dummy/.ruby-version +1 -0
  48. data/spec/dummy/README.rdoc +28 -0
  49. data/spec/dummy/Rakefile +6 -0
  50. data/spec/dummy/app/assets/images/.keep +0 -0
  51. data/spec/dummy/app/assets/javascripts/application.js +13 -0
  52. data/spec/dummy/app/assets/stylesheets/application.css +13 -0
  53. data/spec/dummy/app/controllers/application_controller.rb +5 -0
  54. data/spec/dummy/app/controllers/forms_controller.rb +3 -0
  55. data/spec/dummy/app/controllers/test_controller.rb +57 -0
  56. data/spec/dummy/app/helpers/application_helper.rb +2 -0
  57. data/spec/dummy/app/mailers/.keep +0 -0
  58. data/spec/dummy/app/models/concerns/.keep +0 -0
  59. data/spec/dummy/app/models/entry.rb +7 -0
  60. data/spec/dummy/app/models/entry_with_alternate_column_name.rb +11 -0
  61. data/spec/dummy/app/views/layouts/application.html.erb +14 -0
  62. data/spec/dummy/app/views/test/_form.rb +2 -0
  63. data/spec/dummy/app/views/test/render_entry.html.erb +1 -0
  64. data/spec/dummy/app/views/test/show_form.html.erb +1 -0
  65. data/spec/dummy/bin/bundle +3 -0
  66. data/spec/dummy/bin/rails +4 -0
  67. data/spec/dummy/bin/rake +4 -0
  68. data/spec/dummy/config.ru +4 -0
  69. data/spec/dummy/config/application.rb +25 -0
  70. data/spec/dummy/config/boot.rb +5 -0
  71. data/spec/dummy/config/database.yml.ci +15 -0
  72. data/spec/dummy/config/database.yml.example +15 -0
  73. data/spec/dummy/config/environment.rb +5 -0
  74. data/spec/dummy/config/environments/development.rb +29 -0
  75. data/spec/dummy/config/environments/production.rb +80 -0
  76. data/spec/dummy/config/environments/test.rb +52 -0
  77. data/spec/dummy/config/initializers/backtrace_silencers.rb +7 -0
  78. data/spec/dummy/config/initializers/filter_parameter_logging.rb +4 -0
  79. data/spec/dummy/config/initializers/inflections.rb +16 -0
  80. data/spec/dummy/config/initializers/mime_types.rb +5 -0
  81. data/spec/dummy/config/initializers/secret_token.rb +12 -0
  82. data/spec/dummy/config/initializers/session_store.rb +3 -0
  83. data/spec/dummy/config/initializers/wrap_parameters.rb +14 -0
  84. data/spec/dummy/config/locales/en.yml +23 -0
  85. data/spec/dummy/config/routes.rb +12 -0
  86. data/spec/dummy/db/migrate/20130924182939_create_entries.rb +13 -0
  87. data/spec/dummy/db/migrate/20130924192151_create_formbuilder_forms.formbuilder.rb +11 -0
  88. data/spec/dummy/db/migrate/20130924192152_create_formbuilder_response_fields.formbuilder.rb +17 -0
  89. data/spec/dummy/db/migrate/20130926205845_create_formbuilder_entry_attachments.formbuilder.rb +12 -0
  90. data/spec/dummy/db/migrate/20140128000000_create_entry_with_alternate_column_names.rb +13 -0
  91. data/spec/dummy/db/schema.rb +64 -0
  92. data/spec/dummy/lib/assets/.keep +0 -0
  93. data/spec/dummy/log/.keep +0 -0
  94. data/spec/dummy/public/404.html +58 -0
  95. data/spec/dummy/public/422.html +58 -0
  96. data/spec/dummy/public/500.html +57 -0
  97. data/spec/dummy/public/favicon.ico +0 -0
  98. data/spec/dummy/test/fixtures/entries.yml +9 -0
  99. data/spec/dummy/test/fixtures/response_fields.yml +19 -0
  100. data/spec/dummy/test/models/entry_test.rb +7 -0
  101. data/spec/dummy/test/models/response_field_test.rb +7 -0
  102. data/spec/factories/formbuilder_forms.rb +45 -0
  103. data/spec/features/form_renderer_spec.rb +30 -0
  104. data/spec/features/submitting_an_entry_spec.rb +79 -0
  105. data/spec/fixtures/test_files/text.txt +1 -0
  106. data/spec/fixtures/test_files/text2.txt +1 -0
  107. data/spec/lib/formbuilder/entry_spec.rb +199 -0
  108. data/spec/lib/formbuilder/entry_validator_spec.rb +215 -0
  109. data/spec/lib/formbuilder/entry_with_alternate_column_name_spec.rb +37 -0
  110. data/spec/lib/formbuilder/views/entry_dl_spec.rb +38 -0
  111. data/spec/models/formbuilder/entry_attachment_spec.rb +17 -0
  112. data/spec/models/formbuilder/form_spec.rb +100 -0
  113. data/spec/models/formbuilder/response_field_address_spec.rb +25 -0
  114. data/spec/models/formbuilder/response_field_checkboxes_spec.rb +57 -0
  115. data/spec/models/formbuilder/response_field_file_spec.rb +80 -0
  116. data/spec/models/formbuilder/response_field_paragraph_spec.rb +22 -0
  117. data/spec/models/formbuilder/response_field_radio_spec.rb +30 -0
  118. data/spec/models/formbuilder/response_field_spec.rb +21 -0
  119. data/spec/models/formbuilder/response_field_table_spec.rb +124 -0
  120. data/spec/spec_helper.rb +25 -0
  121. data/spec/support/database_cleaner.rb +21 -0
  122. data/spec/support/submitting_an_entry_spec_helper.rb +151 -0
  123. metadata +286 -44
  124. data/app/controllers/formbuilder/forms_controller.rb +0 -53
  125. data/lib/formbuilder/entry_renderer.rb +0 -47
  126. data/lib/formbuilder/entry_table_renderer.rb +0 -58
  127. data/lib/formbuilder/form_renderer.rb +0 -102
@@ -1,3 +1,3 @@
1
1
  module Formbuilder
2
- VERSION = "0.0.4"
2
+ VERSION = "0.2.0"
3
3
  end
@@ -0,0 +1,56 @@
1
+ module Formbuilder
2
+ module Views
3
+ class EntryDl < Erector::Widget
4
+
5
+ needs :entry,
6
+ :form,
7
+ show_blind: false,
8
+ show_admin_only: false
9
+
10
+ def content
11
+ dl(class: 'entry-dl') {
12
+ response_fields.each do |rf|
13
+ value = @entry.response_value(rf)
14
+
15
+ dt {
16
+ text rf.label
17
+ blind_label if rf.blind?
18
+ admin_only_label if rf.admin_only?
19
+ }
20
+
21
+ dd {
22
+ if (x = rf.render_entry(value, entry: @entry))
23
+ rawtext x
24
+ else
25
+ no_response
26
+ end
27
+ }
28
+ end
29
+ }
30
+ end
31
+
32
+ private
33
+ def blind_label
34
+ text ' '
35
+ span.label 'Blind'
36
+ end
37
+
38
+ def admin_only_label
39
+ text ' '
40
+ span.label 'Admin only'
41
+ end
42
+
43
+ def no_response
44
+ span 'No response', class: 'no-response'
45
+ end
46
+
47
+ def response_fields
48
+ return_array = @form.input_fields
49
+ return_array.reject! { |rf| rf.blind? } unless @show_blind
50
+ return_array.reject! { |rf| rf.admin_only? } unless @show_admin_only
51
+ return_array
52
+ end
53
+
54
+ end
55
+ end
56
+ end
@@ -0,0 +1,81 @@
1
+ module Formbuilder
2
+ module Views
3
+ class Form < Erector::Widget
4
+
5
+ needs :form,
6
+ :entry,
7
+ current_page: 1,
8
+ action: '',
9
+ method: 'POST'
10
+
11
+ def content
12
+ page_list if @form.multi_page?
13
+
14
+ form_tag @action, method: @method, class: 'formbuilder-form', multipart: true do
15
+ input type: 'hidden', name: 'page', value: @current_page
16
+ render_fields
17
+ actions
18
+ end
19
+ end
20
+
21
+ def page_list
22
+ ul.unstyled.inline.formbuilder_form_pages_list {
23
+ (1..@form.num_pages).each do |x|
24
+ if x == @current_page
25
+ li { span x }
26
+ else
27
+ li.active { a x, href: url_for(params.merge(page: x)) }
28
+ end
29
+ end
30
+ }
31
+ end
32
+
33
+ def actions
34
+ opts = {}
35
+
36
+ unless first_page?
37
+ opts[:go_back_text] = "Back to page #{previous_page}"
38
+ opts[:go_back_html] = { href: url_for(params.merge(page: previous_page)) }
39
+ end
40
+
41
+ if last_page?
42
+ opts[:continue_text] = 'Preview and Submit'
43
+ else
44
+ opts[:continue_text] = 'Next page'
45
+ end
46
+
47
+ div(class: 'form-actions') {
48
+ if opts[:go_back_text]
49
+ a.button opts[:go_back_text], opts[:go_back_html]
50
+ end
51
+
52
+ button.button.primary opts[:continue_text]
53
+ }
54
+ end
55
+
56
+ private
57
+ def render_fields
58
+ @form.response_fields_for_page(@current_page).each do |response_field|
59
+ widget Formbuilder::Views::FormField.new(response_field: response_field, entry: @entry)
60
+ end
61
+ end
62
+
63
+ def first_page?
64
+ @current_page == 1
65
+ end
66
+
67
+ def previous_page
68
+ @current_page - 1
69
+ end
70
+
71
+ def next_page
72
+ @current_page + 1
73
+ end
74
+
75
+ def last_page?
76
+ @current_page == @form.num_pages
77
+ end
78
+
79
+ end
80
+ end
81
+ end
@@ -0,0 +1,45 @@
1
+ module Formbuilder
2
+ module Views
3
+ class FormField < Erector::Widget
4
+
5
+ needs :response_field, :entry
6
+
7
+ def content
8
+ @value = @entry.try(:response_value, @response_field)
9
+
10
+ div(class: "fb-field-wrapper response-field-#{@response_field.field_type} #{@entry.try(:error_for, @response_field) && 'error'}") {
11
+ render_label if @response_field.input_field
12
+ rawtext @response_field.render_input(@value, entry: @entry)
13
+ div.clear
14
+ render_error if @response_field.input_field && @entry.error_for(@response_field)
15
+ render_description if @response_field.input_field && @response_field[:field_options]["description"].present?
16
+ }
17
+ end
18
+
19
+ private
20
+ def render_label
21
+ label(for: "response_fields_#{@response_field.id}") {
22
+ text @response_field[:label]
23
+
24
+ if @response_field.required?
25
+ text ' '
26
+ abbr('*', title: 'required')
27
+ end
28
+ }
29
+ end
30
+
31
+ def render_error
32
+ span(class: "help-block validation-message-wrapper") {
33
+ text @entry.error_for(@response_field)
34
+ }
35
+ end
36
+
37
+ def render_description
38
+ span(class: 'help-block') {
39
+ text simple_format(@response_field[:field_options]["description"])
40
+ }
41
+ end
42
+
43
+ end
44
+ end
45
+ end
@@ -0,0 +1,40 @@
1
+ require 'spec_helper'
2
+
3
+ describe Formbuilder::FormsController do
4
+
5
+ TEST_JSON = '[{"label":"Please enter your clearance number","field_type":"text","required":true,"field_options":{},"cid":"c6"},{"label":"Security personnel #82?","field_type":"radio","required":true,"field_options":{"options":[{"label":"Yes","checked":false},{"label":"No","checked":false}],"include_other_option":true},"cid":"c10"},{"label":"Medical history","field_type":"file","required":true,"field_options":{},"cid":"c14"}]'
6
+
7
+ let(:form) { FactoryGirl.create(:form) }
8
+
9
+ describe '#update' do
10
+ it 'should add new fields' do
11
+ form.response_fields.count.should == 0
12
+ put :update, id: form.id, fields: JSON.parse(TEST_JSON)
13
+ form.response_fields.count.should == 3
14
+ JSON::parse(response.body)[0]['label'].should == 'Please enter your clearance number'
15
+ JSON::parse(response.body)[0]['field_type'].should == 'text'
16
+ JSON::parse(response.body)[0]['cid'].should == 'c6'
17
+ form.response_fields.first.class.should == Formbuilder::ResponseFieldText
18
+ end
19
+
20
+ it 'should remove existing fields' do
21
+ form = FactoryGirl.create(:kitchen_sink_form)
22
+ form.response_fields.count.should == 15
23
+ put :update, id: form.id, fields: JSON.parse(TEST_JSON)
24
+ form.reload.response_fields.count.should == 3
25
+ end
26
+
27
+ it 'should preserve existing fields' do
28
+ form = FactoryGirl.create(:kitchen_sink_form)
29
+ form.response_fields.count.should == 15
30
+ json_payload = JSON.parse(TEST_JSON)
31
+ json_payload[0]['id'] = form.response_fields.first.id
32
+ put :update, id: form.id, fields: json_payload
33
+ form.reload.response_fields.count.should == 3
34
+ JSON::parse(response.body)[0]['id'].should == json_payload[0]['id']
35
+ JSON::parse(response.body)[1]['cid'].should == 'c10'
36
+ JSON::parse(response.body)[2]['cid'].should == 'c14'
37
+ end
38
+
39
+ end
40
+ end
@@ -0,0 +1 @@
1
+ formbuilder-rb
@@ -0,0 +1 @@
1
+ 2.0.0
@@ -0,0 +1,28 @@
1
+ == README
2
+
3
+ This README would normally document whatever steps are necessary to get the
4
+ application up and running.
5
+
6
+ Things you may want to cover:
7
+
8
+ * Ruby version
9
+
10
+ * System dependencies
11
+
12
+ * Configuration
13
+
14
+ * Database creation
15
+
16
+ * Database initialization
17
+
18
+ * How to run the test suite
19
+
20
+ * Services (job queues, cache servers, search engines, etc.)
21
+
22
+ * Deployment instructions
23
+
24
+ * ...
25
+
26
+
27
+ Please feel free to use a different markup language if you do not plan to run
28
+ <tt>rake doc:app</tt>.
@@ -0,0 +1,6 @@
1
+ # Add your own tasks in files placed in lib/tasks ending in .rake,
2
+ # for example lib/tasks/capistrano.rake, and they will automatically be available to Rake.
3
+
4
+ require File.expand_path('../config/application', __FILE__)
5
+
6
+ Dummy::Application.load_tasks
File without changes
@@ -0,0 +1,13 @@
1
+ // This is a manifest file that'll be compiled into application.js, which will include all the files
2
+ // listed below.
3
+ //
4
+ // Any JavaScript/Coffee file within this directory, lib/assets/javascripts, vendor/assets/javascripts,
5
+ // or vendor/assets/javascripts of plugins, if any, can be referenced here using a relative path.
6
+ //
7
+ // It's not advisable to add code directly here, but if you do, it'll appear at the bottom of the
8
+ // compiled file.
9
+ //
10
+ // Read Sprockets README (https://github.com/sstephenson/sprockets#sprockets-directives) for details
11
+ // about supported directives.
12
+ //
13
+ //= require_tree .
@@ -0,0 +1,13 @@
1
+ /*
2
+ * This is a manifest file that'll be compiled into application.css, which will include all the files
3
+ * listed below.
4
+ *
5
+ * Any CSS and SCSS file within this directory, lib/assets/stylesheets, vendor/assets/stylesheets,
6
+ * or vendor/assets/stylesheets of plugins, if any, can be referenced here using a relative path.
7
+ *
8
+ * You're free to add application-wide styles to this file and they'll appear at the top of the
9
+ * compiled file, but it's generally better to create a new file per style scope.
10
+ *
11
+ *= require_self
12
+ *= require_tree .
13
+ */
@@ -0,0 +1,5 @@
1
+ class ApplicationController < ActionController::Base
2
+ # Prevent CSRF attacks by raising an exception.
3
+ # For APIs, you may want to use :null_session instead.
4
+ protect_from_forgery with: :exception
5
+ end
@@ -0,0 +1,3 @@
1
+ class FormsController < ApplicationController
2
+ include Formbuilder::Concerns::FormsController
3
+ end
@@ -0,0 +1,57 @@
1
+ class TestController < ApplicationController
2
+
3
+ before_filter :load_form_and_entry
4
+
5
+ def show_form
6
+ @current_page = [params[:page].to_i, 1].max
7
+
8
+ if flash[:show_errors]
9
+ @entry.valid_page?(@current_page)
10
+ end
11
+ end
12
+
13
+ def post_form
14
+ @current_page = [params[:page].to_i, 1].max
15
+
16
+ @entry.form.show_blind = true
17
+
18
+ @entry.save_responses(
19
+ params[:response_fields],
20
+ @entry.form.response_fields_for_page(@current_page),
21
+ partial_update: true
22
+ )
23
+
24
+ success_path = @entry.form.num_pages == @current_page ?
25
+ render_entry_path(@entry.form, @entry) :
26
+ test_form_path(@entry.form, @entry, page: @current_page + 1)
27
+
28
+ if @current_page != @entry.form.num_pages
29
+ @entry.only_validate_page = @current_page
30
+ end
31
+
32
+ if @entry.valid?
33
+ @entry.save(validate: false)
34
+ redirect_to success_path
35
+ else
36
+ @entry.save(validate: false)
37
+
38
+ failure_path = if @entry.errors_on_page?(@current_page)
39
+ test_form_path(@entry.form, @entry, page: @current_page)
40
+ else
41
+ test_form_path(@entry.form, @entry, page: @entry.first_page_with_errors)
42
+ end
43
+
44
+ redirect_to failure_path, flash: { show_errors: true }
45
+ end
46
+ end
47
+
48
+ def render_entry
49
+ end
50
+
51
+ private
52
+ def load_form_and_entry
53
+ @form = Formbuilder::Form.find(params[:form_id])
54
+ @entry = Entry.find(params[:entry_id])
55
+ end
56
+
57
+ end
@@ -0,0 +1,2 @@
1
+ module ApplicationHelper
2
+ end
File without changes
File without changes
@@ -0,0 +1,7 @@
1
+ class Entry < ActiveRecord::Base
2
+
3
+ include Formbuilder::Entry
4
+
5
+ belongs_to :form, class_name: 'Formbuilder::Form'
6
+
7
+ end
@@ -0,0 +1,11 @@
1
+ class EntryWithAlternateColumnName < ActiveRecord::Base
2
+
3
+ include Formbuilder::Entry
4
+
5
+ belongs_to :form, class_name: 'Formbuilder::Form'
6
+
7
+ after_initialize do
8
+ @responses_column = 'responses_alt'
9
+ end
10
+
11
+ end
@@ -0,0 +1,14 @@
1
+ <!DOCTYPE html>
2
+ <html>
3
+ <head>
4
+ <title>Dummy</title>
5
+ <%= stylesheet_link_tag "application", media: "all", "data-turbolinks-track" => true %>
6
+ <%= javascript_include_tag "application", "data-turbolinks-track" => true %>
7
+ <%= csrf_meta_tags %>
8
+ </head>
9
+ <body>
10
+
11
+ <%= yield %>
12
+
13
+ </body>
14
+ </html>
@@ -0,0 +1,2 @@
1
+ class Views::Test::Form < Formbuilder::Views::Form
2
+ end
@@ -0,0 +1 @@
1
+ <%= link_to 'Back to form', test_form_path(@form, @entry) %>
@@ -0,0 +1 @@
1
+ <%= render partial: 'form' %>
@@ -0,0 +1,3 @@
1
+ #!/usr/bin/env ruby
2
+ ENV['BUNDLE_GEMFILE'] ||= File.expand_path('../../Gemfile', __FILE__)
3
+ load Gem.bin_path('bundler', 'bundle')