doc_contract 0.1.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 (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