incredible 0.0.1.pre

Sign up to get free protection for your applications and to get access to all the features.
Files changed (58) hide show
  1. checksums.yaml +7 -0
  2. data/MIT-LICENSE +20 -0
  3. data/README.md +153 -0
  4. data/Rakefile +24 -0
  5. data/config/routes.rb +2 -0
  6. data/lib/incredible.rb +12 -0
  7. data/lib/incredible/engine.rb +9 -0
  8. data/lib/incredible/form.rb +26 -0
  9. data/lib/incredible/loader.rb +24 -0
  10. data/lib/incredible/step.rb +15 -0
  11. data/lib/incredible/version.rb +3 -0
  12. data/lib/incredible/wizard.rb +42 -0
  13. data/spec/controllers/forms_controller_spec.rb +33 -0
  14. data/spec/dummy/Rakefile +6 -0
  15. data/spec/dummy/app/controllers/application_controller.rb +3 -0
  16. data/spec/dummy/app/controllers/forms_controller.rb +21 -0
  17. data/spec/dummy/app/models/application_record.rb +3 -0
  18. data/spec/dummy/app/models/stub_model.rb +9 -0
  19. data/spec/dummy/app/views/forms/bar.html.erb +0 -0
  20. data/spec/dummy/app/views/forms/foo.html.erb +0 -0
  21. data/spec/dummy/app/views/layouts/application.html.erb +14 -0
  22. data/spec/dummy/app/views/layouts/mailer.html.erb +13 -0
  23. data/spec/dummy/app/views/layouts/mailer.text.erb +1 -0
  24. data/spec/dummy/bin/bundle +3 -0
  25. data/spec/dummy/bin/rails +4 -0
  26. data/spec/dummy/bin/rake +4 -0
  27. data/spec/dummy/bin/setup +37 -0
  28. data/spec/dummy/bin/update +29 -0
  29. data/spec/dummy/bin/yarn +11 -0
  30. data/spec/dummy/config.ru +5 -0
  31. data/spec/dummy/config/application.rb +24 -0
  32. data/spec/dummy/config/boot.rb +5 -0
  33. data/spec/dummy/config/cable.yml +10 -0
  34. data/spec/dummy/config/environment.rb +5 -0
  35. data/spec/dummy/config/environments/development.rb +54 -0
  36. data/spec/dummy/config/environments/production.rb +91 -0
  37. data/spec/dummy/config/environments/test.rb +42 -0
  38. data/spec/dummy/config/forms/bad-yaml.yml +7 -0
  39. data/spec/dummy/config/forms/form.yml +28 -0
  40. data/spec/dummy/config/initializers/application_controller_renderer.rb +8 -0
  41. data/spec/dummy/config/initializers/assets.rb +14 -0
  42. data/spec/dummy/config/initializers/backtrace_silencers.rb +7 -0
  43. data/spec/dummy/config/initializers/cookies_serializer.rb +5 -0
  44. data/spec/dummy/config/initializers/filter_parameter_logging.rb +4 -0
  45. data/spec/dummy/config/initializers/inflections.rb +16 -0
  46. data/spec/dummy/config/initializers/mime_types.rb +4 -0
  47. data/spec/dummy/config/initializers/wrap_parameters.rb +14 -0
  48. data/spec/dummy/config/locales/en.yml +33 -0
  49. data/spec/dummy/config/puma.rb +56 -0
  50. data/spec/dummy/config/routes.rb +3 -0
  51. data/spec/dummy/config/secrets.yml +32 -0
  52. data/spec/dummy/config/spring.rb +6 -0
  53. data/spec/dummy/package.json +5 -0
  54. data/spec/form_spec.rb +36 -0
  55. data/spec/loader_spec.rb +36 -0
  56. data/spec/spec_helper.rb +21 -0
  57. data/spec/step_spec.rb +61 -0
  58. metadata +271 -0
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 136f74de4f0fb1f2ce9b7c034536e309a3cec7ae
4
+ data.tar.gz: 8144f9c6ace33e5a6b2442b8f7704ee0dbfb4a78
5
+ SHA512:
6
+ metadata.gz: 856c927d05693349103b26fc1754e85415d58ba4f52e858d93f2c244a1c609e73fd4ac5a8e27af9ea0ac2a8f1587552db81f6fbde061bc2a566c115b592f58e2
7
+ data.tar.gz: 948ab2aeb444d19082b18cfc432a30e4b76e217d1d2961802d45431ab489f20cb524eb34770f7b18dff20ab63fb284b0bd404f832cacce4eab1adec302abcd17
@@ -0,0 +1,20 @@
1
+ Copyright 2018 pezholio
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.
@@ -0,0 +1,153 @@
1
+ [![Build Status](http://img.shields.io/circleci/project/github/wearefuturegov/incredible.svg?style=flat-square)](https://circleci.com/gh/wearefuturegov/incredible)
2
+ [![Coverage Status](http://img.shields.io/coveralls/wearefuturegov/incredible.svg?style=flat-square)](https://coveralls.io/r/wearefuturegov/incredible)
3
+ [![Code Climate](http://img.shields.io/codeclimate/github/wearefuturegov/incredible.svg?style=flat-square)](https://codeclimate.com/github/wearefuturegov/incredible)
4
+ [![Gem Version](http://img.shields.io/gem/v/Incredible.svg?style=flat-square)](https://rubygems.org/gems/Incredible)
5
+ [![License](http://img.shields.io/:license-mit-blue.svg?style=flat-square)](http://wearefuturegov.mit-license.org)
6
+
7
+ # Incredible
8
+
9
+ Build multi-page forms like a [General](https://www.youtube.com/watch?v=mL2Bgj-za5k).
10
+
11
+ Incredible uses the power of [Wicked](https://github.com/schneems/wicked) to allow you to build multi-page, ActiveRecord model-based, Rails forms using a simple YAML-based format.
12
+
13
+ ## Installation
14
+ Add this line to your Rails application's Gemfile:
15
+
16
+ ```ruby
17
+ gem 'incredible'
18
+ ```
19
+
20
+ And then execute:
21
+ ```bash
22
+ $ bundle
23
+ ```
24
+
25
+ Or install it yourself as:
26
+ ```bash
27
+ $ gem install incredible
28
+ ```
29
+
30
+ ## Usage
31
+
32
+ *NOTE:* Incredible is still a work in progress and at an early stage, so these docs are subject to change (and definitely need improving!)
33
+
34
+ First, create a YAML file in `config/forms` - for example `config/forms/my_awesome_form.yml`.
35
+
36
+ Here's an example:
37
+
38
+ ```YAML
39
+ form:
40
+ name: 'Test form'
41
+ steps:
42
+ step1:
43
+ template: foo
44
+ rules:
45
+ name:
46
+ 'Mike': :step3
47
+ questions:
48
+ - name: :name
49
+ title: Your full name
50
+ widget: :input
51
+ - name: :postcode
52
+ title: Your postcode
53
+ widget: :input
54
+ step2:
55
+ template: bar
56
+ questions:
57
+ - name: :email
58
+ title: Email
59
+ widget: :email
60
+ - name: :phone_number
61
+ title: Phone Number
62
+ widget: :tel
63
+ step3:
64
+ template: :baz
65
+ ```
66
+
67
+ Each step *must* have a template, and questions as a minimum.
68
+
69
+ Next create a model:
70
+
71
+ ```bash
72
+ rails g model form name:string postcode:string email:string postcode:string
73
+ rails db:migrate
74
+ ```
75
+
76
+ Note how all the columns refer to a question in your YAML file.
77
+
78
+ Then create a controller:
79
+
80
+ ```bash
81
+ rails g controller forms/build
82
+ ````
83
+
84
+ Add Routes into config/routes.rb:
85
+
86
+ ```Ruby
87
+ resources :forms do
88
+ resources :build, controller: 'forms/build'
89
+ end
90
+ ```
91
+
92
+ Next include `Incredible::Wizard` in your controller
93
+
94
+ ```Ruby
95
+ class Forms::BuildController < ApplicationController
96
+ include Incredible::Wizard
97
+
98
+ form 'my_awesome_form'
99
+ end
100
+ ```
101
+
102
+ (Where `my_awesome_form` is the name of the YAML file you created)
103
+
104
+ Next add `show`, `create` and `new` methods to your controller
105
+
106
+ ```Ruby
107
+ class Forms::BuildController < ApplicationController
108
+ include Incredible::Wizard
109
+
110
+ form 'my_awesome_form'
111
+
112
+ def show
113
+ render_wizard nil, template: "forms/#{template}"
114
+ end
115
+
116
+ def update
117
+ @form = Form.find(params[:id])
118
+ render_wizard @form
119
+ end
120
+
121
+ def new
122
+ redirect_to wizard_path(steps.first, foster_check_id: foster_check.id)
123
+ end
124
+
125
+ end
126
+ ```
127
+
128
+ Next, you'll need to have a controller that creates your model and redirects to the form. Run this:
129
+
130
+ ```bash
131
+ rails g controller forms
132
+ ````
133
+
134
+ Then edit your controller:
135
+
136
+ ```ruby
137
+ class FormsController < ApplicationController
138
+
139
+ def create
140
+ form = Form.create
141
+ redirect_to new_form_build_path(form_id: form.id)
142
+ end
143
+
144
+ end
145
+ ```
146
+
147
+ More docs coming soon!
148
+
149
+ ## Contributing
150
+ See [CONTRIBUTING.md](https://github.com/wearefuturegov/incredible/blob/master/CONTRIBUTING.md)
151
+
152
+ ## License
153
+ The gem is available as open source under the terms of the [MIT License](http://opensource.org/licenses/MIT).
@@ -0,0 +1,24 @@
1
+ #!/usr/bin/env rake
2
+ begin
3
+ require 'bundler/setup'
4
+ rescue LoadError
5
+ puts 'You must `gem install bundler` and `bundle install` to run rake tasks'
6
+ end
7
+
8
+ APP_RAKEFILE = File.expand_path('../spec/dummy/Rakefile', __FILE__)
9
+ load 'rails/tasks/engine.rake'
10
+
11
+ Bundler::GemHelper.install_tasks
12
+
13
+ Dir[File.join(File.dirname(__FILE__), 'tasks/**/*.rake')].each { |f| load f }
14
+
15
+ require 'rspec/core'
16
+ require 'rspec/core/rake_task'
17
+ require 'coveralls/rake/task'
18
+
19
+ Coveralls::RakeTask.new
20
+ RSpec::Core::RakeTask.new(:spec)
21
+
22
+ desc 'Run all specs in spec directory (excluding plugin specs)'
23
+
24
+ task default: [:spec, 'coveralls:push']
@@ -0,0 +1,2 @@
1
+ Incredible::Engine.routes.draw do
2
+ end
@@ -0,0 +1,12 @@
1
+ require 'wicked'
2
+
3
+ require 'incredible/engine'
4
+ require 'incredible/loader'
5
+ require 'incredible/form'
6
+ require 'incredible/step'
7
+
8
+ require 'incredible/wizard'
9
+
10
+ module Incredible
11
+ # Your code goes here...
12
+ end
@@ -0,0 +1,9 @@
1
+ module Incredible
2
+ class Engine < ::Rails::Engine
3
+ isolate_namespace Incredible
4
+
5
+ config.generators do |g|
6
+ g.test_framework :rspec, fixture: false
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,26 @@
1
+ module Incredible
2
+ class Form
3
+ def initialize(name)
4
+ @data = Incredible::Loader.load(name)
5
+ end
6
+
7
+ def step_names
8
+ raw_steps.keys
9
+ end
10
+
11
+ def steps
12
+ @steps ||= raw_steps.map { |k, v| { k => Step.new(v) } }.reduce(:merge)
13
+ end
14
+
15
+ def find_step(step_name)
16
+ steps[step_name]
17
+ end
18
+
19
+ private
20
+
21
+ def raw_steps
22
+ @data['form']['steps']
23
+ end
24
+
25
+ end
26
+ end
@@ -0,0 +1,24 @@
1
+ module Incredible
2
+ class Loader
3
+ class FormNotFound < StandardError; end
4
+ class BadYAML < StandardError; end
5
+
6
+ def self.load(name)
7
+ filename = "#{name}.yml"
8
+ new(filename).data
9
+ end
10
+
11
+ def initialize(filename)
12
+ @path = Rails.root.join('config', 'forms', filename)
13
+ end
14
+
15
+ def data
16
+ YAML.safe_load File.open(@path), [Symbol]
17
+ rescue Errno::ENOENT => e
18
+ raise FormNotFound, e.message
19
+ rescue Psych::SyntaxError => e
20
+ raise BadYAML, e.message
21
+ end
22
+
23
+ end
24
+ end
@@ -0,0 +1,15 @@
1
+ module Incredible
2
+ class Step
3
+
4
+ def initialize(data)
5
+ @data = data.symbolize_keys
6
+
7
+ %I[questions rules template].each do |k|
8
+ self.class.send :define_method, k.to_sym do
9
+ @data[k]
10
+ end
11
+ end
12
+ end
13
+
14
+ end
15
+ end
@@ -0,0 +1,3 @@
1
+ module Incredible
2
+ VERSION = '0.0.1.pre'.freeze
3
+ end
@@ -0,0 +1,42 @@
1
+ module Incredible
2
+ module Wizard
3
+ extend ActiveSupport::Concern
4
+ include Wicked::Wizard
5
+
6
+ attr_accessor :wizard_form, :step_data, :template, :rules, :questions
7
+
8
+ included do
9
+ before_action :load_step, only: %i[show update]
10
+ before_action :process_rules, only: :update
11
+ before_action :load_step_data, only: %i[show update]
12
+ end
13
+
14
+ def load_step
15
+ self.step_data = wizard_form.find_step(params[:id])
16
+ end
17
+
18
+ def load_step_data
19
+ self.template = step_data.template
20
+ self.questions = step_data.questions
21
+ end
22
+
23
+ def process_rules
24
+ self.rules = step_data.rules || {}
25
+ next_step = permitted_params.to_h.map do |k, v|
26
+ rules.dig(k, v)
27
+ end&.first
28
+ jump_to next_step if next_step
29
+ end
30
+
31
+ module ClassMethods
32
+ def form(form_name)
33
+ wizard_form = Incredible::Form.new(form_name)
34
+ steps(*wizard_form.step_names)
35
+ prepend_before_action do
36
+ self.wizard_form = wizard_form
37
+ end
38
+ end
39
+ end
40
+
41
+ end
42
+ end
@@ -0,0 +1,33 @@
1
+ require 'spec_helper'
2
+
3
+ describe FormsController, type: :controller do
4
+
5
+ context 'rendering templates' do
6
+ it 'renders step 1 template' do
7
+ expect(
8
+ (get :show, params: { id: :step1 })
9
+ ).to render_template('forms/foo')
10
+ end
11
+
12
+ it 'renders step 2 template' do
13
+ expect(
14
+ (get :show, params: { id: :step2 })
15
+ ).to render_template('forms/bar')
16
+ end
17
+ end
18
+
19
+ context 'rules' do
20
+ it 'follows a rule' do
21
+ expect(
22
+ (put :update, params: { id: :step1, model: { name: 'Mike' } })
23
+ ).to redirect_to('http://test.host/forms/step3')
24
+ end
25
+
26
+ it 'goes to the next step by default' do
27
+ expect(
28
+ (put :update, params: { id: :step1, model: { name: 'Ian' } })
29
+ ).to redirect_to('http://test.host/forms/step2')
30
+ end
31
+ end
32
+
33
+ end
@@ -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_relative 'config/application'
5
+
6
+ Rails.application.load_tasks
@@ -0,0 +1,3 @@
1
+ class ApplicationController < ActionController::Base
2
+ protect_from_forgery with: :exception
3
+ end
@@ -0,0 +1,21 @@
1
+ class FormsController < ActionController::Base
2
+ include Incredible::Wizard
3
+
4
+ form 'form'
5
+
6
+ def show
7
+ render_wizard nil, template: "forms/#{template}"
8
+ end
9
+
10
+ def update
11
+ @model = StubModel.new(permitted_params)
12
+ render_wizard @model
13
+ end
14
+
15
+ private
16
+
17
+ def permitted_params
18
+ params.require(:model).permit(:name, :postcode, :email, :phone_number)
19
+ end
20
+
21
+ end
@@ -0,0 +1,3 @@
1
+ class ApplicationRecord < ActiveRecord::Base
2
+ self.abstract_class = true
3
+ end
@@ -0,0 +1,9 @@
1
+ class StubModel
2
+ include ActiveModel::Model
3
+
4
+ attr_accessor :name, :postcode, :email, :phone_number
5
+
6
+ def save
7
+ true
8
+ end
9
+ end
@@ -0,0 +1,14 @@
1
+ <!DOCTYPE html>
2
+ <html>
3
+ <head>
4
+ <title>Dummy</title>
5
+ <%= csrf_meta_tags %>
6
+
7
+ <%= stylesheet_link_tag 'application', media: 'all' %>
8
+ <%= javascript_include_tag 'application' %>
9
+ </head>
10
+
11
+ <body>
12
+ <%= yield %>
13
+ </body>
14
+ </html>