sweet_actions 0.1.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 (53) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +12 -0
  3. data/.rspec +2 -0
  4. data/.travis.yml +5 -0
  5. data/Gemfile +4 -0
  6. data/LICENSE.txt +21 -0
  7. data/PITCHME.md +224 -0
  8. data/PITCHME.yaml +1 -0
  9. data/README.md +257 -0
  10. data/Rakefile +6 -0
  11. data/bin/console +14 -0
  12. data/bin/setup +8 -0
  13. data/lib/.DS_Store +0 -0
  14. data/lib/generators/.DS_Store +0 -0
  15. data/lib/generators/rails/.DS_Store +0 -0
  16. data/lib/generators/rails/actions_generator.rb +21 -0
  17. data/lib/generators/rails/resource_override.rb +10 -0
  18. data/lib/generators/rails/templates/.DS_Store +0 -0
  19. data/lib/generators/rails/templates/collect.rb.erb +11 -0
  20. data/lib/generators/rails/templates/create.rb.erb +15 -0
  21. data/lib/generators/rails/templates/destroy.rb.erb +15 -0
  22. data/lib/generators/rails/templates/show.rb.erb +11 -0
  23. data/lib/generators/rails/templates/update.rb.erb +11 -0
  24. data/lib/generators/sweet_actions/install_generator.rb +18 -0
  25. data/lib/generators/sweet_actions/templates/collect_action.rb +10 -0
  26. data/lib/generators/sweet_actions/templates/create_action.rb +14 -0
  27. data/lib/generators/sweet_actions/templates/destroy_action.rb +14 -0
  28. data/lib/generators/sweet_actions/templates/initializer.rb +9 -0
  29. data/lib/generators/sweet_actions/templates/show_action.rb +10 -0
  30. data/lib/generators/sweet_actions/templates/update_action.rb +10 -0
  31. data/lib/sweet_actions.rb +42 -0
  32. data/lib/sweet_actions/.DS_Store +0 -0
  33. data/lib/sweet_actions/action_factory.rb +64 -0
  34. data/lib/sweet_actions/api_action.rb +63 -0
  35. data/lib/sweet_actions/authorization_concerns.rb +23 -0
  36. data/lib/sweet_actions/collect_action.rb +11 -0
  37. data/lib/sweet_actions/configuration.rb +9 -0
  38. data/lib/sweet_actions/controller_concerns.rb +10 -0
  39. data/lib/sweet_actions/create_action.rb +6 -0
  40. data/lib/sweet_actions/destroy_action.rb +19 -0
  41. data/lib/sweet_actions/exceptions.rb +5 -0
  42. data/lib/sweet_actions/railtie.rb +8 -0
  43. data/lib/sweet_actions/read_concerns.rb +14 -0
  44. data/lib/sweet_actions/rest_concerns.rb +47 -0
  45. data/lib/sweet_actions/rest_serializer_concerns.rb +54 -0
  46. data/lib/sweet_actions/routes_helpers.rb +40 -0
  47. data/lib/sweet_actions/save_concerns.rb +51 -0
  48. data/lib/sweet_actions/show_action.rb +9 -0
  49. data/lib/sweet_actions/update_action.rb +6 -0
  50. data/lib/sweet_actions/version.rb +3 -0
  51. data/sweet_actions-0.1.0.gem +0 -0
  52. data/sweet_actions.gemspec +36 -0
  53. metadata +139 -0
