templet_rails 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 (108) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +8 -0
  3. data/.travis.yml +5 -0
  4. data/Gemfile +6 -0
  5. data/LICENSE.txt +21 -0
  6. data/README.md +1059 -0
  7. data/Rakefile +10 -0
  8. data/bin/console +14 -0
  9. data/bin/setup +8 -0
  10. data/lib/generators/templet/controller/USAGE +13 -0
  11. data/lib/generators/templet/controller/controller_generator.rb +106 -0
  12. data/lib/generators/templet/core/USAGE +23 -0
  13. data/lib/generators/templet/core/core_generator.rb +128 -0
  14. data/lib/generators/templet/core_rspec/USAGE +16 -0
  15. data/lib/generators/templet/core_rspec/core_rspec_generator.rb +65 -0
  16. data/lib/generators/templet/destroy/USAGE +19 -0
  17. data/lib/generators/templet/destroy/destroy_generator.rb +126 -0
  18. data/lib/generators/templet/routes/USAGE +14 -0
  19. data/lib/generators/templet/routes/routes_generator.rb +64 -0
  20. data/lib/generators/templet/rspec/USAGE +10 -0
  21. data/lib/generators/templet/rspec/rspec_generator.rb +124 -0
  22. data/lib/generators/templet/scaffold/USAGE +22 -0
  23. data/lib/generators/templet/scaffold/scaffold_generator.rb +75 -0
  24. data/lib/generators/templet/shared/actions_option.rb +24 -0
  25. data/lib/generators/templet/shared/add_routes_option.rb +19 -0
  26. data/lib/generators/templet/shared/child_option.rb +23 -0
  27. data/lib/generators/templet/shared/comment_tests_option.rb +19 -0
  28. data/lib/generators/templet/shared/core_helpers.rb +48 -0
  29. data/lib/generators/templet/shared/grand_parent_option.rb +20 -0
  30. data/lib/generators/templet/shared/model_fields.rb +55 -0
  31. data/lib/generators/templet/shared/model_option.rb +25 -0
  32. data/lib/generators/templet/shared/parent_option.rb +20 -0
  33. data/lib/generators/templet/templates/controller.rb.erb +108 -0
  34. data/lib/generators/templet/templates/core/app/base_viewer.rb +7 -0
  35. data/lib/generators/templet/templates/core/app/link_sets/navbar.rb +12 -0
  36. data/lib/generators/templet/templates/core/app/panel/flash_messages.rb +33 -0
  37. data/lib/generators/templet/templates/core/app/panel/layout_base.rb +40 -0
  38. data/lib/generators/templet/templates/core/app/panel/layout_header.rb +22 -0
  39. data/lib/generators/templet/templates/core/app/panel/layout_header_sidebar.rb +18 -0
  40. data/lib/generators/templet/templates/core/app/panel/nav.rb +55 -0
  41. data/lib/generators/templet/templates/core/app/panel/nav_args_option.rb +30 -0
  42. data/lib/generators/templet/templates/core/app/panel/options_config.rb +19 -0
  43. data/lib/generators/templet/templates/core/app/panel/show_parents_option.rb +22 -0
  44. data/lib/generators/templet/templates/core/app/panel/sidebar_links_option.rb +24 -0
  45. data/lib/generators/templet/templates/core/controllers/.keep +0 -0
  46. data/lib/generators/templet/templates/core/controllers/json_rendering_helpers.rb +12 -0
  47. data/lib/generators/templet/templates/core/controllers/rendering_helpers.rb +53 -0
  48. data/lib/generators/templet/templates/core/controllers/viewer_call_string.rb +144 -0
  49. data/lib/generators/templet/templates/core/controllers/viewer_call_string_class.rb +65 -0
  50. data/lib/generators/templet/templates/core/controllers/viewer_responders.rb +121 -0
  51. data/lib/generators/templet/templates/core/helpers/app.rb +4 -0
  52. data/lib/generators/templet/templates/core/helpers/templet_helper.rb +10 -0
  53. data/lib/generators/templet/templates/core/spec/support/apis/api_helper.rb +13 -0
  54. data/lib/generators/templet/templates/core/spec/support/apis/shared_examples_a_json_controller.rb +196 -0
  55. data/lib/generators/templet/templates/core/spec/support/core/model_parent_helpers.rb +36 -0
  56. data/lib/generators/templet/templates/core/spec/support/core/rest_link_procs_assignments.rb +43 -0
  57. data/lib/generators/templet/templates/core/spec/support/core/rest_link_procs_helpers.rb +15 -0
  58. data/lib/generators/templet/templates/core/spec/support/viewer/partial_test_helpers.rb +32 -0
  59. data/lib/generators/templet/templates/core/spec/support/viewer/shared_examples_a_viewer.rb +105 -0
  60. data/lib/generators/templet/templates/core/spec/templet/forms/bs_form_errors_spec.rb +18 -0
  61. data/lib/generators/templet/templates/core/spec/templet/forms/bs_form_spec.rb +58 -0
  62. data/lib/generators/templet/templates/core/spec/templet/layout/html_rails_spec.rb +64 -0
  63. data/lib/generators/templet/templates/core/spec/templet/links/bs_link_set_collection_spec.rb +79 -0
  64. data/lib/generators/templet/templates/core/spec/templet/links/rest_link_procs_params_spec.rb +68 -0
  65. data/lib/generators/templet/templates/core/spec/templet/links/rest_link_procs_parents_spec.rb +78 -0
  66. data/lib/generators/templet/templates/core/spec/templet/links/rest_link_procs_spec.rb +140 -0
  67. data/lib/generators/templet/templates/core/templet/constants.rb +54 -0
  68. data/lib/generators/templet/templates/core/templet/forms/bs_form.rb +73 -0
  69. data/lib/generators/templet/templates/core/templet/forms/bs_form_errors.rb +38 -0
  70. data/lib/generators/templet/templates/core/templet/forms/bs_form_field.rb +114 -0
  71. data/lib/generators/templet/templates/core/templet/forms/bs_form_group.rb +115 -0
  72. data/lib/generators/templet/templates/core/templet/layouts/html_rails.rb +36 -0
  73. data/lib/generators/templet/templates/core/templet/links.rb +28 -0
  74. data/lib/generators/templet/templates/core/templet/links/bs_btn_class.rb +61 -0
  75. data/lib/generators/templet/templates/core/templet/links/bs_link_set_base.rb +168 -0
  76. data/lib/generators/templet/templates/core/templet/links/bs_link_set_collection.rb +21 -0
  77. data/lib/generators/templet/templates/core/templet/links/bs_link_set_navigation.rb +62 -0
  78. data/lib/generators/templet/templates/core/templet/links/rest_link_procs.rb +163 -0
  79. data/lib/generators/templet/templates/core/templet/links/rest_link_procs_parent.rb +39 -0
  80. data/lib/generators/templet/templates/core/templet/links/rest_link_procs_sets.rb +30 -0
  81. data/lib/generators/templet/templates/core/templet/links/rest_link_text.rb +102 -0
  82. data/lib/generators/templet/templates/core/templet/links/rest_path.rb +90 -0
  83. data/lib/generators/templet/templates/core/templet/mixins.rb +9 -0
  84. data/lib/generators/templet/templates/core/templet/mixins/bs.rb +11 -0
  85. data/lib/generators/templet/templates/core/templet/mixins/bs/grid.rb +53 -0
  86. data/lib/generators/templet/templates/core/templet/mixins/bs/lists.rb +77 -0
  87. data/lib/generators/templet/templates/core/templet/mixins/field_procs.rb +140 -0
  88. data/lib/generators/templet/templates/core/templet/mixins/html_presenters.rb +82 -0
  89. data/lib/generators/templet/templates/core/templet/require_all.rb +45 -0
  90. data/lib/generators/templet/templates/core/templet/utils/html_search_form.rb +53 -0
  91. data/lib/generators/templet/templates/core/templet/utils/link_set_factory.rb +46 -0
  92. data/lib/generators/templet/templates/core/templet/utils/link_set_factory_wrapper.rb +53 -0
  93. data/lib/generators/templet/templates/core/templet/utils/list_model_parents.rb +27 -0
  94. data/lib/generators/templet/templates/core/templet/utils/navbar_form.rb +26 -0
  95. data/lib/generators/templet/templates/core/templet/utils/selected_wrapper.rb +40 -0
  96. data/lib/generators/templet/templates/core/templet/viewer.rb +11 -0
  97. data/lib/generators/templet/templates/core/templet/viewer/meta_model.rb +66 -0
  98. data/lib/generators/templet/templates/core/templet/viewer/meta_model_defaults.rb +56 -0
  99. data/lib/generators/templet/templates/core/templet/viewer/presenters.rb +44 -0
  100. data/lib/generators/templet/templates/core/templet/viewer/rest_actions.rb +24 -0
  101. data/lib/generators/templet/templates/core/templet/viewer_base.rb +111 -0
  102. data/lib/generators/templet/templates/core/templet/viewer_rest.rb +144 -0
  103. data/lib/generators/templet/viewer/USAGE +10 -0
  104. data/lib/generators/templet/viewer/viewer_generator.rb +86 -0
  105. data/lib/templet_rails.rb +5 -0
  106. data/lib/templet_rails/version.rb +3 -0
  107. data/templet_rails.gemspec +36 -0
  108. metadata +178 -0
