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,61 @@
1
+
2
+ module Templet
3
+ module Links
4
+ # For Bootstrap link/button HTML classes
5
+ class BsBtnClass < Struct.new(:type, :size)
6
+ include Constants
7
+
8
+ def call(type: type(), size: size())
9
+ "#{BS_BUTTON} " +
10
+ "#{BS_BUTTON}-#{type or default_type} " +
11
+ "#{BS_BUTTON}-#{size or default_size}"
12
+ end
13
+
14
+ alias to_s call
15
+
16
+ # Allows compatibily with an HTML class specifield in a String
17
+ def +(suffix)
18
+ suffix = suffix.to_s
19
+
20
+ call + (suffix.start_with?(' ') ? '' : ' ') + suffix
21
+ end
22
+
23
+ class << self
24
+ def call(html_class=nil)
25
+ case html_class
26
+ when String, self
27
+ html_class
28
+ when Symbol
29
+ preset html_class
30
+ when Array
31
+ new *html_class
32
+ else
33
+ new
34
+ end
35
+ end
36
+
37
+ def preset(name=nil)
38
+ case name
39
+ when :default
40
+ new
41
+ when :item
42
+ Constants::BS_LIST_GROUP_ITEM
43
+ else
44
+ new name
45
+ end
46
+ end
47
+ end
48
+
49
+ private
50
+
51
+ def default_type
52
+ BS_BUTTON_TYPE
53
+ end
54
+
55
+ def default_size
56
+ BS_BUTTON_SIZE
57
+ end
58
+ end
59
+ end
60
+ end
61
+
@@ -0,0 +1,168 @@
1
+
2
+ module Templet
3
+ module Links
4
+ # Superclass with utility methods for building a list (Array) of HTML links.
5
+ # Primarily for REST actions, but any kind of link may be specified.
6
+ #
7
+ # Designed to work with any subclass of ActiveRecord.
8
+ class BsLinkSetBase
9
+ include Constants
10
+
11
+ attr_accessor :renderer, :model, :parent, :backward, :forward
12
+
13
+ attr_accessor :scope, :controller, :remote, :html_class,
14
+ :selected, :omit_selected,
15
+ :default_params, :verify_links,
16
+ :wrapper
17
+
18
+ def initialize(renderer, model, parent, backward=nil, forward=nil,
19
+ scope: nil, controller: nil,
20
+ remote: nil, html_class: nil,
21
+ selected: nil, omit_selected: false,
22
+ default_params: nil,
23
+ verify_links: false,
24
+ wrapper: nil)
25
+ self.renderer = renderer
26
+
27
+ self.model = model
28
+ self.parent = parent
29
+
30
+ self.backward = backward
31
+ self.forward = forward
32
+
33
+ self.scope = scope
34
+ self.controller = controller
35
+
36
+ self.remote = remote
37
+
38
+ self.html_class = BsBtnClass.(html_class)
39
+
40
+ self.selected = selected || BS_SELECTED
41
+
42
+ self.omit_selected = omit_selected
43
+
44
+ self.default_params = default_params
45
+
46
+ self.verify_links = verify_links
47
+
48
+ self.wrapper = get_wrapper(wrapper)
49
+ end
50
+
51
+ private
52
+
53
+ def get_wrapper(wrapper)
54
+ if wrapper
55
+ if wrapper.respond_to? :call
56
+ wrapper
57
+ else
58
+ Utils::SelectedWrapper.new(wrapper, selected)
59
+ end
60
+ end
61
+ end
62
+
63
+ def push(links, link)
64
+ links << link if links and link
65
+ end
66
+
67
+ def rest_link_procs(link_class, remote: remote(), controller: controller())
68
+ RestLinkProcs.new link_class, scope: scope,
69
+ controller: controller,
70
+ remote: remote,
71
+ default_params: default_params,
72
+ verify_path: verify_links
73
+ end
74
+
75
+ def link_procs(is_selected=false)
76
+ is_selected ? selected_link_procs : unselected_link_procs
77
+ end
78
+
79
+ def unselected_link_procs
80
+ @unselected_link_procs ||= rest_link_procs(html_class)
81
+ end
82
+
83
+ def selected_link_procs
84
+ @selected_link_procs ||= rest_link_procs(selected_class)
85
+ end
86
+
87
+ def selected_class
88
+ html_class + "#{selected.start_with?(' ') ? '' : ' '}#{selected}"
89
+ end
90
+
91
+ def link_proc(action, is_selected=false)
92
+ link_method = "#{action}_link"
93
+
94
+ if wrapper
95
+ link = link_procs.send(link_method).(renderer, model, parent)
96
+
97
+ wrapper.(link, is_selected)
98
+ else
99
+ link_procs(is_selected).send(link_method).(renderer, model, parent)
100
+ end
101
+ end
102
+
103
+ def link_proc_unless(action, current_action, to: nil)
104
+ is_selected = selected? current_action, action
105
+
106
+ if display?(is_selected)
107
+ link_proc(action, is_selected).tap {|link| push to, link }
108
+ end
109
+ end
110
+
111
+ def link_proc_by_path_selected(action, current_action, *args)
112
+ is_selected = selected? current_action, action
113
+
114
+ if display?(is_selected)
115
+ if wrapper
116
+ link = link_procs.link_by_path(*args).(renderer, model, parent)
117
+
118
+ wrapper.(link, is_selected)
119
+ else
120
+ link_procs(is_selected).link_by_path(*args)
121
+ .(renderer, model, parent)
122
+ end
123
+ end
124
+ end
125
+
126
+ def link_proc_by_action_selected(action, current_action, *args)
127
+ is_selected = selected? current_action, action
128
+
129
+ if display?(is_selected)
130
+ if wrapper
131
+ link = link_procs.link_by_action(action, *args)
132
+ .(renderer, model, parent)
133
+
134
+ wrapper.(link, is_selected)
135
+ else
136
+ link_procs(is_selected).link_by_action(action, *args)
137
+ .(renderer, model, parent)
138
+ end
139
+ end
140
+ end
141
+
142
+ def parent_link_proc(action)
143
+ link = rest_link_procs(html_class, controller: nil)
144
+ .send("#{action}_parent_link", **grand_parent_options)
145
+ .(renderer, nil, parent)
146
+
147
+ wrapper ? wrapper.(link) : link
148
+ end
149
+
150
+ def grand_parent_options
151
+ { grand_parent: backward }
152
+ end
153
+
154
+ def selected?(current_action, action)
155
+ current_action.to_s == action.to_s
156
+ end
157
+
158
+ def display?(is_selected)
159
+ not (omit_selected and is_selected)
160
+ end
161
+
162
+ def rest_path(scope: scope(), controller: controller())
163
+ RestPath.new(model, parent, scope: scope, controller: controller)
164
+ end
165
+ end
166
+ end
167
+ end
168
+
@@ -0,0 +1,21 @@
1
+
2
+ module Templet
3
+ module Links
4
+ # Returns a list of REST links when there's no model instance.
5
+ # For the buttons: back, index & new
6
+ class BsLinkSetCollection < BsLinkSetBase
7
+ def call(action=nil)
8
+ links = []
9
+
10
+ links << parent_link_proc(:index) if parent
11
+
12
+ link_proc_unless(:index, action, to: links)
13
+
14
+ link_proc_unless(:new, action, to: links)
15
+
16
+ links
17
+ end
18
+ end
19
+ end
20
+ end
21
+
@@ -0,0 +1,62 @@
1
+
2
+ module Templet
3
+ module Links
4
+ # Returns a list of links for a model instance.
5
+ # Has all the main buttons for REST actions.
6
+ class BsLinkSetNavigation < BsLinkSetBase
7
+ # Returns a list of 3 lists of REST links.
8
+ # The first is for parent links
9
+ # The second are links for the current model
10
+ # The third is a link pointing to an index of hildren
11
+ # Note that this list is usually flattened.
12
+ def call(action=nil)
13
+ parents, current, children = [ [], [], [] ]
14
+
15
+ # Ancestors
16
+ if parent
17
+ push parents, parent_link_proc(:index)
18
+
19
+ push parents, parent_link_proc(:show)
20
+ end
21
+
22
+ # Current model
23
+
24
+ link_proc_unless(:new, action, to: current)
25
+
26
+ if have_instance?
27
+ link_proc_unless(:edit, action, to: current)
28
+
29
+ link_proc_unless(:show, action, to: current)
30
+
31
+ push current, link_proc(:delete)
32
+ end
33
+
34
+ link_proc_unless(:index, action, to: current)
35
+
36
+ # Descendants
37
+ if have_instance?
38
+ if forward
39
+ push children, link_procs.index_link.(renderer, forward, model)
40
+
41
+ singular = forward.to_s.singularize
42
+
43
+ push children, link_procs.new_link.(renderer, singular, model)
44
+ end
45
+ end
46
+
47
+ Array.new << parents << current << children
48
+ end
49
+
50
+ private
51
+
52
+ def push_in(links, link, at: 1)
53
+ links[at].push link if link
54
+ end
55
+
56
+ def have_instance?
57
+ not (Symbol === model or String === model or model.new_record?)
58
+ end
59
+ end
60
+ end
61
+ end
62
+
@@ -0,0 +1,163 @@
1
+
2
+ module Templet
3
+ module Links
4
+ # For rendering REST links for any type of model.
5
+ # The methods return lambdas that take as parameters a model
6
+ # and its (optional) parent.
7
+ # These lambdas are also given a Renderer instance,
8
+ # with which they call the Rails helper method +link_to+, as used in views.
9
+ class RestLinkProcs
10
+ include RestLinkProcsSets
11
+ include RestLinkProcsParent
12
+
13
+ attr_accessor :link_class, :scope, :controller,
14
+ :remote, :link_text, :default_params,
15
+ :verify_path
16
+
17
+ def initialize(link_class=nil, remote: nil,
18
+ scope: nil,
19
+ controller: nil,
20
+ default_params: nil,
21
+ link_text: nil,
22
+ verify_path: false)
23
+ self.link_class = BsBtnClass.(link_class)
24
+
25
+ self.remote = remote
26
+
27
+ self.scope = scope
28
+
29
+ self.controller = controller
30
+
31
+ self.default_params = default_params
32
+
33
+ self.link_text ||= RestLinkText.new
34
+
35
+ self.verify_path = verify_path
36
+ end
37
+
38
+ def index_link(text=nil, name: nil, params: nil, title: nil)
39
+ -> renderer, model, parent {
40
+ parent, model = model, name if name
41
+
42
+ text ||= link_text.index(model)
43
+
44
+ link_to(renderer, :index, model, parent, text, params, title)
45
+ }
46
+ end
47
+
48
+ def show_link(text=nil, params: nil, title: nil)
49
+ -> renderer, model, parent {
50
+ text ||= link_text.show(model)
51
+
52
+ link_to(renderer, :show, model, parent, text, params, title)
53
+ }
54
+ end
55
+
56
+ def new_link(text=nil, name: nil, params: nil, title: nil)
57
+ -> renderer, model, parent {
58
+ parent, model = model, name if name
59
+
60
+ text ||= link_text.new(model)
61
+
62
+ link_to(renderer, :new, model, parent, text, params, title)
63
+ }
64
+ end
65
+
66
+ def edit_link(text=nil, params: nil, title: nil)
67
+ -> renderer, model, parent {
68
+ text ||= link_text.edit(model)
69
+
70
+ link_to(renderer, :edit, model, parent, text, params, title)
71
+ }
72
+ end
73
+
74
+ def delete_link(text=nil, params: nil, title: nil)
75
+ -> renderer, model, parent {
76
+ text ||= link_text.delete(model)
77
+
78
+ link_to(renderer, :delete, model, parent, text,
79
+ params, title, delete_options)
80
+ }
81
+ end
82
+
83
+ alias destroy_link delete_link
84
+
85
+ # For additional REST controller links
86
+ def link_by_action(name, params: nil, text: nil, title: nil,
87
+ on_collection: false, opts: {})
88
+ text ||= name.to_s.capitalize
89
+
90
+ -> renderer, model, parent {
91
+ path = rest_path(model, parent)
92
+ .action(name, params: parameters(params),
93
+ on_collection: on_collection)
94
+
95
+ title ||= link_text.default_title(name, model)
96
+
97
+ link_options = link_to_options title
98
+
99
+ renderer.call { link_to text, path, link_options.merge(opts) }
100
+ }
101
+ end
102
+
103
+ # For arbitrary explicitly given links - REST or otherwise
104
+ def link_by_path(path, text=nil, title=nil, opts={})
105
+ -> renderer, model, parent {
106
+ link_options = link_to_options title
107
+
108
+ path = path.(renderer, model, parent) if path.respond_to? :call
109
+
110
+ text ||= link_text.by_path(path)
111
+
112
+ renderer.call { link_to text, path, link_options.merge(opts) }
113
+ }
114
+ end
115
+
116
+ private
117
+
118
+ def link_to(renderer, action, model, parent, text, params, title, opts={})
119
+ path = rest_path(model, parent).send(action, parameters(params))
120
+
121
+ return if verify_path and not path_exists?(renderer, path)
122
+
123
+ title ||= link_text.default_title(action, model)
124
+
125
+ link_options = link_to_options title
126
+
127
+ renderer.call { link_to text, path, link_options.merge(opts) }
128
+ end
129
+
130
+ def path_exists?(renderer, path)
131
+ !! renderer.url_for(path) rescue false
132
+ end
133
+
134
+ def delete_options
135
+ { method: :delete, data: confirm }
136
+ end
137
+ def confirm
138
+ { confirm: 'Delete this record?' }
139
+ end
140
+
141
+ def parameters(params)
142
+ if default_params
143
+ default_params.merge(params || {})
144
+ else
145
+ params
146
+ end
147
+ end
148
+
149
+ def link_to_options(title)
150
+ opts = link_class ? { class: link_class.to_s, role: 'button' } : {}
151
+
152
+ opts[:remote] = true if remote
153
+
154
+ opts.merge title: title || ''
155
+ end
156
+
157
+ def rest_path(model, parent=nil)
158
+ RestPath.new(model, parent, scope: scope, controller: controller)
159
+ end
160
+ end
161
+ end
162
+ end
163
+