sweet_actions 0.1.4
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +12 -0
- data/.rspec +2 -0
- data/.travis.yml +5 -0
- data/Gemfile +4 -0
- data/LICENSE.txt +21 -0
- data/PITCHME.md +224 -0
- data/PITCHME.yaml +1 -0
- data/README.md +257 -0
- data/Rakefile +6 -0
- data/bin/console +14 -0
- data/bin/setup +8 -0
- data/lib/.DS_Store +0 -0
- data/lib/generators/.DS_Store +0 -0
- data/lib/generators/rails/.DS_Store +0 -0
- data/lib/generators/rails/actions_generator.rb +21 -0
- data/lib/generators/rails/resource_override.rb +10 -0
- data/lib/generators/rails/templates/.DS_Store +0 -0
- data/lib/generators/rails/templates/collect.rb.erb +11 -0
- data/lib/generators/rails/templates/create.rb.erb +15 -0
- data/lib/generators/rails/templates/destroy.rb.erb +15 -0
- data/lib/generators/rails/templates/show.rb.erb +11 -0
- data/lib/generators/rails/templates/update.rb.erb +11 -0
- data/lib/generators/sweet_actions/install_generator.rb +18 -0
- data/lib/generators/sweet_actions/templates/collect_action.rb +10 -0
- data/lib/generators/sweet_actions/templates/create_action.rb +14 -0
- data/lib/generators/sweet_actions/templates/destroy_action.rb +14 -0
- data/lib/generators/sweet_actions/templates/initializer.rb +9 -0
- data/lib/generators/sweet_actions/templates/show_action.rb +10 -0
- data/lib/generators/sweet_actions/templates/update_action.rb +10 -0
- data/lib/sweet_actions.rb +42 -0
- data/lib/sweet_actions/.DS_Store +0 -0
- data/lib/sweet_actions/action_factory.rb +64 -0
- data/lib/sweet_actions/api_action.rb +63 -0
- data/lib/sweet_actions/authorization_concerns.rb +23 -0
- data/lib/sweet_actions/collect_action.rb +11 -0
- data/lib/sweet_actions/configuration.rb +9 -0
- data/lib/sweet_actions/controller_concerns.rb +10 -0
- data/lib/sweet_actions/create_action.rb +6 -0
- data/lib/sweet_actions/destroy_action.rb +19 -0
- data/lib/sweet_actions/exceptions.rb +5 -0
- data/lib/sweet_actions/railtie.rb +8 -0
- data/lib/sweet_actions/read_concerns.rb +14 -0
- data/lib/sweet_actions/rest_concerns.rb +47 -0
- data/lib/sweet_actions/rest_serializer_concerns.rb +54 -0
- data/lib/sweet_actions/routes_helpers.rb +40 -0
- data/lib/sweet_actions/save_concerns.rb +51 -0
- data/lib/sweet_actions/show_action.rb +9 -0
- data/lib/sweet_actions/update_action.rb +6 -0
- data/lib/sweet_actions/version.rb +3 -0
- data/sweet_actions-0.1.0.gem +0 -0
- data/sweet_actions.gemspec +36 -0
- metadata +139 -0
data/Rakefile
ADDED
data/bin/console
ADDED
@@ -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__)
|
data/bin/setup
ADDED
data/lib/.DS_Store
ADDED
Binary file
|
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
|
Binary file
|
@@ -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,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,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)
|
Binary file
|
@@ -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
|