abstracted 0.0.4
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.envrc +1 -0
- data/.gitignore +8 -0
- data/.rspec +3 -0
- data/.ruby-version +1 -0
- data/Gemfile +14 -0
- data/Gemfile.lock +218 -0
- data/Guardfile +77 -0
- data/MIT-LICENSE +20 -0
- data/README.rdoc +3 -0
- data/Rakefile +15 -0
- data/abstracted.gemspec +51 -0
- data/app/assets/images/abstracted/.keep +0 -0
- data/app/assets/javascripts/abstract_resources.js +39 -0
- data/app/assets/javascripts/abstracted/.keep +0 -0
- data/app/assets/javascripts/crud.js.coffee +49 -0
- data/app/assets/javascripts/initializers.js.coffee +111 -0
- data/app/assets/stylesheets/abstract_resources.css +5 -0
- data/app/assets/stylesheets/abstracted/.keep +0 -0
- data/app/assets/stylesheets/scaffold.css +56 -0
- data/app/controllers/.keep +0 -0
- data/app/controllers/abstract_resources_controller.rb +290 -0
- data/app/controllers/application_controller.rb +22 -0
- data/app/helpers/.keep +0 -0
- data/app/helpers/abstract_resources_helper.rb +26 -0
- data/app/mailers/.keep +0 -0
- data/app/models/.keep +0 -0
- data/app/models/abstract_resource.rb +122 -0
- data/app/models/concerns/roleable.rb +61 -0
- data/app/policies/abstract_resource_policy.rb +58 -0
- data/app/views/.keep +0 -0
- data/app/views/abstract_resources/_default.html.erb +11 -0
- data/app/views/abstract_resources/destroy.js.haml +1 -0
- data/app/views/abstract_resources/edit.html.haml +11 -0
- data/app/views/abstract_resources/index.html.erb +1 -0
- data/app/views/abstract_resources/new.html.haml +12 -0
- data/app/views/abstract_resources/show.html.haml +13 -0
- data/bin/rails +12 -0
- data/config/locales/abstracted.en.yml +20 -0
- data/config/routes.rb +4 -0
- data/lib/abstracted.rb +8 -0
- data/lib/abstracted/engine.rb +19 -0
- data/lib/abstracted/version.rb +3 -0
- data/lib/abstracted_responder.rb +7 -0
- data/lib/tasks/abstracted_tasks.rake +4 -0
- data/spec/controllers/abstract_resources_controller_spec.rb +241 -0
- data/spec/dummy/README.rdoc +28 -0
- data/spec/dummy/Rakefile +6 -0
- data/spec/dummy/app/assets/images/.keep +0 -0
- data/spec/dummy/app/assets/javascripts/application.js +13 -0
- data/spec/dummy/app/assets/stylesheets/application.css +15 -0
- data/spec/dummy/app/controllers/application_controller.rb +5 -0
- data/spec/dummy/app/controllers/concerns/.keep +0 -0
- data/spec/dummy/app/helpers/application_helper.rb +2 -0
- data/spec/dummy/app/mailers/.keep +0 -0
- data/spec/dummy/app/models/.keep +0 -0
- data/spec/dummy/app/models/concerns/.keep +0 -0
- data/spec/dummy/app/models/user.rb +3 -0
- data/spec/dummy/app/views/layouts/application.html.erb +14 -0
- data/spec/dummy/bin/bundle +3 -0
- data/spec/dummy/bin/rails +4 -0
- data/spec/dummy/bin/rake +4 -0
- data/spec/dummy/bin/setup +29 -0
- data/spec/dummy/config.ru +4 -0
- data/spec/dummy/config/application.rb +26 -0
- data/spec/dummy/config/boot.rb +5 -0
- data/spec/dummy/config/database.yml +25 -0
- data/spec/dummy/config/environment.rb +5 -0
- data/spec/dummy/config/environments/development.rb +41 -0
- data/spec/dummy/config/environments/production.rb +79 -0
- data/spec/dummy/config/environments/test.rb +42 -0
- data/spec/dummy/config/initializers/assets.rb +11 -0
- data/spec/dummy/config/initializers/backtrace_silencers.rb +7 -0
- data/spec/dummy/config/initializers/cookies_serializer.rb +3 -0
- data/spec/dummy/config/initializers/filter_parameter_logging.rb +4 -0
- data/spec/dummy/config/initializers/inflections.rb +16 -0
- data/spec/dummy/config/initializers/mime_types.rb +4 -0
- data/spec/dummy/config/initializers/session_store.rb +3 -0
- data/spec/dummy/config/initializers/wrap_parameters.rb +14 -0
- data/spec/dummy/config/locales/en.yml +23 -0
- data/spec/dummy/config/routes.rb +56 -0
- data/spec/dummy/config/secrets.yml +22 -0
- data/spec/dummy/db/development.sqlite3 +0 -0
- data/spec/dummy/db/schema.rb +21 -0
- data/spec/dummy/db/test.sqlite3 +0 -0
- data/spec/dummy/lib/assets/.keep +0 -0
- data/spec/dummy/log/.keep +0 -0
- data/spec/dummy/log/development.log +0 -0
- data/spec/dummy/log/test.log +6229 -0
- data/spec/dummy/public/404.html +67 -0
- data/spec/dummy/public/422.html +67 -0
- data/spec/dummy/public/500.html +66 -0
- data/spec/dummy/public/favicon.ico +0 -0
- data/spec/factories/abstract_resources.rb +6 -0
- data/spec/factories/users.rb +5 -0
- data/spec/features/posts/manage_posts_spec.rb +24 -0
- data/spec/models/abstract_resource_spec.rb +14 -0
- data/spec/rails_helper.rb +114 -0
- data/spec/spec_helper.rb +97 -0
- data/test/integration/abstract_resource_test.rb +7 -0
- metadata +424 -0
@@ -0,0 +1,22 @@
|
|
1
|
+
require 'pundit'
|
2
|
+
class ApplicationController < ActionController::Base
|
3
|
+
# Prevent CSRF attacks by raising an exception.
|
4
|
+
# For APIs, you may want to use :null_session instead.
|
5
|
+
protect_from_forgery with: :exception
|
6
|
+
|
7
|
+
#
|
8
|
+
# Pundit implementation
|
9
|
+
#
|
10
|
+
include Pundit
|
11
|
+
rescue_from Pundit::NotAuthorizedError, with: :user_not_authorized
|
12
|
+
|
13
|
+
private
|
14
|
+
|
15
|
+
def user_not_authorized(exception)
|
16
|
+
policy_name = exception.policy.class.to_s.underscore
|
17
|
+
|
18
|
+
flash[:error] = t '.not_authorized' #t "#{policy_name}.#{exception.query}", scope: "pundit", default: :default
|
19
|
+
redirect_to(request.referrer || "/pages/error", flash: flash)
|
20
|
+
end
|
21
|
+
|
22
|
+
end
|
data/app/helpers/.keep
ADDED
File without changes
|
@@ -0,0 +1,26 @@
|
|
1
|
+
module AbstractResourcesHelper
|
2
|
+
|
3
|
+
#
|
4
|
+
# URL Helpers
|
5
|
+
def edit_resource_url(options={})
|
6
|
+
options[:action] ||= :edit
|
7
|
+
options[:controller] ||= @resource_class.table_name
|
8
|
+
url_for options
|
9
|
+
end
|
10
|
+
|
11
|
+
def resources_url resources=@resources, options={}
|
12
|
+
options[:controller] ||= @resource_class.table_name
|
13
|
+
url_for options
|
14
|
+
end
|
15
|
+
|
16
|
+
|
17
|
+
#
|
18
|
+
# Resource Helpers
|
19
|
+
def resource
|
20
|
+
@resource
|
21
|
+
end
|
22
|
+
|
23
|
+
def resources
|
24
|
+
@resources
|
25
|
+
end
|
26
|
+
end
|
data/app/mailers/.keep
ADDED
File without changes
|
data/app/models/.keep
ADDED
File without changes
|
@@ -0,0 +1,122 @@
|
|
1
|
+
class AbstractResource < ActiveRecord::Base
|
2
|
+
self.abstract_class=true
|
3
|
+
#
|
4
|
+
# include Exceptions
|
5
|
+
# include PrintEngine
|
6
|
+
#
|
7
|
+
# belongs_to :ox
|
8
|
+
# has_many :eventables, as: :eventable
|
9
|
+
#
|
10
|
+
# #
|
11
|
+
# # translate the key
|
12
|
+
# def self.oxt(key, *args)
|
13
|
+
# I18n.t(key, args[0])
|
14
|
+
# end
|
15
|
+
#
|
16
|
+
# def oxt(key, *args)
|
17
|
+
# self.class.oxt(key, args[0])
|
18
|
+
# end
|
19
|
+
#
|
20
|
+
# #
|
21
|
+
# # when implementing searches on models (using params)
|
22
|
+
# def self.find_with_params(params=nil)
|
23
|
+
# all
|
24
|
+
# end
|
25
|
+
#
|
26
|
+
#
|
27
|
+
# def self.logit( log_type, msg )
|
28
|
+
# Rails.logger.send(log_type, "[OXEN] #{Time.now} [#{log_type.to_s}] #{msg}")
|
29
|
+
# end
|
30
|
+
#
|
31
|
+
# def logit( log_type, msg )
|
32
|
+
# Rails.logger.send(log_type, "[OXEN] #{Time.now} [#{log_type.to_s}] #{msg}")
|
33
|
+
# end
|
34
|
+
#
|
35
|
+
#
|
36
|
+
#
|
37
|
+
# # list_title
|
38
|
+
# def list_title
|
39
|
+
# self.respond_to?( "name") ? self.name : "please define list_title on model (#{self.class.to_s})!"
|
40
|
+
# end
|
41
|
+
#
|
42
|
+
# # implement on relevant models
|
43
|
+
# def default_record_template
|
44
|
+
# '/record.html.haml'
|
45
|
+
# end
|
46
|
+
#
|
47
|
+
# def self.default_list_template
|
48
|
+
# 'list.html.haml'
|
49
|
+
# end
|
50
|
+
#
|
51
|
+
# def self.default_label_template
|
52
|
+
# 'label.html.haml'
|
53
|
+
# end
|
54
|
+
#
|
55
|
+
# def print_label options={}
|
56
|
+
# params = {}
|
57
|
+
# params[:print_job] = {}
|
58
|
+
# params[:print_job][:view_template_path] = options[:template] || default_label_template
|
59
|
+
# params[:print_job][:print_driver] = options[:print_driver] || :cab
|
60
|
+
# params[:print_job][:print_format] = options[:print_format] || 'label'
|
61
|
+
# params[:print_job][:paper] = options[:paper] || "Pakkelabel"
|
62
|
+
# params[:printer_name] = options[:printer_name]
|
63
|
+
# params[:user] = options[:user]
|
64
|
+
# self.class.print [self], params
|
65
|
+
# end
|
66
|
+
#
|
67
|
+
# def print_record(options={})
|
68
|
+
# params = {}
|
69
|
+
# params[:print_job] = {}
|
70
|
+
# params[:print_job][:view_template_path] = options[:template] || default_record_template
|
71
|
+
# params[:print_job][:print_driver] = options[:print_driver] || :pdf
|
72
|
+
# params[:print_job][:print_format] = options[:print_format] || 'sheet'
|
73
|
+
# params[:print_job][:paper] = options[:paper] || "A4"
|
74
|
+
# params[:printer_name] = options[:printer_name]
|
75
|
+
# params[:user] = options[:user]
|
76
|
+
# self.class.print [self], params
|
77
|
+
# end
|
78
|
+
#
|
79
|
+
# def self.print_list(options={})
|
80
|
+
# params = {}
|
81
|
+
# params[:print_job] = {}
|
82
|
+
# params[:print_job][:view_template_path] = options[:template] || self.default_list_template
|
83
|
+
# params[:print_job][:print_driver] = options[:print_driver] || :pdf
|
84
|
+
# params[:print_job][:print_format] = options[:print_format] || 'list'
|
85
|
+
# params[:print_job][:paper] = options[:paper] || "A4"
|
86
|
+
# params[:printer_name] = options[:printer_name]
|
87
|
+
# params[:user] = options[:user]
|
88
|
+
# self.print options[:resources], params
|
89
|
+
# end
|
90
|
+
#
|
91
|
+
# # add the child to an association of children
|
92
|
+
# def attach child
|
93
|
+
# case child.class.to_s
|
94
|
+
# when "Event","WageEvent"
|
95
|
+
# Eventable.create( event: child, eventable: self) unless child.eventables.include?( self)
|
96
|
+
# when "Printer"
|
97
|
+
# Printable.create( printer: child, printable: self) unless child.printables.include?( self)
|
98
|
+
# else
|
99
|
+
# children = eval child.class.to_s.underscore.pluralize
|
100
|
+
# children << child
|
101
|
+
# end
|
102
|
+
# end
|
103
|
+
#
|
104
|
+
# # remove the child from an association of children
|
105
|
+
# def detach child
|
106
|
+
# case child.class.to_s
|
107
|
+
# when "Event","WageEvent"
|
108
|
+
# ev = Eventable.where( event: child, eventable: self)
|
109
|
+
# ev.delete_all
|
110
|
+
# when "Printer"
|
111
|
+
# pr = Printable.where( printer: child, printable: self)
|
112
|
+
# pr.delete_all
|
113
|
+
# else
|
114
|
+
# children = eval child.class.to_s.downcase.pluralize
|
115
|
+
# children.delete child
|
116
|
+
# end
|
117
|
+
#
|
118
|
+
#
|
119
|
+
# end
|
120
|
+
|
121
|
+
|
122
|
+
end
|
@@ -0,0 +1,61 @@
|
|
1
|
+
require 'active_support/concern'
|
2
|
+
|
3
|
+
# TODO 05-05-2015 make Roleable work with other resource_class too
|
4
|
+
|
5
|
+
module Roleable
|
6
|
+
extend ActiveSupport::Concern
|
7
|
+
|
8
|
+
included do
|
9
|
+
# has_many :somthing
|
10
|
+
enum role: [:user, :vip, :account_admin, :admin]
|
11
|
+
attr_accessor :max_role
|
12
|
+
after_initialize :set_default_role, :if => :new_record?
|
13
|
+
|
14
|
+
validates_with RoleValidator
|
15
|
+
|
16
|
+
end
|
17
|
+
|
18
|
+
module ClassMethods
|
19
|
+
def policed_roles user
|
20
|
+
User.roles.keys.map {|role| [role.titleize,role] if User.roles[role] <= User.roles[user.role] }.compact
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
# role management
|
25
|
+
# ---------------
|
26
|
+
# enum listing possible roles
|
27
|
+
# max_role setting the model max role to that of the current user - you never can promote anyone above your own level
|
28
|
+
# set_default_role sets the role of a new user
|
29
|
+
#
|
30
|
+
|
31
|
+
class RoleValidator < ActiveModel::Validator
|
32
|
+
attr_accessor :user
|
33
|
+
def validate(record)
|
34
|
+
@user = record
|
35
|
+
Rails.logger.info ("roles: old %s new %s" % [ User.roles[record.previous_version.role], User.roles[record.role] ] ) rescue "no previous role"
|
36
|
+
if max_role_exhausted and old_role_less_than_new
|
37
|
+
record.errors[:role] << I18n.t('.assigned_role_not_allowed')
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
def old_role_less_than_new
|
42
|
+
User.roles[user.previous_version.role] < User.roles[user.role]
|
43
|
+
rescue
|
44
|
+
false
|
45
|
+
end
|
46
|
+
|
47
|
+
def max_role_exhausted
|
48
|
+
User.roles[user.role] > User.roles[user.max_role]
|
49
|
+
rescue
|
50
|
+
false
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
|
55
|
+
|
56
|
+
def set_default_role
|
57
|
+
self.role ||= :user
|
58
|
+
end
|
59
|
+
|
60
|
+
|
61
|
+
end
|
@@ -0,0 +1,58 @@
|
|
1
|
+
class AbstractResourcePolicy
|
2
|
+
class Scope
|
3
|
+
attr_reader :current_user, :scope
|
4
|
+
|
5
|
+
def initialize(user, scope)
|
6
|
+
@current_user = user
|
7
|
+
@scope = scope
|
8
|
+
end
|
9
|
+
|
10
|
+
def resolve
|
11
|
+
scope.all
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
attr_reader :current_user, :model
|
16
|
+
|
17
|
+
def initialize(current_user, model)
|
18
|
+
@current_user = current_user
|
19
|
+
@model = model
|
20
|
+
end
|
21
|
+
|
22
|
+
def index?
|
23
|
+
# @current_user.admin?
|
24
|
+
true
|
25
|
+
end
|
26
|
+
|
27
|
+
def new?
|
28
|
+
# @current_user.admin?
|
29
|
+
true
|
30
|
+
end
|
31
|
+
|
32
|
+
def edit?
|
33
|
+
# @current_user.admin?
|
34
|
+
true
|
35
|
+
end
|
36
|
+
|
37
|
+
def show?
|
38
|
+
# @current_user.admin? or @current_user == @user
|
39
|
+
true
|
40
|
+
end
|
41
|
+
|
42
|
+
def create?
|
43
|
+
# @current_user.admin?
|
44
|
+
true
|
45
|
+
end
|
46
|
+
|
47
|
+
def update?
|
48
|
+
# @current_user.admin?
|
49
|
+
true
|
50
|
+
end
|
51
|
+
|
52
|
+
def destroy?
|
53
|
+
# return false if @current_user == @user
|
54
|
+
# @current_user.admin?
|
55
|
+
true
|
56
|
+
end
|
57
|
+
|
58
|
+
end
|
data/app/views/.keep
ADDED
File without changes
|
@@ -0,0 +1,11 @@
|
|
1
|
+
<%- format = request.format.symbol.to_s %>
|
2
|
+
<hr/>
|
3
|
+
<h4>Explanation:</h4>
|
4
|
+
You 'hit' the '<%= params[:action]%>' action - and got the abstracted view template in response
|
5
|
+
(I'm guessing here: because the <%= params[:controller].pluralize.capitalize %>Controller is wired to inherit from AbstractedController)!
|
6
|
+
<h4>Errand</h4>
|
7
|
+
Add an <%= params[:action]%>.<%= format %>.<templating-language-suffix> file to the folder <%= Rails.root %>/app/views/<%= params[:controller].pluralize %>
|
8
|
+
<h4>Example</h4>
|
9
|
+
<pre>
|
10
|
+
<%= Rails.root %>/app/views/<%= params[:controller].pluralize %>/<strong><%= params[:action]%>.<%= format %>.haml</strong>
|
11
|
+
</pre>
|
@@ -0,0 +1 @@
|
|
1
|
+
= render 'layouts/messages'
|
@@ -0,0 +1,11 @@
|
|
1
|
+
- title = t( '%s.%s.title' % [@resource_class.table_name,params[:action]])
|
2
|
+
- content_for :title do
|
3
|
+
= title
|
4
|
+
|
5
|
+
- @disabled = false
|
6
|
+
|
7
|
+
%h3= title
|
8
|
+
= render 'form'
|
9
|
+
|
10
|
+
.right-align
|
11
|
+
= link_to t( @resource_class.table_name + '.actions.index'), resources_url, class: 'waves-effect waves-light btn'
|
@@ -0,0 +1 @@
|
|
1
|
+
<%= render partial: 'default' %>
|
@@ -0,0 +1,12 @@
|
|
1
|
+
- title = t( '%s.%s.title' % [@resource_class.table_name,params[:action]])
|
2
|
+
- content_for :title do
|
3
|
+
= title
|
4
|
+
|
5
|
+
- @disabled = false
|
6
|
+
|
7
|
+
%h3= title
|
8
|
+
= render 'form'
|
9
|
+
|
10
|
+
.row
|
11
|
+
.right-align
|
12
|
+
= link_to t( @resource_class.table_name + '.actions.index'), resources_url, class: 'waves-effect waves-light btn'
|
@@ -0,0 +1,13 @@
|
|
1
|
+
- content_for :title do
|
2
|
+
= t( @resource_class.table_name + '.show.title')
|
3
|
+
|
4
|
+
- @disabled = true
|
5
|
+
|
6
|
+
%h3= t( @resource_class.table_name + '.show.title')
|
7
|
+
|
8
|
+
= render 'form'
|
9
|
+
|
10
|
+
.row
|
11
|
+
.right-align
|
12
|
+
= link_to t( @resource_class.table_name + '.actions.edit'), edit_resource_url, class: 'waves-effect waves-light btn'
|
13
|
+
= link_to t( @resource_class.table_name + '.actions.index'), resources_url, class: 'waves-effect waves-light btn'
|
data/bin/rails
ADDED
@@ -0,0 +1,12 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
# This command will automatically be run when you run "rails" with Rails 4 gems installed from the root of your application.
|
3
|
+
|
4
|
+
ENGINE_ROOT = File.expand_path('../..', __FILE__)
|
5
|
+
ENGINE_PATH = File.expand_path('../../lib/abstracted/engine', __FILE__)
|
6
|
+
|
7
|
+
# Set up gems listed in the Gemfile.
|
8
|
+
ENV['BUNDLE_GEMFILE'] ||= File.expand_path('../../Gemfile', __FILE__)
|
9
|
+
require 'bundler/setup' if File.exist?(ENV['BUNDLE_GEMFILE'])
|
10
|
+
|
11
|
+
require 'rails/all'
|
12
|
+
require 'rails/engine/commands'
|
@@ -0,0 +1,20 @@
|
|
1
|
+
en:
|
2
|
+
success:
|
3
|
+
created: '%{resource} was created successfully'
|
4
|
+
updated: '%{resource} was updated successfully'
|
5
|
+
deleted: '%{resource} was deleted successfully'
|
6
|
+
|
7
|
+
flash:
|
8
|
+
actions:
|
9
|
+
create:
|
10
|
+
notice: "%{resource_name} was successfully created."
|
11
|
+
update:
|
12
|
+
notice: "%{resource_name} was successfully updated."
|
13
|
+
destroy:
|
14
|
+
notice: "%{resource_name} was successfully destroyed."
|
15
|
+
alert: "%{resource_name} could not be destroyed."
|
16
|
+
alert_html: "<strong>OH NOES!</strong> You did it wrong!"
|
17
|
+
|
18
|
+
# posts:
|
19
|
+
# create:
|
20
|
+
# notice: "Your post was created and will be published soon"
|
data/config/routes.rb
ADDED
data/lib/abstracted.rb
ADDED
@@ -0,0 +1,19 @@
|
|
1
|
+
module Abstracted
|
2
|
+
class Engine < ::Rails::Engine
|
3
|
+
# config.autoload_paths << File.expand_path("../concerns", __FILE__)
|
4
|
+
|
5
|
+
config.generators do |g|
|
6
|
+
g.test_framework :rspec,
|
7
|
+
:fixture => false,
|
8
|
+
:fixtures => true,
|
9
|
+
:view_specs => false,
|
10
|
+
:helper_specs => false,
|
11
|
+
:routing_specs => false,
|
12
|
+
:controller_specs => true,
|
13
|
+
:request_specs => true
|
14
|
+
g.fixture_replacement :factory_girl, :dir => "spec/factories"
|
15
|
+
g.assets false
|
16
|
+
g.helper false
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,7 @@
|
|
1
|
+
class AbstractedResponder < ActionController::Responder
|
2
|
+
include Responders::FlashResponder
|
3
|
+
include Responders::HttpCacheResponder
|
4
|
+
# Redirects resources to the collection path (index action) instead
|
5
|
+
# of the resource path (show action) for POST/PUT/DELETE requests.
|
6
|
+
include Responders::CollectionResponder
|
7
|
+
end
|