@@ -0,0 +1,6 @@
1
+ require "bundler/gem_tasks"
2
+ require "rspec/core/rake_task"
3
+
4
+ RSpec::Core::RakeTask.new(:spec)
5
+
6
+ task :default => :spec
@@ -0,0 +1,14 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require "bundler/setup"
4
+ require "sweet_actions"
5
+
6
+ # You can add fixtures and/or initialization code here to make experimenting
7
+ # with your gem easier. You can also use a different console, if you like.
8
+
9
+ # (If you use this, don't forget to add pry to your Gemfile!)
10
+ # require "pry"
11
+ # Pry.start
12
+
13
+ require "irb"
14
+ IRB.start(__FILE__)
@@ -0,0 +1,8 @@
1
+ #!/usr/bin/env bash
2
+ set -euo pipefail
3
+ IFS=$'\n\t'
4
+ set -vx
5
+
6
+ bundle install
7
+
8
+ # Do any other automated setup that you need to do here
Binary file
Binary file
@@ -0,0 +1,21 @@
1
+ module Rails
2
+ module Generators
3
+ class ActionsGenerator < NamedBase
4
+ source_root File.expand_path('../templates', __FILE__)
5
+
6
+ def create_actions_folder
7
+ template 'collect.rb.erb', File.join('app/actions', plural_name, 'collect.rb')
8
+ template 'create.rb.erb', File.join('app/actions', plural_name, 'create.rb')
9
+ template 'destroy.rb.erb', File.join('app/actions', plural_name, 'destroy.rb')
10
+ template 'show.rb.erb', File.join('app/actions', plural_name, 'show.rb')
11
+ template 'update.rb.erb', File.join('app/actions', plural_name, 'update.rb')
12
+ end
13
+
14
+ private
15
+
16
+ def module_name
17
+ plural_name.classify.pluralize
18
+ end
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,10 @@
1
+ require 'rails/generators'
2
+ require 'rails/generators/rails/resource/resource_generator'
3
+
4
+ module Rails
5
+ module Generators
6
+ class ResourceGenerator
7
+ hook_for :decanter, default: true, boolean: true
8
+ end
9
+ end
10
+ end
@@ -0,0 +1,11 @@
1
+ module <%= module_name %>
2
+ class Collect < CollectAction
3
+ # def set_resource
4
+ # resource_class.all
5
+ # end
6
+
7
+ # def authorized?
8
+ # can?(:read, resource) # resource can be a collection
9
+ # end
10
+ end
11
+ end
@@ -0,0 +1,15 @@
1
+ module <%= module_name %>
2
+ class Create < CreateAction
3
+ # def set_resource
4
+ # resource_class.new(resource_params)
5
+ # end
6
+
7
+ # def authorized?
8
+ # can?(:create, resource)
9
+ # end
10
+
11
+ # def save
12
+ # resource.save
13
+ # end
14
+ end
15
+ end
@@ -0,0 +1,15 @@
1
+ module <%= module_name %>
2
+ class Destroy < DestroyAction
3
+ # def set_resource
4
+ # resource_class.find(params[:id])
5
+ # end
6
+
7
+ # def authorized?
8
+ # can?(:destroy, resource)
9
+ # end
10
+
11
+ # def destroy
12
+ # resource.destroy
13
+ # end
14
+ end
15
+ end
@@ -0,0 +1,11 @@
1
+ module <%= module_name %>
2
+ class Show < ShowAction
3
+ # def set_resource
4
+ # resource_class.find(params[:id])
5
+ # end
6
+
7
+ # def authorized?
8
+ # can?(:read, resource)
9
+ # end
10
+ end
11
+ end
@@ -0,0 +1,11 @@
1
+ module <%= module_name %>
2
+ class Update < UpdateAction
3
+ # def set_resource
4
+ # resource_class.find(params[:id])
5
+ # end
6
+
7
+ # def authorized?
8
+ # can?(:update, resource)
9
+ # end
10
+ end
11
+ end
@@ -0,0 +1,18 @@
1
+ module SweetActions
2
+ module Generators
3
+ class InstallGenerator < Rails::Generators::Base
4
+ source_root File.expand_path('../templates', __FILE__)
5
+
6
+ desc 'Creates a Sweet Actions initializer in your application.'
7
+
8
+ def copy_initializer
9
+ copy_file 'initializer.rb', 'config/initializers/sweet_actions.rb'
10
+ copy_file 'collect_action.rb', 'app/actions/collect_action.rb'
11
+ copy_file 'create_action.rb', 'app/actions/create_action.rb'
12
+ copy_file 'destroy_action.rb', 'app/actions/destroy_action.rb'
13
+ copy_file 'show_action.rb', 'app/actions/show_action.rb'
14
+ copy_file 'update_action.rb', 'app/actions/update_action.rb'
15
+ end
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,10 @@
1
+ class CollectAction < SweetActions::CollectAction
2
+ def set_resource
3
+ resource_class.all
4
+ end
5
+
6
+ def authorized?
7
+ # can?(:read, resource)
8
+ false
9
+ end
10
+ end
@@ -0,0 +1,14 @@
1
+ class CreateAction < SweetActions::CreateAction
2
+ def set_resource
3
+ resource_class.new(resource_params)
4
+ end
5
+
6
+ def authorized?
7
+ # can?(:create, resource)
8
+ false
9
+ end
10
+
11
+ def save
12
+ resource.save
13
+ end
14
+ end
@@ -0,0 +1,14 @@
1
+ class DestroyAction < SweetActions::DestroyAction
2
+ def set_resource
3
+ resource_class.find(params[:id])
4
+ end
5
+
6
+ def authorized?
7
+ # can?(:destroy, resource)
8
+ false
9
+ end
10
+
11
+ def destroy
12
+ resource.destroy
13
+ end
14
+ end
@@ -0,0 +1,9 @@
1
+ class SweetActionsController < ApplicationController
2
+ include SweetActions::ControllerConcerns
3
+ end
4
+
5
+ SweetActions.config do |config|
6
+ # REST actions must implement `authorize` method
7
+ # setting to true is the most secure
8
+ config.authorize_rest_requests = true
9
+ end
@@ -0,0 +1,10 @@
1
+ class ShowAction < SweetActions::ShowAction
2
+ def set_resource
3
+ resource_class.find(params[:id])
4
+ end
5
+
6
+ def authorized?
7
+ # can?(:read, resource)
8
+ false
9
+ end
10
+ end
@@ -0,0 +1,10 @@
1
+ class UpdateAction < SweetActions::UpdateAction
2
+ def set_resource
3
+ resource_class.find(params[:id])
4
+ end
5
+
6
+ def authorized?
7
+ # can?(:update, resource)
8
+ false
9
+ end
10
+ end
@@ -0,0 +1,42 @@
1
+ module SweetActions
2
+ class << self
3
+ def configuration
4
+ @config ||= SweetActions::Configuration.new
5
+ end
6
+
7
+ def config
8
+ yield configuration
9
+ end
10
+ end
11
+
12
+ ActiveSupport.run_load_hooks(:sweet_actions, self)
13
+ end
14
+
15
+ # overhead
16
+ require 'sweet_actions/version'
17
+ require 'sweet_actions/configuration'
18
+ require 'sweet_actions/exceptions'
19
+
20
+ # base classes
21
+ require 'sweet_actions/action_factory'
22
+ require 'sweet_actions/api_action'
23
+
24
+ # concerns
25
+ require 'sweet_actions/rest_serializer_concerns'
26
+ require 'sweet_actions/rest_concerns'
27
+ require 'sweet_actions/authorization_concerns'
28
+ require 'sweet_actions/save_concerns'
29
+ require 'sweet_actions/read_concerns'
30
+
31
+ # actions
32
+ require 'sweet_actions/collect_action'
33
+ require 'sweet_actions/create_action'
34
+ require 'sweet_actions/update_action'
35
+ require 'sweet_actions/show_action'
36
+ require 'sweet_actions/destroy_action'
37
+
38
+ # helpers
39
+ require 'sweet_actions/controller_concerns'
40
+ require 'sweet_actions/routes_helpers'
41
+
42
+ require 'sweet_actions/railtie' if defined?(::Rails)
@@ -0,0 +1,64 @@
1
+ module SweetActions
2
+ class ActionFactory
3
+ attr_reader :controller, :resource_name, :action, :namespace
4
+
5
+ def initialize(controller, action_name)
6
+ @controller = controller
7
+ path_parameters = env['action_dispatch.request.path_parameters']
8
+ @resource_name = path_parameters[:resource_name]
9
+ @action = action_name
10
+ @namespace = path_parameters[:namespace]
11
+ end
12
+
13
+ def build_action
14
+ action_class.new(controller)
15
+ end
16
+
17
+ private
18
+
19
+ def env
20
+ controller.request.env
21
+ end
22
+
23
+ def action_class
24
+ klass_name = [namespace, resource_module, action_class_name].compact.join('::')
25
+ return klass_name.constantize if klass_defined?(klass_name)
26
+ default_action
27
+ end
28
+
29
+ def resource_module
30
+ return nil unless resource_name
31
+ resource_name.pluralize
32
+ end
33
+
34
+ def action_class_name
35
+ raise 'action is required to be passed into actionFactory' unless action.present?
36
+ action.to_s.classify
37
+ end
38
+
39
+ def default_action
40
+ modules = namespace.split('::')
41
+ class_found = false
42
+ klass_name = nil
43
+
44
+ until class_found || modules.count == 0
45
+ namespace_to_test = modules.join('::')
46
+ target = "#{namespace_to_test}::Defaults::#{action_class_name}"
47
+ if klass_defined?(target)
48
+ klass_name = target
49
+ class_found = true
50
+ end
51
+ modules.pop
52
+ end
53
+ return klass_name.constantize if klass_name.present?
54
+ "#{action_class_name}Action".constantize
55
+ end
56
+
57
+ def klass_defined?(klass_name)
58
+ klass_name.constantize
59
+ return true
60
+ rescue
61
+ return false
62
+ end
63
+ end
64
+ end
@@ -0,0 +1,63 @@
1
+ module SweetActions
2
+ class ApiAction
3
+ attr_reader :controller, :response_data, :response_code
4
+
5
+ def initialize(controller, options = {})
6
+ @controller = controller
7
+ after_init(options)
8
+ end
9
+
10
+ def perform_action
11
+ run_action = Proc.new do
12
+ @response_data = action
13
+ end
14
+
15
+ debug_mode? ? run_action.call : fail_gracefully(run_action)
16
+ end
17
+
18
+ private
19
+
20
+ def after_init(options); end
21
+
22
+ def fail_gracefully(proc)
23
+ @response_code = '200'
24
+ begin
25
+ proc.call
26
+ rescue Exceptions::NotAuthorized => e
27
+ @response_code = '401'
28
+ @response_data = {
29
+ message: 'not authorized'
30
+ }
31
+ rescue StandardError => e
32
+ @response_code = '500'
33
+ @response_data = {
34
+ server_error: e.message
35
+ }
36
+ end
37
+ end
38
+
39
+ def debug_mode?
40
+ ENV['SWEET_ACTION_DEBUG_MODE'] == true
41
+ end
42
+
43
+ def action
44
+ raise "action method is required for #{self.class.name} because it inherits from ApiAction"
45
+ end
46
+
47
+ def path_parameters
48
+ @path_parameters ||= env['action_dispatch.request.path_parameters']
49
+ end
50
+
51
+ def request
52
+ @request ||= controller.request
53
+ end
54
+
55
+ def params
56
+ @params ||= controller.params
57
+ end
58
+
59
+ def env
60
+ request.env
61
+ end
62
+ end
63
+ end
@@ -0,0 +1,23 @@
1
+ module SweetActions
2
+ module AuthorizationConcerns
3
+ private
4
+
5
+ def authorize?
6
+ SweetActions.configuration.authorize_rest_requests
7
+ end
8
+
9
+ def authorize
10
+ return unless authorize?
11
+ return true if authorized?
12
+ unauthorized
13
+ end
14
+
15
+ def authorized?
16
+ raise "authorized? method is required for the #{self.class.name} action"
17
+ end
18
+
19
+ def unauthorized
20
+ raise Exceptions::NotAuthorized
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,11 @@
1
+ module SweetActions
2
+ class CollectAction < ApiAction
3
+ include ReadConcerns
4
+
5
+ private
6
+
7
+ def root_key
8
+ plural_key
9
+ end
10
+ end
11
+ end