effective_resources 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
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: []