effective_resources 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.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: c009d7e3ecdcedf8d6237f147268f258cb1def21
4
+ data.tar.gz: e626bb392c315716a7f8805a0ec43fee41aa2543
5
+ SHA512:
6
+ metadata.gz: 22d8d71e5e635de0dac748d98a99cabbcefb1a741c0705489de856274a5ce0903e355ffb0d10de19751e6e8132988dc785a1ba8ef077f47c319d232a95888b48
7
+ data.tar.gz: f37f7fec56ae18b3dd8e86f0cc6ff43127fd0a7150231cd2be2e43a7e42456ca8ba5d0db6089de3fcd31e7aff698ba9b28973e48c884b70d1e108447edbfbf67
data/MIT-LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ Copyright 2017 Code and Effect Inc.
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,74 @@
1
+ # Effective Resources
2
+
3
+ Make your controller an effective resource controller.
4
+
5
+ Implements the 7 RESTful actions as a one-liner on any controller.
6
+
7
+ ## Getting Started
8
+
9
+ Add to your Gemfile:
10
+
11
+ ```ruby
12
+ gem 'effective_resources'
13
+ ```
14
+
15
+ Run the bundle command to install it:
16
+
17
+ ```console
18
+ bundle install
19
+ ```
20
+
21
+ ## Usage
22
+
23
+ Add to your contoller:
24
+
25
+ ```ruby
26
+ class PostsController < ApplicationController
27
+ include Effective::CrudController
28
+
29
+ def post_params
30
+ params.require(:post).permit(:id, :title, :body)
31
+ end
32
+
33
+ end
34
+ ```
35
+
36
+ ## What it does
37
+
38
+ Implements the 7 RESTful actions: `index`, `new`, `create`, `show`, `edit`, `update`, `destroy`.
39
+
40
+ # Loads an appropriate `@post` type instance
41
+ # Sets a `@page_title` (effective_pages).
42
+ # Calls authorize as per the configured `EffectiveResources.authorization_method` (flow through to CanCan or Pundit)
43
+ # Does the create/update save
44
+ # Sets a `flash[:success]` and redirects on success, or sets a `flash.now[:danger]` and renders on error.
45
+
46
+ ## Helpers
47
+
48
+ ### simple_form_submit
49
+
50
+ Call `simple_form_submit(f)` like follows:
51
+
52
+ ```haml
53
+ = simple_form_for(post) do |f|
54
+ = f.input :title
55
+ = f.input :body
56
+
57
+ = simple_form_submit(f)
58
+ ```
59
+
60
+ to render 3 submit buttons: `Save`, `Save and Continue`, and `Save and Add New`.
61
+
62
+ ## License
63
+
64
+ MIT License. Copyright [Code and Effect Inc.](http://www.codeandeffect.com/)
65
+
66
+ ## Contributing
67
+
68
+ 1. Fork it
69
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
70
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
71
+ 4. Push to the branch (`git push origin my-new-feature`)
72
+ 5. Bonus points for test coverage
73
+ 6. Create new Pull Request
74
+
@@ -0,0 +1,158 @@
1
+ module Effective
2
+ module CrudController
3
+ extend ActiveSupport::Concern
4
+
5
+ included do
6
+ end
7
+
8
+ module ClassMethods
9
+ end
10
+
11
+ def index
12
+ @page_title ||= resource_name.pluralize.titleize
13
+ EffectiveResources.authorized?(self, :index, resource_class)
14
+
15
+ self.resources ||= resource_class.all
16
+ @datatable ||= resource_datatable_class.new(params[:scopes])
17
+ end
18
+
19
+ def new
20
+ self.resource ||= resource_class.new
21
+
22
+ @page_title ||= "New #{resource_name.titleize}"
23
+ EffectiveResources.authorized?(self, :new, resource)
24
+ end
25
+
26
+ def create
27
+ self.resource ||= resource_class.new(send(resource_params_method_name))
28
+
29
+ @page_title ||= "New #{resource_name.titleize}"
30
+ EffectiveResources.authorized?(self, :create, resource)
31
+
32
+ if resource.save
33
+ flash[:success] = "Successfully created #{resource_name}"
34
+ redirect_to(resource_redirect_path)
35
+ else
36
+ flash.now[:danger] = "Unable to create #{resource_name}: #{resource.errors.full_messages.to_sentence}"
37
+ render :new
38
+ end
39
+ end
40
+
41
+ def show
42
+ self.resource ||= resource_class.find(params[:id])
43
+
44
+ @page_title ||= resource.to_s
45
+ EffectiveResources.authorized?(self, :show, resource)
46
+ end
47
+
48
+ def edit
49
+ self.resource ||= resource_class.find(params[:id])
50
+
51
+ @page_title ||= "Edit #{resource}"
52
+ EffectiveResources.authorized?(self, :edit, resource)
53
+ end
54
+
55
+ def update
56
+ self.resource ||= resource_class.find(params[:id])
57
+
58
+ @page_title = "Edit #{resource}"
59
+ EffectiveResources.authorized?(self, :update, resource)
60
+
61
+ if resource.update_attributes(send(resource_params_method_name))
62
+ flash[:success] = "Successfully updated #{resource_name}"
63
+ redirect_to(resource_redirect_path)
64
+ else
65
+ flash.now[:danger] = "Unable to update #{resource_name}: #{resource.errors.full_messages.to_sentence}"
66
+ render :edit
67
+ end
68
+ end
69
+
70
+ def destroy
71
+ self.resource = resource_class.find(params[:id])
72
+
73
+ @page_title = "Destroy #{resource}"
74
+ EffectiveResources.authorized?(self, :destroy, resource)
75
+
76
+ if resource.destroy
77
+ flash[:success] = "Successfully deleted #{resource_name}"
78
+ else
79
+ flash[:danger] = "Unable to delete #{resource_name}: #{resource.errors.full_messages.to_sentence}"
80
+ end
81
+
82
+ request.referer.present? ? redirect_to(request.referer) : redirect_to(resources_path)
83
+ end
84
+
85
+ protected
86
+
87
+ def resource # @thing
88
+ instance_variable_get("@#{resource_name}")
89
+ end
90
+
91
+ def resource=(instance)
92
+ instance_variable_set("@#{resource_name}", instance)
93
+ end
94
+
95
+ def resources # @things
96
+ send(:instance_variable_get, "@#{resource_name.pluralize}")
97
+ end
98
+
99
+ def resources=(instance)
100
+ send(:instance_variable_set, "@#{resource_name.pluralize}", instance)
101
+ end
102
+
103
+ def resource_class # Thing
104
+ resource_namespaced_name.classify.safe_constantize || resource_name.classify.constantize
105
+ end
106
+
107
+ def resource_name # 'thing'
108
+ controller_path.split('/').last.singularize
109
+ end
110
+
111
+ def resource_namespace # ['admin']
112
+ controller_path.split('/')[0..-2].presence
113
+ end
114
+
115
+ def resource_namespaced_name # 'Admin::Thing'
116
+ ([resource_namespace, resource_name].compact * '/').singularize.camelize
117
+ end
118
+
119
+ def resource_datatable_class
120
+ if defined?(EffectiveDatatables)
121
+ "#{resource_namespaced_name.pluralize}Datatable".safe_constantize ||
122
+ "#{resource_name.pluralize.camelize}Datatable".safe_constantize ||
123
+ "Effective::Datatables::#{resource_namespaced_name.pluralize}".safe_constantize ||
124
+ "Effective::Datatables::#{resource_name.pluralize.camelize}".safe_constantize
125
+ end
126
+ end
127
+
128
+ def resource_params_method_name
129
+ ["#{resource_name}_params", "#{resource_name.pluralize}_params", 'permitted_params'].find { |name| respond_to?(name, true) } || 'params'
130
+ end
131
+
132
+ def resources_path # /admin/things
133
+ send([resource_namespace, resource_name.pluralize, 'path'].compact.join('_'))
134
+ end
135
+
136
+ def new_resource_path # /admin/things/new
137
+ send(['new', resource_namespace, resource_name, 'path'].compact.join('_'))
138
+ end
139
+
140
+ def edit_resource_path # /admin/things/1/edit
141
+ send(['edit', resource_namespace, resource_name, 'path'].compact.join('_'), resource)
142
+ end
143
+
144
+ def resource_path # /admin/things/1
145
+ send([resource_namespace, resource_name, 'path'].compact.join('_'), resource)
146
+ end
147
+
148
+ def resource_redirect_path
149
+ case params[:commit].to_s
150
+ when 'Save' ; edit_resource_path
151
+ when 'Save and Continue' ; resources_path
152
+ when 'Save and Add New' ; new_resource_path
153
+ else resource_path
154
+ end
155
+ end
156
+
157
+ end
158
+ end
@@ -0,0 +1,13 @@
1
+ module EffectiveResourcesHelper
2
+
3
+ def simple_form_submit(form)
4
+ content_tag(:p, class: 'text-right') do
5
+ [
6
+ form.button(:submit, 'Save', data: { disable_with: 'Saving...' }),
7
+ form.button(:submit, 'Save and Continue', data: { disable_with: 'Saving...' }),
8
+ form.button(:submit, 'Save and Add New', data: { disable_with: 'Saving...' })
9
+ ].join(' ').html_safe
10
+ end
11
+ end
12
+
13
+ end
@@ -0,0 +1,17 @@
1
+ unless defined?(Effective::AccessDenied)
2
+ module Effective
3
+ class AccessDenied < StandardError
4
+ attr_reader :action, :subject
5
+
6
+ def initialize(message = nil, action = nil, subject = nil)
7
+ @message = message
8
+ @action = action
9
+ @subject = subject
10
+ end
11
+
12
+ def to_s
13
+ @message || I18n.t(:'unauthorized.default', :default => 'Access Denied')
14
+ end
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,22 @@
1
+ EffectiveResources.setup do |config|
2
+ # Authorization Method
3
+ #
4
+ # This method is called by all controller actions with the appropriate action and resource
5
+ # If the method returns false, an Effective::AccessDenied Error will be raised (see README.md for complete info)
6
+ #
7
+ # Use via Proc (and with CanCan):
8
+ # config.authorization_method = Proc.new { |controller, action, resource| can?(action, resource) }
9
+ #
10
+ # Use via custom method:
11
+ # config.authorization_method = :my_authorization_method
12
+ #
13
+ # And then in your application_controller.rb:
14
+ #
15
+ # def my_authorization_method(action, resource)
16
+ # current_user.is?(:admin)
17
+ # end
18
+ #
19
+ # Or disable the check completely:
20
+ # config.authorization_method = false
21
+ config.authorization_method = Proc.new { |controller, action, resource| authorize!(action, resource) } # CanCanCan
22
+ end
@@ -0,0 +1,20 @@
1
+ require 'effective_resources/engine'
2
+ require 'effective_resources/version'
3
+
4
+ module EffectiveResources
5
+
6
+ # The following are all valid config keys
7
+ mattr_accessor :authorization_method
8
+
9
+ def self.setup
10
+ yield self
11
+ end
12
+
13
+ def self.authorized?(controller, action, resource)
14
+ if authorization_method.respond_to?(:call) || authorization_method.kind_of?(Symbol)
15
+ raise Effective::AccessDenied.new() unless (controller || self).instance_exec(controller, action, resource, &authorization_method)
16
+ end
17
+ true
18
+ end
19
+
20
+ end
@@ -0,0 +1,13 @@
1
+ module EffectiveResources
2
+ class Engine < ::Rails::Engine
3
+ engine_name 'effective_resources'
4
+
5
+ config.autoload_paths += Dir["#{config.root}/lib/"]
6
+
7
+ # Set up our default configuration options.
8
+ initializer 'effective_resources.defaults', before: :load_config_initializers do |app|
9
+ eval File.read("#{config.root}/config/effective_resources.rb")
10
+ end
11
+
12
+ end
13
+ end
@@ -0,0 +1,3 @@
1
+ module EffectiveResources
2
+ VERSION = '0.1.0'.freeze
3
+ end
@@ -0,0 +1,14 @@
1
+ module EffectiveResources
2
+ module Generators
3
+ class InstallGenerator < Rails::Generators::Base
4
+ desc 'Creates an EffectiveResources initializer in your application.'
5
+
6
+ source_root File.expand_path('../../templates', __FILE__)
7
+
8
+ def copy_initializer
9
+ template ('../' * 3) + 'config/effective_resources.rb', 'config/initializers/effective_resources.rb'
10
+ end
11
+
12
+ end
13
+ end
14
+ end
metadata ADDED
@@ -0,0 +1,68 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: effective_resources
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Code and Effect
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2017-01-10 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: rails
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ">="
18
+ - !ruby/object:Gem::Version
19
+ version: 3.2.0
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ">="
25
+ - !ruby/object:Gem::Version
26
+ version: 3.2.0
27
+ description: Make any controller an effective resource controller.
28
+ email:
29
+ - info@codeandeffect.com
30
+ executables: []
31
+ extensions: []
32
+ extra_rdoc_files: []
33
+ files:
34
+ - MIT-LICENSE
35
+ - README.md
36
+ - app/controllers/concerns/effective/crud_controller.rb
37
+ - app/helpers/effective_resources_helper.rb
38
+ - app/models/effective/access_denied.rb
39
+ - config/effective_resources.rb
40
+ - lib/effective_resources.rb
41
+ - lib/effective_resources/engine.rb
42
+ - lib/effective_resources/version.rb
43
+ - lib/generators/effective_resources/install_generator.rb
44
+ homepage: https://github.com/code-and-effect/effective_resources
45
+ licenses:
46
+ - MIT
47
+ metadata: {}
48
+ post_install_message:
49
+ rdoc_options: []
50
+ require_paths:
51
+ - lib
52
+ required_ruby_version: !ruby/object:Gem::Requirement
53
+ requirements:
54
+ - - ">="
55
+ - !ruby/object:Gem::Version
56
+ version: '0'
57
+ required_rubygems_version: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - ">="
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ requirements: []
63
+ rubyforge_project:
64
+ rubygems_version: 2.4.5.1
65
+ signing_key:
66
+ specification_version: 4
67
+ summary: Make any controller an effective resource controller.
68
+ test_files: []