doc_contract 0.1.0

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 +191 -0
  4. data/Rakefile +8 -0
  5. data/app/assets/config/doc_contract_manifest.js +3 -0
  6. data/app/assets/javascripts/doc_contract/application.coffee +68 -0
  7. data/app/assets/stylesheets/doc_contract/application.sass +52 -0
  8. data/app/assets/stylesheets/doc_contract/pandoc.css +15 -0
  9. data/app/controllers/concerns/doc_contract/shared_template_and_instance_methods.rb +71 -0
  10. data/app/controllers/doc_contract/application_controller.rb +20 -0
  11. data/app/controllers/doc_contract/contract_instances_controller.rb +56 -0
  12. data/app/controllers/doc_contract/contract_templates_controller.rb +69 -0
  13. data/app/helpers/doc_contract/application_helper.rb +178 -0
  14. data/app/models/concerns/yaml_validator.rb +9 -0
  15. data/app/models/doc_contract/contract_instance.rb +39 -0
  16. data/app/models/doc_contract/contract_template.rb +37 -0
  17. data/app/views/doc_contract/application/_button-destroy-record.html.slim +1 -0
  18. data/app/views/doc_contract/application/_button-edit-record.html.slim +1 -0
  19. data/app/views/doc_contract/application/_button-new-record.html.slim +1 -0
  20. data/app/views/doc_contract/application/_button-preview-html.html.slim +9 -0
  21. data/app/views/doc_contract/application/_button-preview-markdown.html.slim +9 -0
  22. data/app/views/doc_contract/application/_button-preview-pdf.html.slim +1 -0
  23. data/app/views/doc_contract/application/_definition_table_attribute_errors.html.slim +7 -0
  24. data/app/views/doc_contract/application/_messages.html.slim +4 -0
  25. data/app/views/doc_contract/application/_navigation.html.slim +18 -0
  26. data/app/views/doc_contract/application/main.html.slim +6 -0
  27. data/app/views/doc_contract/contract_instances/_form.html.slim +25 -0
  28. data/app/views/doc_contract/contract_instances/edit.html.slim +3 -0
  29. data/app/views/doc_contract/contract_instances/index.html.slim +34 -0
  30. data/app/views/doc_contract/contract_instances/new.html.slim +3 -0
  31. data/app/views/doc_contract/contract_instances/show.html.slim +25 -0
  32. data/app/views/doc_contract/contract_templates/_form.html.slim +34 -0
  33. data/app/views/doc_contract/contract_templates/edit.html.slim +3 -0
  34. data/app/views/doc_contract/contract_templates/index.html.slim +31 -0
  35. data/app/views/doc_contract/contract_templates/new.html.slim +3 -0
  36. data/app/views/doc_contract/contract_templates/show.html.slim +28 -0
  37. data/app/views/doc_contract/kaminari/_first_page.html.slim +2 -0
  38. data/app/views/doc_contract/kaminari/_gap.html.slim +2 -0
  39. data/app/views/doc_contract/kaminari/_last_page.html.slim +2 -0
  40. data/app/views/doc_contract/kaminari/_next_page.html.slim +2 -0
  41. data/app/views/doc_contract/kaminari/_page.html.slim +6 -0
  42. data/app/views/doc_contract/kaminari/_paginator.html.slim +11 -0
  43. data/app/views/doc_contract/kaminari/_prev_page.html.slim +2 -0
  44. data/app/views/layouts/doc_contract/application.html.slim +23 -0
  45. data/config/initializers/human_plural.rb +16 -0
  46. data/config/locales/en.yml +30 -0
  47. data/config/routes.rb +17 -0
  48. data/db/migrate/20220118150923_create_doc_contract_contract_templates.rb +10 -0
  49. data/db/migrate/20220121160034_add_markdown_to_doc_contract_contract_templates.rb +5 -0
  50. data/db/migrate/20220121165825_add_config_yml_to_doc_contract_contract_templates.rb +5 -0
  51. data/db/migrate/20220122151402_create_doc_contract_contract_instances.rb +11 -0
  52. data/db/migrate/20220125183437_add_titlepage_background_to_contract_templates.rb +5 -0
  53. data/lib/doc_contract/engine.rb +24 -0
  54. data/lib/doc_contract/handlebars.rb +99 -0
  55. data/lib/doc_contract/version.rb +3 -0
  56. data/lib/doc_contract.rb +9 -0
  57. data/lib/tasks/doc_contract_tasks.rake +4 -0
  58. metadata +254 -0
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: 5eb3ce664185e17d8c932c25bce2b271961673dbf91cc8bdc468c362f821981a
4
+ data.tar.gz: 9bb96322248d535055d6b5f7ad257388b6d2ef3ce41dd0057600fcc49545e5ee
5
+ SHA512:
6
+ metadata.gz: 1be23ad090e9720299542b7fd16242c1aa2b3c4965535773ac166bd5de9fa65d97a2bd717df25667e6c7f185b50cb1d369b690721bce3e3ef91a4236a56a6441
7
+ data.tar.gz: d61685f08d14746fc7125932de2fe348e1e8403cc30a8705daf4916ee4dedab49c1bb074ba4fef586f4217b494697de91e4d87938b9ed77a0e63d39261b86ba7
data/MIT-LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ Copyright 2022 Benjamin ter Kuile
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.
data/README.md ADDED
@@ -0,0 +1,191 @@
1
+ # DocContract
2
+ DocContract is a `rails` `engine` that is an application wrapper around the https://pandoc.org/
3
+ pdf creation library.
4
+
5
+ The objective is to create and maintain contracts for customers as easy as possible
6
+ and thereby removing redundancy, which gives reason to errors and to create for
7
+ example a maintenance contract for a new year by just setting the `yaml` configuration to:
8
+ ```yaml
9
+ year: 2022
10
+ ```
11
+
12
+ ![Scheme](/spec/dummy/public/DocContract-scheme.png)
13
+
14
+ The structure of contract maintenance is that you create a contract template for a customer,
15
+ for example a maintenance contract by creating a configuration (`yaml`) and a `markdown`
16
+ formatted contract. The markdown is then [handlebars](https://handlebarsjs.com/guide/expressions.html)
17
+ processed to prevent search/replace, summation and redundancy errors.
18
+
19
+ Then the [LaTeX](https://www.latex-project.org/) based [pandoc](https://pandoc.org/) system using the [eisvogel](https://github.com/Wandmalfarbe/pandoc-latex-template)
20
+ template is further used to convert the readable `markdown` to a nicely formatted PDF contract.
21
+
22
+ This `engine` is inpired by the [walle/gimli](https://github.com/walle/gimli)
23
+ gem but was no longer viable due to lack of maintenance and apparently a better renderer
24
+ that is [pandoc](https://pandoc.org/)
25
+
26
+ ## Usage
27
+ Create a contract template consisting of a configuration `yaml` and a `markdown` formatted
28
+ contract. The `yaml` might look like:
29
+
30
+ ```yaml
31
+ titlepage: true
32
+ title: Maintenance contract {{customer}} {{year}}
33
+ subtitle: To the future and beyond!
34
+ date: 2022-01-24
35
+ year: 2021
36
+ full_customer_name: E-corp located in Gotham City
37
+ customer: E-corp
38
+ contractor: Path-E-Tech Management
39
+ full_contractor_name: Path-E-Tech Management L.L.C. located in Gotham City
40
+ production_url: https://contracts.path-e-tech.com
41
+ staging_url: https://contracts-staging.path-e-tech.com
42
+ support_email: support@path-e-tech.com
43
+ author: Dullbert
44
+ header-left: "{{title}}"
45
+ header-right: "{{contractor}}"
46
+ footer-left: "{{customer}} | {{today}}"
47
+ toc: true
48
+ toc-own-page: true
49
+ numbersections: true
50
+ footer-right: '\thepage\ of \pageref{LastPage}'
51
+ geometry: margin=2.5cm
52
+ urlcolor: blue
53
+ header-includes: '\usepackage{lastpage}'
54
+ offer_items:
55
+ - label: Maintenance of the platform infrastructure
56
+ amount: 2_000
57
+ - label: Maintenance of the application API
58
+ amount: 2_000
59
+ - label: Do migrations for the Infrastructure adapter
60
+ amount: 2_500
61
+ ```
62
+
63
+ And a basic markdown:
64
+
65
+ ```markdown
66
+ # Introduction
67
+
68
+ ## Client
69
+
70
+ This maintenance contract is requested by:
71
+ {{full_customer_name}}, hereafter {{customer}},
72
+
73
+ And created by:
74
+ {{full_contractor_name}}, hereafter {{contractor}}.
75
+
76
+
77
+ ## Behest
78
+ contract stuff
79
+
80
+ \newpage
81
+ # Quote breakdown
82
+
83
+ ## Fixed costs
84
+
85
+ Subject | Cost/y
86
+ --- | ---:
87
+ {{#each offer_items}}{{this.label}} | {{euro this.amount}}
88
+ {{/each}}**Total** | **{{euro offer_items_total}}**
89
+
90
+ The total costs for {{year}} for {{to_sentence (map offer_items 'label')}} will thereby be {{to_words offer_items_total}} ({{euro offer_items_total}}). All the amounts include
91
+ a VAT of 21%.
92
+
93
+ ## Variable costs
94
+ And more contract stuff
95
+ ```
96
+
97
+ ## Installation
98
+
99
+ ### Install the system dependencies
100
+ The largest dependency is the [LaTeX](https://www.latex-project.org/) installation:
101
+ ```bash
102
+ $ sudo apt-get install texlive-full
103
+ $ sudo apt-get install pandoc
104
+ ```
105
+ *NOTE*: For trimmed down version of `texlive-full` do trial and error or check docs
106
+
107
+ Or for mac:
108
+ ```bash
109
+ $ brew install mactex
110
+ $ brew install pandoc
111
+ ```
112
+
113
+ And to be able to use the `pandoc-latex-environment`
114
+ also install that one:
115
+ ```bash
116
+ $ pip install pandoc-latex-environment
117
+ ```
118
+
119
+ ### Add the engine to your `rails` app
120
+ Add this line to your application's Gemfile:
121
+
122
+ ```ruby
123
+ gem "doc_contract"
124
+ ```
125
+
126
+ And then execute:
127
+ ```bash
128
+ $ bundle
129
+ $ bundle exec rails db:migrate
130
+ ```
131
+
132
+ ### Mount the engine to your routes
133
+ In your `config/routes.rb` file add:
134
+ ```ruby
135
+ mount DocContract::Engine => '/doc-contract'
136
+ ```
137
+
138
+ ### Add the authorizations
139
+ In your `app/models/ability.rb` file add the authorizations.
140
+ This is a custom operation that you have to adjust to your needs.
141
+ To allow all users full controll to the contracts add:
142
+ ```ruby
143
+ can :manage, DocContract::ContractTemplate
144
+ can :manage, DocContract::ContractInstance
145
+ ```
146
+
147
+ If the `Ability` file does not yet exist, generate it using:
148
+ ```bash
149
+ rails generate cancan:ability
150
+ ```
151
+
152
+ ### Other languages (i18n)
153
+ To use for a lets say Spanish based website add [rails-i18n](https://github.com/svenfuchs/rails-i18n) to your `Gemfile`
154
+
155
+ ```ruby
156
+ gem 'rails-i18n'
157
+ ```
158
+
159
+ And configure your application in `config/application.rb` to handle the languages:
160
+
161
+ ```ruby
162
+ config.i18n.available_locales = %i[en es]
163
+ config.i18n.default_locale = :en
164
+ ```
165
+
166
+ ## Customization
167
+
168
+ ### The main page
169
+ The main page of this engine is a bit of a placeholder page. The contents of this page can be found in [app/views/doc\_contract/application/main.html.slim](app/views/doc\_contract/application/main.html.slim).
170
+ To put your own version of this page create a view having this path in the main application. To only deactivate the README content there
171
+ put the following in your `config/application.rb` file:
172
+
173
+ ```ruby
174
+ config.doc_contract.show_readme_on_main_page = false
175
+ ```
176
+
177
+ ### The link home content
178
+ The default value for `config/application.rb` is:
179
+
180
+ ```ruby
181
+ config.doc_contract.link_home_content = '<i class="arrow left icon"></i> Back'
182
+ ```
183
+ To change for example the icon, see the options at the [fomantic-ui](https://fomantic-ui.com/elements/icon.html) site.
184
+
185
+ ### Screenshot
186
+ ![Edit template scnreenshot](/spec/dummy/public/DocContract-template-edit.png)
187
+ ## Contributing
188
+ Contribution directions go here.
189
+
190
+ ## License
191
+ The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
data/Rakefile ADDED
@@ -0,0 +1,8 @@
1
+ require "bundler/setup"
2
+
3
+ APP_RAKEFILE = File.expand_path("spec/dummy/Rakefile", __dir__)
4
+ load "rails/tasks/engine.rake"
5
+
6
+ load "rails/tasks/statistics.rake"
7
+
8
+ require "bundler/gem_tasks"
@@ -0,0 +1,3 @@
1
+ //= link 'doc_contract/application.css'
2
+ //= link 'doc_contract/application.js'
3
+ //= link 'doc_contract/pandoc.css'
@@ -0,0 +1,68 @@
1
+ #= require jquery
2
+ #= require jquery_ujs
3
+ #= require semantic-ui
4
+ #= require ace-rails-ap
5
+
6
+ latex_template_infos =
7
+ eisvogel: '
8
+ Look at:
9
+ <a href="https://github.com/Wandmalfarbe/pandoc-latex-template" target="_blank">
10
+ https://github.com/Wandmalfarbe/pandoc-latex-template
11
+ </a>'
12
+ $ ->
13
+ $('.ui.dropdown').dropdown() # assume fomantic that has the clearable class option, a lot better than the below custom code
14
+
15
+ $('.preview-markdown').click ->
16
+ markdown = $('#contract_template_markdown').val()
17
+ target = $(@).data('target')
18
+ modal = $('#markdown-preview-modal')
19
+ modal.modal 'show'
20
+ $.post target, {markdown: markdown}, (response) ->
21
+ content = modal.find('.content')
22
+ content.html response.markdown
23
+ false
24
+ $('.preview-html').click ->
25
+ markdown = $('#contract_template_markdown').val()
26
+ target = $(@).data('target')
27
+ modal = $('#html-preview-modal')
28
+ modal.modal 'show'
29
+ $.post target, {markdown: markdown}, (response) ->
30
+ content = modal.find('.content')
31
+ content.html response.html
32
+ false
33
+
34
+ latex_template = $('select#contract_template_latex_template')
35
+ latex_template.change ->
36
+ el = $(@)
37
+ $('.contract_template_latex_template_info').remove()
38
+ if info_html = latex_template_infos[el.val()]
39
+ info = $('<button><i class="info icon"></button>').addClass('contract_template_latex_template_info circular ui olive icon button')
40
+ info.popup
41
+ html: info_html
42
+ hoverable: true
43
+ el.after info
44
+ latex_template.change() if latex_template.length
45
+
46
+ contract_config_yml = $('#contract_template_config_yml,#contract_instance_config_yml')
47
+ if contract_config_yml.length
48
+ config_yml_editor = ace.edit 'contract_config_yml_editor',
49
+ mode: 'ace/mode/yaml'
50
+ theme: 'ace/theme/monokai'
51
+ value: contract_config_yml.val()
52
+ tabSize: 2
53
+ useSoftTabs: true
54
+ config_yml_editor.getSession().on 'change', (something, session) ->
55
+ contract_config_yml.val session.getValue()
56
+ false
57
+ contract_config_yml.hide()
58
+
59
+ contract_markdown = $('#contract_template_markdown')
60
+ if contract_markdown.length
61
+ markdown_editor = ace.edit 'contract_template_markdown_editor',
62
+ mode: 'ace/mode/markdown'
63
+ theme: 'ace/theme/monokai'
64
+ value: contract_markdown.val()
65
+ markdown_editor.getSession().on 'change', (something, session) ->
66
+ contract_markdown.val session.getValue()
67
+ false
68
+ contract_markdown.hide()
@@ -0,0 +1,52 @@
1
+ @import "semantic-ui"
2
+ main
3
+ min-height: calc(100% - 57px - 1rem) // 34px for footer inclusion
4
+ padding-top: 40px
5
+ > .page-title
6
+ padding-top: 12px
7
+ > .container .page-title
8
+ padding-top: 12px
9
+
10
+ #contract_template_markdown_editor, #contract_config_yml_editor
11
+ //position: absolute
12
+ width: 100%
13
+ height: 600px
14
+
15
+ #readme_container
16
+ pre
17
+ max-height: 500px
18
+ overflow: auto
19
+ margin: 10px
20
+ border: 1px solid #777
21
+ .contract-markdown-show-container
22
+ @import "./pandoc"
23
+ .contract-markdown-show-container
24
+ max-height: 600px
25
+ overflow-y: scroll
26
+
27
+ pre.scrolling.content
28
+ margin: 0
29
+
30
+ /* tables */
31
+ table.ui.table
32
+ .actions
33
+ text-align: right
34
+ thead
35
+ tr.search
36
+ th, td
37
+ padding-top: 2px
38
+ padding-bottom: 2px
39
+ .clear-filters-button
40
+ display: none
41
+ &.conditions-present
42
+ th, td
43
+ background-color: #d2e1ec
44
+ .clear-filters-button
45
+ display: inline-block
46
+ .column-filter.actions
47
+ min-width: 85px
48
+ padding-right: 3px
49
+ tbody
50
+ td.actions
51
+ min-width: 112px
52
+ padding-right: 3px
@@ -0,0 +1,15 @@
1
+ body, table {
2
+ font-size: 12px;
3
+ }
4
+
5
+ table {
6
+ border: 0px;
7
+ border-collapse: collapse;
8
+ }
9
+ th {
10
+ text-align: left;
11
+ }
12
+
13
+ h2, h3, h4 {
14
+ padding-top: 1em;
15
+ }
@@ -0,0 +1,71 @@
1
+ module DocContract
2
+ module SharedTemplateAndInstanceMethods
3
+ # POST /doc-contract/contract_templates/:id/processed_markdown?markdown=...
4
+ def processed_markdown
5
+ @record = record_class.find params[:id]
6
+ authorize! :show, @record
7
+ # Allow preview using the markdown parameter. Fallback to actual saved
8
+ # version when param is not given
9
+ @record.markdown = params[:markdown] if params[:markdown].present?
10
+ render json: {markdown: @record.processed_markdown}
11
+ end
12
+
13
+ def processed_html
14
+ @record = record_class.find params[:id]
15
+ authorize! :show, @record
16
+ # Allow preview using the markdown parameter. Fallback to actual saved
17
+ # version when param is not given
18
+ @record.markdown = params[:markdown] if params[:markdown].present?
19
+ render json: {html: @record.processed_html}
20
+ end
21
+
22
+ def get_pdf
23
+ @record = record_class.find params[:id]
24
+ authorize! :show, @record
25
+ # Allow preview using the markdown parameter. Fallback to actual saved
26
+ # version when param is not given
27
+ @record.markdown = params[:markdown] if params[:markdown].present?
28
+ @tempfile_markdown = Tempfile.new(['pandoc-markdown', '.md'])
29
+ config_addittions = {}
30
+ if nbackground = @record.try(:titlepage_background) || @record.contract_template.titlepage_background.presence
31
+ config_addittions['titlepage-background'] = "vendor/assets/doc-contract/titlepage-backgrounds/background#{nbackground}.pdf"
32
+ end
33
+ template_markdown = @record.template_markdown(config_addittions)
34
+ @tempfile_markdown.write template_markdown
35
+ #@tempfile_markdown.rewind
36
+ @tempfile_markdown.close
37
+ @tempfile_pdf = Tempfile.create(['pandoc-pdf-', '.pdf'])
38
+ @tempfile_pdf.close
39
+ command = %( pandoc --template=vendor/assets/doc-contract/pandoc-templates/eisvogel.tex --css=app/assets/stylesheets/doc_contract/pandoc.css #{@tempfile_markdown.path} -o #{@tempfile_pdf.path} )
40
+ command << " --variable top-level-division=chapter" if @record.config['book']
41
+ #command << " --variable titlepage=true" if false # done through YAML config
42
+ command << " --listings" # if some conditions TODO: make this a database boolean
43
+ command << " --filter pandoc-latex-environment" if template_markdown['pandoc-latex-environment:']
44
+
45
+ stdout, stderr, status = nil
46
+ Dir.chdir DocContract::Engine.root do
47
+ stdout, stderr, status = Open3.capture3(command)
48
+ end
49
+ if status.success?
50
+ send_file @tempfile_pdf.path
51
+ else
52
+ redirect_back fallback_location: record_class, flash: {error: stderr}
53
+ end
54
+ ensure
55
+ @tempfile_markdown.unlink rescue nil
56
+ @tempfile_pdf.unlink rescue nil
57
+ end
58
+
59
+ private
60
+
61
+ def record_class
62
+ result = controller_path.classify.safe_constantize
63
+ raise "Cannot determine record_class from controller_path: #{controller_path}" unless result
64
+ result
65
+ end
66
+
67
+ def record_params
68
+ params.require(record_class.name.demodulize.underscore).permit!
69
+ end
70
+ end
71
+ end
@@ -0,0 +1,20 @@
1
+ module DocContract
2
+ class ApplicationController < ApplicationController
3
+ helper_method :query, :readme_html
4
+ def main
5
+ end
6
+
7
+ private
8
+
9
+ def query
10
+ params[:q]
11
+ end
12
+
13
+ def readme_html
14
+ result = DocContract::Engine.root.join('README.md').read
15
+ markdown = Redcarpet::Markdown.new(Redcarpet::Render::HTML, tables: true, fenced_code_blocks: true)
16
+ markdown.render result
17
+ end
18
+
19
+ end
20
+ end
@@ -0,0 +1,56 @@
1
+ module DocContract
2
+ class ContractInstancesController < ApplicationController
3
+ include SharedTemplateAndInstanceMethods
4
+ helper_method :record_class
5
+ respond_to :html
6
+
7
+ def index
8
+ authorize! :index, record_class
9
+ @q = record_class.search query
10
+ @q.sorts = "created_at desc" if @q.sorts.empty?
11
+ @records = @q.result.includes(:contract_template).page(params[:page]).per(100)
12
+ respond_with(@records)
13
+ end
14
+
15
+ def new
16
+ @record = record_class.new
17
+ end
18
+
19
+ def edit
20
+ @record = record_class.find(params[:id])
21
+ authorize! :edit, @record
22
+ end
23
+
24
+ def create
25
+ authorize! :create, record_class
26
+ @record = record_class.new record_params
27
+ if @record.save
28
+ redirect_to @record
29
+ else
30
+ render :new, status: :unprocessable_entity
31
+ end
32
+ end
33
+
34
+ def update
35
+ @record = record_class.find params[:id]
36
+ authorize! :update, @record
37
+ if @record.update record_params
38
+ redirect_to @record
39
+ else
40
+ render :edit, status: :unprocessable_entity
41
+ end
42
+ end
43
+
44
+ def show
45
+ @record = record_class.find params[:id]
46
+ authorize! :show, @record
47
+ end
48
+
49
+ def destroy
50
+ @record = record_class.find params[:id]
51
+ authorize! :destroy, @record
52
+ @record.destroy
53
+ redirect_to record_class
54
+ end
55
+ end
56
+ end
@@ -0,0 +1,69 @@
1
+ module DocContract
2
+ class ContractTemplatesController < ApplicationController
3
+ include SharedTemplateAndInstanceMethods
4
+ helper_method :record_class
5
+ respond_to :html
6
+
7
+ def index
8
+ authorize! :index, record_class
9
+ @q = record_class.search query
10
+ @q.sorts = 'created_at desc' if @q.sorts.empty?
11
+ @records = @q.result.page(params[:page]).per(100)
12
+ respond_with(@records)
13
+ end
14
+
15
+ def new
16
+ @record = record_class.new
17
+ end
18
+
19
+ def edit
20
+ @record = record_class.find(params[:id])
21
+ authorize! :edit, @record
22
+ end
23
+
24
+ def create
25
+ authorize! :create, record_class
26
+ @record = record_class.new record_params
27
+ if @record.save
28
+ redirect_to @record, status: :see_other
29
+ else
30
+ render action: 'new'
31
+ end
32
+ end
33
+
34
+ def update
35
+ @record = record_class.find params[:id]
36
+ authorize! :update, @record
37
+ if @record.update record_params
38
+ redirect_to @record, status: :see_other
39
+ else
40
+ render action: 'edit'
41
+ end
42
+ end
43
+
44
+ def show
45
+ @record = record_class.find params[:id]
46
+ authorize! :show, @record
47
+ end
48
+
49
+ def destroy
50
+ @record = record_class.find params[:id]
51
+ authorize! :destroy, @record
52
+ @record.destroy
53
+ redirect_to record_class, status: :see_other
54
+ end
55
+
56
+ private
57
+
58
+ def record_class
59
+ result = controller_path.classify.safe_constantize
60
+ raise "Cannot determine record_class from controller_path: #{controller_path}" unless result
61
+
62
+ result
63
+ end
64
+
65
+ def record_params
66
+ params.require(record_class.name.demodulize.underscore).permit!
67
+ end
68
+ end
69
+ end