abstracted 0.0.4

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 (101) hide show
  1. checksums.yaml +7 -0
  2. data/.envrc +1 -0
  3. data/.gitignore +8 -0
  4. data/.rspec +3 -0
  5. data/.ruby-version +1 -0
  6. data/Gemfile +14 -0
  7. data/Gemfile.lock +218 -0
  8. data/Guardfile +77 -0
  9. data/MIT-LICENSE +20 -0
  10. data/README.rdoc +3 -0
  11. data/Rakefile +15 -0
  12. data/abstracted.gemspec +51 -0
  13. data/app/assets/images/abstracted/.keep +0 -0
  14. data/app/assets/javascripts/abstract_resources.js +39 -0
  15. data/app/assets/javascripts/abstracted/.keep +0 -0
  16. data/app/assets/javascripts/crud.js.coffee +49 -0
  17. data/app/assets/javascripts/initializers.js.coffee +111 -0
  18. data/app/assets/stylesheets/abstract_resources.css +5 -0
  19. data/app/assets/stylesheets/abstracted/.keep +0 -0
  20. data/app/assets/stylesheets/scaffold.css +56 -0
  21. data/app/controllers/.keep +0 -0
  22. data/app/controllers/abstract_resources_controller.rb +290 -0
  23. data/app/controllers/application_controller.rb +22 -0
  24. data/app/helpers/.keep +0 -0
  25. data/app/helpers/abstract_resources_helper.rb +26 -0
  26. data/app/mailers/.keep +0 -0
  27. data/app/models/.keep +0 -0
  28. data/app/models/abstract_resource.rb +122 -0
  29. data/app/models/concerns/roleable.rb +61 -0
  30. data/app/policies/abstract_resource_policy.rb +58 -0
  31. data/app/views/.keep +0 -0
  32. data/app/views/abstract_resources/_default.html.erb +11 -0
  33. data/app/views/abstract_resources/destroy.js.haml +1 -0
  34. data/app/views/abstract_resources/edit.html.haml +11 -0
  35. data/app/views/abstract_resources/index.html.erb +1 -0
  36. data/app/views/abstract_resources/new.html.haml +12 -0
  37. data/app/views/abstract_resources/show.html.haml +13 -0
  38. data/bin/rails +12 -0
  39. data/config/locales/abstracted.en.yml +20 -0
  40. data/config/routes.rb +4 -0
  41. data/lib/abstracted.rb +8 -0
  42. data/lib/abstracted/engine.rb +19 -0
  43. data/lib/abstracted/version.rb +3 -0
  44. data/lib/abstracted_responder.rb +7 -0
  45. data/lib/tasks/abstracted_tasks.rake +4 -0
  46. data/spec/controllers/abstract_resources_controller_spec.rb +241 -0
  47. data/spec/dummy/README.rdoc +28 -0
  48. data/spec/dummy/Rakefile +6 -0
  49. data/spec/dummy/app/assets/images/.keep +0 -0
  50. data/spec/dummy/app/assets/javascripts/application.js +13 -0
  51. data/spec/dummy/app/assets/stylesheets/application.css +15 -0
  52. data/spec/dummy/app/controllers/application_controller.rb +5 -0
  53. data/spec/dummy/app/controllers/concerns/.keep +0 -0
  54. data/spec/dummy/app/helpers/application_helper.rb +2 -0
  55. data/spec/dummy/app/mailers/.keep +0 -0
  56. data/spec/dummy/app/models/.keep +0 -0
  57. data/spec/dummy/app/models/concerns/.keep +0 -0
  58. data/spec/dummy/app/models/user.rb +3 -0
  59. data/spec/dummy/app/views/layouts/application.html.erb +14 -0
  60. data/spec/dummy/bin/bundle +3 -0
  61. data/spec/dummy/bin/rails +4 -0
  62. data/spec/dummy/bin/rake +4 -0
  63. data/spec/dummy/bin/setup +29 -0
  64. data/spec/dummy/config.ru +4 -0
  65. data/spec/dummy/config/application.rb +26 -0
  66. data/spec/dummy/config/boot.rb +5 -0
  67. data/spec/dummy/config/database.yml +25 -0
  68. data/spec/dummy/config/environment.rb +5 -0
  69. data/spec/dummy/config/environments/development.rb +41 -0
  70. data/spec/dummy/config/environments/production.rb +79 -0
  71. data/spec/dummy/config/environments/test.rb +42 -0
  72. data/spec/dummy/config/initializers/assets.rb +11 -0
  73. data/spec/dummy/config/initializers/backtrace_silencers.rb +7 -0
  74. data/spec/dummy/config/initializers/cookies_serializer.rb +3 -0
  75. data/spec/dummy/config/initializers/filter_parameter_logging.rb +4 -0
  76. data/spec/dummy/config/initializers/inflections.rb +16 -0
  77. data/spec/dummy/config/initializers/mime_types.rb +4 -0
  78. data/spec/dummy/config/initializers/session_store.rb +3 -0
  79. data/spec/dummy/config/initializers/wrap_parameters.rb +14 -0
  80. data/spec/dummy/config/locales/en.yml +23 -0
  81. data/spec/dummy/config/routes.rb +56 -0
  82. data/spec/dummy/config/secrets.yml +22 -0
  83. data/spec/dummy/db/development.sqlite3 +0 -0
  84. data/spec/dummy/db/schema.rb +21 -0
  85. data/spec/dummy/db/test.sqlite3 +0 -0
  86. data/spec/dummy/lib/assets/.keep +0 -0
  87. data/spec/dummy/log/.keep +0 -0
  88. data/spec/dummy/log/development.log +0 -0
  89. data/spec/dummy/log/test.log +6229 -0
  90. data/spec/dummy/public/404.html +67 -0
  91. data/spec/dummy/public/422.html +67 -0
  92. data/spec/dummy/public/500.html +66 -0
  93. data/spec/dummy/public/favicon.ico +0 -0
  94. data/spec/factories/abstract_resources.rb +6 -0
  95. data/spec/factories/users.rb +5 -0
  96. data/spec/features/posts/manage_posts_spec.rb +24 -0
  97. data/spec/models/abstract_resource_spec.rb +14 -0
  98. data/spec/rails_helper.rb +114 -0
  99. data/spec/spec_helper.rb +97 -0
  100. data/test/integration/abstract_resource_test.rb +7 -0
  101. metadata +424 -0