@@ -0,0 +1,14 @@
1
+ Description:
2
+ Displays the routing entry for a REST controller.
3
+ If the option, --add-route is supplied then it actually writes this
4
+ routing information to the config/routes.rb file.
5
+
6
+ Example:
7
+ rails generate templet:routes admin/user --parent group --add-route --actions index show
8
+
9
+ This example will add an entry near the top of:
10
+ config/routes.rb
11
+ as follows:
12
+ namespace('admin') do
13
+ resources(:groups, only: []) { resources(:users, only: %i(index show)) }
14
+ end
@@ -0,0 +1,64 @@
1
+
2
+ require_relative '../shared/parent_option'
3
+ require_relative '../shared/add_routes_option'
4
+ require_relative '../shared/actions_option'
5
+
6
+ class Templet::RoutesGenerator < Rails::Generators::NamedBase
7
+ include Shared::ParentOption
8
+ include Shared::AddRoutesOption
9
+ include Shared::ActionsOption
10
+
11
+ source_root File.expand_path('.', __FILE__)
12
+ desc
13
+
14
+ def add_routes
15
+ routes = route_statement
16
+
17
+ if add_routes?
18
+ route routes
19
+
20
+ puts 'Routes written to config/routes.rb as follows:', routes
21
+ else
22
+ puts 'If applicable, update your config/routes.rb file with:', routes
23
+ end
24
+ end
25
+
26
+ private
27
+
28
+ def route_statement
29
+ in_scope { in_parent { resources plural_name, only_actions: true } }
30
+ end
31
+
32
+ def in_scope
33
+ if scope_name
34
+ " namespace('#{scope_name}') do\n #{yield}\n end\n"
35
+ else
36
+ yield
37
+ end
38
+ end
39
+
40
+ def in_parent
41
+ if parent
42
+ " #{resources parent.pluralize, no_only: true} { #{yield} }"
43
+ else
44
+ " #{yield}"
45
+ end
46
+ end
47
+
48
+ def resources(name, **options)
49
+ "resources(:#{name}#{only_actions **options})"
50
+ end
51
+
52
+ ONLY = ', only: '
53
+ def only_actions(only_actions: false, no_only: false)
54
+ only_actions ? action_syms(ONLY) : no_only ? "#{ONLY}[]" : ''
55
+ end
56
+
57
+ def scope_name
58
+ elements = file_path.split('/')[0..-2]
59
+
60
+ if elements.any?
61
+ elements * '/'
62
+ end
63
+ end
64
+ end
@@ -0,0 +1,10 @@
1
+ Description:
2
+ Creates tests to check the HTML in the views using CSS selectors.
3
+ And further tests to check the JSON output from the controller.
4
+
5
+ Example:
6
+ rails generate templet:rspec admin/user --model person --parent group --grand-parent sector
7
+
8
+ This will create:
9
+ spec/apis/admin/users_controller_spec.rb
10
+ spec/helpers/app/admin/user_viewer_spec.rb
@@ -0,0 +1,124 @@
1
+
2
+ require_relative '../shared/parent_option'
3
+ require_relative '../shared/grand_parent_option'
4
+ require_relative '../shared/model_option'
5
+ require_relative '../shared/comment_tests_option'
6
+ require_relative '../shared/model_fields'
7
+ require_relative '../shared/actions_option'
8
+
9
+ class Templet::RspecGenerator < Rails::Generators::NamedBase
10
+ FILL_IN = 'FILL_IN_FIELD_NAME'
11
+
12
+ include Shared::ParentOption
13
+ include Shared::GrandParentOption
14
+ include Shared::ModelOption
15
+ include Shared::CommentTestsOption
16
+ include Shared::ActionsOption
17
+
18
+ include Shared::ModelFields
19
+
20
+ viewer_desc = "Create a spec file containing tests for the viewer class"
21
+ class_option 'viewer-tests', type: :boolean, aliases: "-v",
22
+ default: true, desc: viewer_desc
23
+
24
+ source_root File.expand_path('.', __FILE__)
25
+ desc
26
+
27
+ def create_viewer
28
+ create_file viewer_path, viewer_spec if viewer_tests?
29
+ end
30
+
31
+ def create_controller_api
32
+ create_file controller_api_path, controller_api_spec
33
+ end
34
+
35
+ private
36
+
37
+ def viewer_path
38
+ "spec/helpers/app/#{file_path}_viewer_spec.rb"
39
+ end
40
+
41
+ def viewer_tests?
42
+ options['viewer-tests']
43
+ end
44
+
45
+ def controller_api_path
46
+ "spec/apis/#{file_path.pluralize}_controller_spec.rb"
47
+ end
48
+
49
+ def assign_overrides
50
+ "#{assign_parent}#{assign_grand_parent}#{assign_scope}#{assign_controller}"
51
+ end
52
+
53
+ def assign_parent
54
+ parent ? " let(:parent_name) { :#{parent} }\n\n" : ""
55
+ end
56
+
57
+ def assign_grand_parent
58
+ grand_parent ? " let(:grand_parent_name) { :#{grand_parent} }\n\n" : ""
59
+ end
60
+
61
+ def assign_scope
62
+ elements = file_path.split('/')[0..-2]
63
+
64
+ if elements.any?
65
+ scope = elements * '/'
66
+
67
+ scope ? " let(:scope) { '#{scope}' }\n\n" : ""
68
+ end
69
+ end
70
+
71
+ def assign_controller
72
+ controller_name = file_path.split('/').last
73
+
74
+ if controller_name != model_name
75
+ " let(:controller_name) { '#{controller_name.pluralize}' }\n\n"
76
+ end
77
+ end
78
+
79
+ def comment(name=:begin)
80
+ comment_tests? ? "\n=#{name}" : ''
81
+ end
82
+
83
+ def viewer_spec
84
+ name = model_name || singular_name
85
+
86
+ input_field, input_field_tag = textual_field_with_tag name
87
+
88
+ %Q[
89
+ require "rails_helper"
90
+ #{comment}
91
+ RSpec.describe App::#{class_name}Viewer, type: :helper do
92
+ it_should_behave_like "a viewer"#{action_syms ', '} do
93
+ let(:model_name) { :#{name} }
94
+
95
+ #{assign_overrides}
96
+ let(:field_name) { :#{input_field || FILL_IN} }
97
+
98
+ let(:input_field_tag) { "#{input_field_tag || FILL_IN}" }
99
+ end
100
+ end
101
+ #{comment :end}
102
+ ]
103
+ end
104
+
105
+ def controller_api_spec
106
+ name = model_name || singular_name
107
+
108
+ input_field, _ = textual_field_with_tag name
109
+
110
+ %Q[
111
+ require "rails_helper"
112
+ #{comment}
113
+ RSpec.describe #{class_name.pluralize}Controller, type: :api do
114
+ it_behaves_like "a json controller"#{action_syms ', '} do
115
+ let(:model_singular) { :#{name} }
116
+
117
+ #{assign_overrides}
118
+ let(:field_name) { :#{input_field || FILL_IN} }
119
+ end
120
+ end
121
+ #{comment :end}
122
+ ]
123
+ end
124
+ end
@@ -0,0 +1,22 @@
1
+ Description:
2
+ Generates a CRUD controller that renders a view via a Viewer class,
3
+ an actual Viewer class (which renders HTML),
4
+ tests for the controller & views,
5
+ and a routing entry for config/routes.rb.
6
+ It should produce fully working code.
7
+ It invokes, in turn, the four generators:
8
+ templet:controller, templet:viewer, templet:rspec and templet:routes.
9
+ By default, the model's name is taken from that of the controller's,
10
+ to specify a different model name use the MODEL option
11
+
12
+ Example:
13
+ rails generate templet:scaffold admin/user --model person --parent group --grand-parent department --child project --add-routes --actions index show
14
+
15
+ This will create:
16
+ app/controllers/admin/users_controller.rb
17
+ app/helpers/app/admin/user_viewer.rb
18
+ spec/apis/admin/users_controller_spec.rb
19
+ spec/helpers/app/admin/user_viewer_spec.rb
20
+
21
+ And, if requested, will add an entry to:
22
+ config/routes.rb
@@ -0,0 +1,75 @@
1
+
2
+ require_relative '../shared/model_option'
3
+ require_relative '../shared/parent_option'
4
+ require_relative '../shared/grand_parent_option'
5
+ require_relative '../shared/child_option'
6
+ require_relative '../shared/add_routes_option'
7
+ require_relative '../shared/comment_tests_option'
8
+ require_relative '../shared/actions_option'
9
+
10
+ class Templet::ScaffoldGenerator < Rails::Generators::NamedBase
11
+ include Shared::ModelOption
12
+ include Shared::ParentOption
13
+ include Shared::GrandParentOption
14
+ include Shared::ChildOption
15
+ include Shared::CommentTestsOption
16
+ include Shared::AddRoutesOption
17
+ include Shared::ActionsOption
18
+
19
+ source_root File.expand_path('.', __FILE__)
20
+ desc
21
+
22
+ def create_controller
23
+ generate 'templet:controller', args(name, parent_option, model_option,
24
+ grand_parent_option, actions_option)
25
+ end
26
+
27
+ def create_viewer_subclass
28
+ generate 'templet:viewer', args(name, child_option, actions_option)
29
+ end
30
+
31
+ def create_rspec
32
+ generate 'templet:rspec', args(name, parent_option, model_option,
33
+ grand_parent_option,
34
+ comment_tests_option, actions_option)
35
+ end
36
+
37
+ def create_routes
38
+ generate 'templet:routes', args(name, parent_option,
39
+ add_routes_option, actions_option)
40
+ end
41
+
42
+ private
43
+
44
+ def args(*options)
45
+ options * ' ' + ' '
46
+ end
47
+
48
+ def parent_option
49
+ parent ? "--parent #{parent}" : ''
50
+ end
51
+
52
+ def model_option
53
+ model_name? ? "--model #{model_name}" : ''
54
+ end
55
+
56
+ def grand_parent_option
57
+ grand_parent ? "--grand-parent #{grand_parent}" : ''
58
+ end
59
+
60
+ def child_option
61
+ child? ? "--child #{child}" : ''
62
+ end
63
+
64
+ def add_routes_option
65
+ add_routes? ? "--add-routes" : ''
66
+ end
67
+
68
+ def comment_tests_option
69
+ comment_tests? ? '' : "--no-comment-tests"
70
+ end
71
+
72
+ def actions_option
73
+ actions&.any? ? "--actions #{actions * ' '}" : ''
74
+ end
75
+ end
@@ -0,0 +1,24 @@
1
+
2
+ module Shared
3
+ module ActionsOption
4
+ def self.included(base)
5
+ desc = "A list of REST action names - leave this out if you want them all"
6
+
7
+ base.class_eval do
8
+ class_option :actions, type: :array, aliases: "-a",
9
+ banner: 'index show create',
10
+ default: [], desc: desc
11
+ end
12
+ end
13
+
14
+ private
15
+
16
+ def actions
17
+ options['actions'].any? ? options['actions'] : nil
18
+ end
19
+
20
+ def action_syms(prefix='')
21
+ actions and "#{prefix}%i(#{actions * ' '})"
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,19 @@
1
+
2
+ module Shared
3
+ module AddRoutesOption
4
+ def self.included(base)
5
+ desc = "Update the the file config/routes.rb"
6
+
7
+ base.class_eval do
8
+ class_option 'add-routes', type: :boolean, aliases: "-r",
9
+ default: false, desc: desc
10
+ end
11
+ end
12
+
13
+ private
14
+
15
+ def add_routes?
16
+ options['add-routes']
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,23 @@
1
+
2
+ module Shared
3
+ module ChildOption
4
+ def self.included(base)
5
+ desc = "A direct descendant of the model - the principal has_many record type"
6
+
7
+ base.class_eval do
8
+ class_option :child, type: :string, aliases: "-c", default: nil,
9
+ banner: 'singular name', desc: desc
10
+ end
11
+ end
12
+
13
+ private
14
+
15
+ def child
16
+ options['child']
17
+ end
18
+
19
+ def child?
20
+ child and child.present?
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,19 @@
1
+
2
+ module Shared
3
+ module CommentTestsOption
4
+ def self.included(base)
5
+ desc = "Insert block comments around Viewer and JSON tests"
6
+
7
+ base.class_eval do
8
+ class_option 'comment-tests', type: :boolean, aliases: "-t",
9
+ default: true, desc: desc
10
+ end
11
+ end
12
+
13
+ private
14
+
15
+ def comment_tests?
16
+ options['comment-tests']
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,48 @@
1
+
2
+ module Shared
3
+ module CoreHelpers
4
+ SOURCE_ROOT = File.expand_path('../../templates/core', __FILE__) + '/'
5
+
6
+ LIB_ROOT = 'lib/'
7
+ APP_ROOT = 'app/'
8
+
9
+ APP_SUBDIR = 'app/'
10
+ HELPERS_SUBDIR = 'helpers/'
11
+ TEMPLET_SUBDIR = 'templet/'
12
+ SPEC_SUBDIR = 'spec/'
13
+ SUPPORT_SUBDIR = 'support/'
14
+
15
+ private
16
+
17
+ def copy(from, to)
18
+ puts "#{from}\n => #{to}"
19
+ end
20
+
21
+ #alias copy_file copy
22
+ #alias directory copy
23
+
24
+ def rspec?
25
+ Dir.exists? spec_support_dir
26
+ end
27
+
28
+ def spec_support_dir
29
+ SPEC_SUBDIR + SUPPORT_SUBDIR
30
+ end
31
+
32
+ def already_installed_at
33
+ dest_dirs.each do |dir|
34
+ return dir if Dir.exists?(dir) and not Dir.empty?(dir)
35
+ end
36
+
37
+ nil
38
+ end
39
+
40
+ def dest_dirs
41
+ [ core_default_dir ]
42
+ end
43
+
44
+ def core_default_dir
45
+ APP_ROOT + HELPERS_SUBDIR + TEMPLET_SUBDIR
46
+ end
47
+ end
48
+ end