@@ -0,0 +1,49 @@
1
+ #
2
+ # deletePost handles deleting records
3
+ #
4
+ # dependencies:
5
+ # sweetalert
6
+ #
7
+ # data-url="", data-id="" - eg.
8
+
9
+ closeSweetAlert = () ->
10
+ try
11
+ swal.close()
12
+ catch error
13
+ $('.sweet-overlay').hide()
14
+ $('.sweet-alert').hide()
15
+
16
+ @deletePost = ($elem) ->
17
+ try
18
+ url = $elem.data('url') + "/" + $elem.data('id') + ".js"
19
+ $remove = $($elem.data('remove'))
20
+ request = $.ajax
21
+ url: url,
22
+ type: "delete",
23
+ statusCode:
24
+
25
+ 200: (response,textStatus,jqXHR) ->
26
+ if $remove
27
+ $remove.hide()
28
+ closeSweetAlert()
29
+ $('.message_container').html(response.responseText)
30
+
31
+ 301: () ->
32
+ $elem.show()
33
+ closeSweetAlert()
34
+ swal "Ikke slettet!", "Posten blev ikke slettet - årsagen ikke kendt", "warning"
35
+
36
+ 401: (response) ->
37
+ $('.message_container').append(response.responseText)
38
+ closeSweetAlert()
39
+
40
+ 409: (response) ->
41
+ $('.message_container').append(response.responseText)
42
+ closeSweetAlert()
43
+
44
+ 412: () ->
45
+ closeSweetAlert()
46
+ swal "Øv!", "Et eller andet gik galt!", "error"
47
+
48
+ catch error
49
+ swal "Hmmm", "#{error}", "error"
@@ -0,0 +1,111 @@
1
+ #
2
+ # initializeSweetAlert
3
+ # initializes the sweetalert prompt
4
+ #
5
+ @initializeSweetAlert = () ->
6
+ try
7
+ # console.log 'sweet alert initializing...'
8
+ sweetHTML = '<div class="sweet-overlay" tabIndex="-1"></div><div class="sweet-alert" tabIndex="-1"><div class="icon error"><span class="x-mark"><span class="line left"></span><span class="line right"></span></span></div><div class="icon warning"> <span class="body"></span> <span class="dot"></span> </div> <div class="icon info"></div> <div class="icon success"> <span class="line tip"></span> <span class="line long"></span> <div class="placeholder"></div> <div class="fix"></div> </div> <div class="icon custom"></div> <h2>Title</h2><p>Text</p><button class="cancel" tabIndex="2">Cancel</button><button class="confirm" tabIndex="1">OK</button></div>'
9
+ sweetWrap = document.createElement('div')
10
+ sweetWrap.innerHTML = sweetHTML
11
+ $(document.body).append(sweetWrap)
12
+ catch error
13
+ console.log error
14
+
15
+
16
+ #
17
+ # initializeDeleteLinks
18
+ # initializes the tags classed with '.delete_link' to verify deleting an issue
19
+ #
20
+ @initializeDeleteLinks = () ->
21
+ $('.delete_link').on 'click', (e) ->
22
+ e.preventDefault()
23
+ $elem = $(this)
24
+ $elem.hide()
25
+
26
+ swal
27
+ title: "Er du sikker?",
28
+ text: "Hvis du accepterer slettes posten <b>" + $(this).data('name') + "</b> permanent, og du vil ikke kunne hente den frem igen!",
29
+ type: "warning",
30
+ html: true,
31
+ showCancelButton: true,
32
+ confirmButtonColor: "#DD6B55",
33
+ confirmButtonText: "Ja, slet den!",
34
+ cancelButtonText: "Nej - jeg har fortrudt!"
35
+ closeOnConfirm: false,
36
+ # closeOnCancel: true,
37
+ (confirmed) ->
38
+ if !confirmed
39
+ $elem.show()
40
+ # swal "Ok!", "Posten blev ikke slettet - du valgte at fortryde.", "success"
41
+ else
42
+ deletePost($elem)
43
+
44
+ # console.log( ".delete_link event handler was set")
45
+
46
+
47
+ #
48
+ # fadeItOut will fade an element out with a preset or
49
+ # supplied delay
50
+ #
51
+ @fadeItOut = (e,delay=3500) ->
52
+ $(e).delay( delay ).fadeOut( 1000 )
53
+
54
+
55
+ #
56
+ # PageOnLoad loads and initializes
57
+ # fixed elements like SELECT's, Materialized's elements, et al.
58
+ #
59
+ @pageOnLoad = () ->
60
+
61
+ #
62
+ # Initialize the 'hamburger'
63
+ #
64
+ $(".button-collapse").sideNav();
65
+
66
+ #
67
+ # Initialize collapsible (uncomment the line below if you use the dropdown variation)
68
+ #
69
+ $('.collapsible').collapsible
70
+ accordion : true # A setting that changes the collapsible behavior to expandable instead of the default accordion style
71
+
72
+ #
73
+ # Initialize SELECT's
74
+ #
75
+ $('select').material_select();
76
+
77
+ #
78
+ # Initialize INPUT TYPE='DATE'
79
+ #
80
+ # %input.datepicker{ type:"date" }
81
+ #
82
+ $('.datepicker').pickadate
83
+ selectMonths: true, # Creates a dropdown to control month
84
+ selectYears: 15 # Creates a dropdown of 15 years to control year
85
+
86
+ #
87
+ # Prepare delete_link's for acting on clicks to delete posts
88
+ #
89
+ initializeDeleteLinks()
90
+
91
+ #
92
+ # Try to keep users from double-clicking submit's
93
+ #
94
+ # document.addEventListener('DOMContentLoaded', disableMultipleSubmits, false);
95
+
96
+ #
97
+ # Prepare close-notice's for acting on clicks to remove div
98
+ #
99
+ $('.message_container').delegate 'a.close-notice', 'click', () ->
100
+ $(this).closest('.alert').remove()
101
+
102
+ #
103
+ # make drop-downs react nicely
104
+ #
105
+ $(".dropdown-button").dropdown()
106
+
107
+ # here to test whether pageOnLoad runs - -
108
+ # try
109
+ # swal( 'pageOnLoad', 'pageOnLoad blev kaldt!', 'success')
110
+ # catch
111
+ # console.log 'autch!'
@@ -0,0 +1,5 @@
1
+ /*
2
+ * Place all the styles related to the matching controller here.
3
+ * They will automatically be included in application.css.
4
+ *
5
+ */
@@ -0,0 +1,56 @@
1
+ body { background-color: #fff; color: #333; }
2
+
3
+ body, p, ol, ul, td {
4
+ font-family: verdana, arial, helvetica, sans-serif;
5
+ font-size: 13px;
6
+ line-height: 18px;
7
+ }
8
+
9
+ pre {
10
+ background-color: #eee;
11
+ padding: 10px;
12
+ font-size: 11px;
13
+ }
14
+
15
+ a { color: #000; }
16
+ a:visited { color: #666; }
17
+ a:hover { color: #fff; background-color:#000; }
18
+
19
+ div.field, div.actions {
20
+ margin-bottom: 10px;
21
+ }
22
+
23
+ #notice {
24
+ color: green;
25
+ }
26
+
27
+ .field_with_errors {
28
+ padding: 2px;
29
+ background-color: red;
30
+ display: table;
31
+ }
32
+
33
+ #error_explanation {
34
+ width: 450px;
35
+ border: 2px solid red;
36
+ padding: 7px;
37
+ padding-bottom: 0;
38
+ margin-bottom: 20px;
39
+ background-color: #f0f0f0;
40
+ }
41
+
42
+ #error_explanation h2 {
43
+ text-align: left;
44
+ font-weight: bold;
45
+ padding: 5px 5px 5px 15px;
46
+ font-size: 12px;
47
+ margin: -7px;
48
+ margin-bottom: 0px;
49
+ background-color: #c00;
50
+ color: #fff;
51
+ }
52
+
53
+ #error_explanation ul li {
54
+ font-size: 12px;
55
+ list-style: square;
56
+ }
File without changes
@@ -0,0 +1,290 @@
1
+ require "abstracted_responder"
2
+
3
+ class AbstractResourcesController < ApplicationController
4
+ self.responder = ::AbstractedResponder
5
+ respond_to :html, :xml, :js, :json
6
+
7
+ before_action :set_resource
8
+ before_action :set_resources, only: [:index]
9
+ before_action :set_variant_template
10
+
11
+ before_filter :authenticate_user!
12
+ after_action :verify_authorized
13
+ # after_action :manage_parenthood, only: [:create,:update,:destroy]
14
+
15
+ # default implementation
16
+ def show
17
+ authorize resource
18
+ respond_with resource
19
+ rescue Exception => e
20
+ scoop_from_error e
21
+ end
22
+
23
+ def new
24
+ resource.parent_id = params[:parent_id] if resource.respond_to? :parent_id
25
+ authorize resource
26
+ respond_with resource
27
+ rescue Exception => e
28
+ scoop_from_error e
29
+ end
30
+
31
+ def edit
32
+ authorize resource
33
+ respond_with resource
34
+ rescue Exception => e
35
+ scoop_from_error e
36
+ end
37
+
38
+ def index
39
+ authorize resource_class
40
+ respond_with resources
41
+ rescue Exception => e
42
+ scoop_from_error e
43
+ end
44
+
45
+ def create
46
+ @resource = resource_class.new(resource_params)
47
+ authorize resource
48
+ flash[:notice] = t('.success.created', resource: resource_class.to_s ) if resource.save
49
+ respond_with(resource)
50
+ rescue Exception => e
51
+ scoop_from_error e
52
+ end
53
+
54
+ def update
55
+ authorize resource
56
+ flash[:notice] = t('.success.updated', resource: resource_class.to_s ) if resource.update_attributes(resource_params)
57
+ respond_with(resource)
58
+ rescue Exception => e
59
+ scoop_from_error e
60
+ end
61
+
62
+ def destroy
63
+ authorize resource
64
+ result = true if resource.destroy
65
+ result ? (flash.now[:notice] = t('.success', resource: resource_class.to_s)) : (flash.now[:error] = t('.deleted.error',resource: resource_class.to_s))
66
+ if result==true
67
+ render layout:false, status: 200, locals: { result: true }
68
+ else
69
+ render layout:false, status: 301, locals: { result: true }
70
+ end
71
+ rescue Exception => e
72
+ scoop_from_error e
73
+ end
74
+
75
+ def resource_params
76
+ raise 'You need to "def resource_params" on the %sController! (see: http://blog.trackets.com/2013/08/17/strong-parameters-by-example.html)' % params[:controller].capitalize
77
+ end
78
+
79
+ def set_resource
80
+ parent
81
+ resource
82
+ end
83
+
84
+ def set_resources
85
+ resources
86
+ end
87
+
88
+ def resource
89
+ @resource ||= (params[:id].nil? ? resource_class.new : resource_class.find(params[:id]) ) rescue nil
90
+ end
91
+
92
+ def resource_name
93
+ resource_class.to_s.underscore.pluralize
94
+ end
95
+
96
+ def resource_class
97
+ @resource_class ||= params[:controller].singularize.classify.constantize rescue nil
98
+ end
99
+
100
+ def parent
101
+ @parent ||= find_parent
102
+ end
103
+
104
+
105
+ def parent_class
106
+ @parent_class ||= @parent.class
107
+ end
108
+
109
+ def parent?
110
+ !(%w{NilClass TrueClass FalseClass}.include? @parent.class.to_s)
111
+ end
112
+
113
+ #
114
+ #
115
+ # return the resources collection - preferably from the cache
116
+ def resources options={}
117
+ @resources ||= find_resources options
118
+ end
119
+
120
+
121
+ #
122
+ # returns the url for the resource - like /users/1
123
+ def resource_url options={}
124
+ options = resource_options(options)
125
+ action= case params[:action]
126
+ when 'show'; '/%s' % resource.id
127
+ when 'edit'; '/%s/edit' % resource.id
128
+ else ''
129
+ end
130
+ parent? ? ("%s/%s%s%s" % [parent_url,resource_name,action,options]) : ("/%s%s%s" % [resource_name,action,options])
131
+ end
132
+
133
+
134
+ #
135
+ # returns the url for the resources - /employees or /employees/1/events
136
+ def resources_url options={}
137
+ options = resource_options(options)
138
+ "%s/%s" % [ parent_url, resource_name ]
139
+ end
140
+
141
+ #
142
+ # parent_url returns the parent url - /employees/1
143
+ def parent_url
144
+ parent? ? ( "/%s/%s" % [ @parent.class.table_name, @parent.id ] ) : ""
145
+ end
146
+
147
+
148
+ private
149
+
150
+ #
151
+ # use views/../$action.html+mobile.erb if request originates from an iPad
152
+ #
153
+ def set_variant_template
154
+ request.variant = :mobile if request.user_agent =~ /iPad/
155
+ end
156
+
157
+ def resource_options options
158
+ options.merge! params.except( "id", "controller", "action" )
159
+ options = (options.empty? ? "" : "?" + options.collect{ |k,v| "#{k}=#{v}" }.join("&"))
160
+ end
161
+
162
+ #
163
+ # find the resources collection
164
+ def find_resources options
165
+
166
+ params[:ids] ||= []
167
+ params[:ids] << params[:id] unless params[:id].nil?
168
+
169
+ if params[:ids].compact.any?
170
+ policy_scope(resource_class).where(id: params[:ids].compact.split(",").flatten)
171
+ else
172
+ if params[:q].nil? or params[:q]=="" #or params[:q]=="undefined"
173
+ r = parent? ? parent.send(resource_name) : (resource_class.nil? ? nil : policy_scope(resource_class))
174
+ else
175
+ r = find_resources_queried options
176
+ end
177
+
178
+ return r #if params[:print_list]
179
+ # params[:perpage] ||= 20
180
+ # (params[:format].nil? or params[:format]=='html') ? r.page(params[:page]).per(params[:perpage]) : r
181
+ end
182
+
183
+ end
184
+
185
+ #
186
+ # find queried resources collection - implement on each controller to customize
187
+ # raise an exception
188
+ def find_resources_queried options
189
+ case params[:f]
190
+ when nil
191
+ if parent?
192
+ policy_scope(resource_class).tags_included?( params[:q].split(" ") ).where( options )
193
+ else
194
+ policy_scope(resource_class).tags_included?( params[:q].split(" ") )
195
+ end
196
+ else
197
+ policy_scope(resource_class)
198
+ end
199
+ end
200
+ #
201
+ #
202
+ # /employees/1/teams
203
+ # /employees/1/teams/5
204
+ # /employees/1/teams/5/attach
205
+ def find_parent
206
+ if params[:parent].nil?
207
+ return nil if (request.path.split("/").size < 4) or (request.path.split("/").size==4 and %w{edit new}.include?( params[:action]))
208
+ dummy, parent_cls, parent_id, resource_cls, resource_id, action = request.path.split("/")
209
+ parent_cls.singularize.classify.constantize.find(parent_id) rescue nil
210
+ else
211
+ params[:parent].constantize.find(params[:parent_id])
212
+ end
213
+ end
214
+ #
215
+ # # /employees/1/teams/new
216
+ # # /employees/1/teams/1/edit
217
+ # # /employees/1/teams/1/delete
218
+ # def manage_parenthood
219
+ # if params[:parent] and params[:parent_id]
220
+ # parent = params[:parent].classify.constantize.find(params[:parent_id])
221
+ # unless parent.blank?
222
+ # case params[:action]
223
+ # when "create"
224
+ # child = eval("@#{resource_class.to_s.underscore}")
225
+ # children = eval("parent.#{resource_name}")
226
+ # children << child
227
+ # when "edit"
228
+ # when "delete"
229
+ # child = eval("@#{resource_class.to_s.underscore}")
230
+ # children = eval("parent.#{resource_name}")
231
+ # children >> child
232
+ # end
233
+ # end
234
+ # end
235
+ # end
236
+ #
237
+ #
238
+
239
+ def scoop_from_error e
240
+ logger.debug "AbstractResourcesController##{params[:action]}: #{e.class}"
241
+ case e.class.to_s
242
+ when "Pundit::NotAuthorizedError"
243
+ flash.now[:error] = flash[:error] = t('.fail.authorized', resource: resource)
244
+ result = false
245
+ status = 401
246
+ when "ActiveRecord::StatementInvalid" # Mysql2::Error
247
+ flash.now[:error] = flash[:error] = t('fail.mysql_error', mysql: e.to_s)
248
+ result= false
249
+ status = 409
250
+ else
251
+ flash.now[:error] = flash[:error] = "An error occured - please refer to log for details!"
252
+ render head: 412
253
+ end
254
+
255
+
256
+ respond_to do |format|
257
+ case params[:action]
258
+ when 'new'
259
+ format.html { flash.keep(:error) ; redirect_to resources_url }
260
+ format.js { render layout: false, status: status, locals: { result: result} }
261
+ format.json { render json: resources, status: status }
262
+ when 'create'
263
+ format.html { render :new }
264
+ format.js { render layout: false, status: status, locals: { result: result} }
265
+ format.json { render json: resource.errors, status: status }
266
+ when 'show'
267
+ format.html { flash.keep(:error) ; redirect_to resources_url }
268
+ format.js { render layout: false, status: status, locals: { result: result} }
269
+ format.json { render json: resources, status: status }
270
+ when 'edit'
271
+ format.html { flash.keep(:error) ; redirect_to resources_url }
272
+ format.js { render layout: false, status: status, locals: { result: result} }
273
+ format.json { render json: resources, status: status }
274
+ when 'update'
275
+ format.html { render :edit }
276
+ format.js { render layout: false, status: status, locals: { result: result} }
277
+ format.json { render json: resource.errors, status: status }
278
+ when 'index', 'destroy'
279
+ # we should render index - but an error here will not make us happy
280
+ # format.html { render :index }
281
+ #
282
+ format.html { redirect_to root_path, alert: flash[:error] }
283
+ format.js { render layout: false, status: status, locals: { result: result} }
284
+ format.json { render json: resources, status: status }
285
+ end
286
+ end
287
+
288
+ end
289
+
290
+ end