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
@@ -0,0 +1,10 @@
|
|
1
|
+
module SweetActions
|
2
|
+
module ControllerConcerns
|
3
|
+
def action_missing(action_name)
|
4
|
+
factory = ActionFactory.new(self, action_name)
|
5
|
+
action = factory.build_action
|
6
|
+
action.perform_action
|
7
|
+
render status: action.response_code, json: action.response_data
|
8
|
+
end
|
9
|
+
end
|
10
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
module SweetActions
|
2
|
+
class DestroyAction < ApiAction
|
3
|
+
include RestConcerns
|
4
|
+
include AuthorizationConcerns
|
5
|
+
|
6
|
+
private
|
7
|
+
|
8
|
+
def action
|
9
|
+
@resource = set_resource
|
10
|
+
authorize
|
11
|
+
destroy
|
12
|
+
serialize
|
13
|
+
end
|
14
|
+
|
15
|
+
def destroy
|
16
|
+
raise "destroy method must be implemented in #{self.class.name} class since it inherits from DestroyAction"
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,47 @@
|
|
1
|
+
module SweetActions
|
2
|
+
module RestConcerns
|
3
|
+
include RestSerializerConcerns
|
4
|
+
|
5
|
+
attr_reader :resource_name, :resource
|
6
|
+
|
7
|
+
private
|
8
|
+
|
9
|
+
def resource_name
|
10
|
+
path_parameters[:resource_name]
|
11
|
+
end
|
12
|
+
|
13
|
+
def set_resource
|
14
|
+
raise "set_resource method must be implemented in #{self.class.name} class since it includes RestConcerns"
|
15
|
+
end
|
16
|
+
|
17
|
+
def resource
|
18
|
+
return @resource if defined?("@resource")
|
19
|
+
raise "@resource must be set for #{self.class.name} since it includes RestConcerns"
|
20
|
+
end
|
21
|
+
|
22
|
+
def resource_class
|
23
|
+
resource_name.constantize
|
24
|
+
end
|
25
|
+
|
26
|
+
def resource_decanter
|
27
|
+
decanter_class_name = "#{resource_class.to_s.classify}Decanter"
|
28
|
+
begin
|
29
|
+
decanter_class_name.constantize
|
30
|
+
rescue
|
31
|
+
raise "The following Decanter was not found: #{decanter_class_name} and is required for create and update actions"
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
def resource_params
|
36
|
+
@resource_params ||= resource_decanter.decant(params[singular_key])
|
37
|
+
end
|
38
|
+
|
39
|
+
def plural_key
|
40
|
+
resource_class.name.underscore.pluralize
|
41
|
+
end
|
42
|
+
|
43
|
+
def singular_key
|
44
|
+
resource_class.name.underscore
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
@@ -0,0 +1,54 @@
|
|
1
|
+
module SweetActions
|
2
|
+
module RestSerializerConcerns
|
3
|
+
private
|
4
|
+
|
5
|
+
def root_key
|
6
|
+
raise "root_key method must be implemented in #{self.class.name} since it includes RestSerializerConcerns"
|
7
|
+
end
|
8
|
+
|
9
|
+
def serialize
|
10
|
+
return serialize_destroyed_resource if destroyed?
|
11
|
+
|
12
|
+
{
|
13
|
+
type: root_key,
|
14
|
+
attributes: serialized_attributes
|
15
|
+
}
|
16
|
+
end
|
17
|
+
|
18
|
+
def serialize_destroyed_resource
|
19
|
+
{ root_key => {} }
|
20
|
+
end
|
21
|
+
|
22
|
+
def serialize_errors
|
23
|
+
{
|
24
|
+
errors: {
|
25
|
+
singular_key => map_base_to__error(errors.messages)
|
26
|
+
}
|
27
|
+
}
|
28
|
+
end
|
29
|
+
|
30
|
+
def errors
|
31
|
+
resource.respond_to?(:errors) && resource.errors
|
32
|
+
end
|
33
|
+
|
34
|
+
def serialized_attributes
|
35
|
+
return resource unless serialized_resource
|
36
|
+
serialized_resource.serializer_instance
|
37
|
+
end
|
38
|
+
|
39
|
+
def serialized_resource
|
40
|
+
return nil unless Object.const_defined?('ActiveModelSerializers')
|
41
|
+
@serialized_resource ||= begin
|
42
|
+
ActiveModelSerializers::SerializableResource.new(resource, serializer_options)
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
def serializer_options
|
47
|
+
{}
|
48
|
+
end
|
49
|
+
|
50
|
+
def destroyed?
|
51
|
+
resource.respond_to?(:destroyed?) && resource.destroyed?
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
@@ -0,0 +1,40 @@
|
|
1
|
+
def create_sweet_action(method, path, action, options = {})
|
2
|
+
to = options.fetch(:to, "sweet_actions##{action}")
|
3
|
+
|
4
|
+
valid_methods = %i[get post put delete]
|
5
|
+
raise 'not a valid method' unless valid_methods.include?(method.to_sym)
|
6
|
+
args = { to: to }.merge(options)
|
7
|
+
send(method, path, args)
|
8
|
+
end
|
9
|
+
|
10
|
+
def create_sweet_actions(resource, options = {})
|
11
|
+
path = options.fetch(:path, '/')
|
12
|
+
namespace = options.fetch(:namespace, nil)
|
13
|
+
singular = resource.to_s.singularize
|
14
|
+
resource_class = singular.classify
|
15
|
+
actions = %i[collect show create update destroy]
|
16
|
+
only = options.fetch(:only, actions)
|
17
|
+
base_path = "#{path}#{resource}"
|
18
|
+
|
19
|
+
options = options.merge(resource_name: resource_class, namespace: namespace)
|
20
|
+
|
21
|
+
if only.include?(:collect) || only.include?(:index)
|
22
|
+
create_sweet_action(:get, base_path, :collect, options)
|
23
|
+
end
|
24
|
+
|
25
|
+
if only.include?(:show)
|
26
|
+
create_sweet_action(:get, "#{base_path}/:id", :show, options)
|
27
|
+
end
|
28
|
+
|
29
|
+
if only.include?(:create)
|
30
|
+
create_sweet_action(:post, base_path, :create, options)
|
31
|
+
end
|
32
|
+
|
33
|
+
if only.include?(:update)
|
34
|
+
create_sweet_action(:put, "#{base_path}/:id", :update, options)
|
35
|
+
end
|
36
|
+
|
37
|
+
if only.include?(:destroy)
|
38
|
+
create_sweet_action(:delete, "#{base_path}/:id", :destroy, options)
|
39
|
+
end
|
40
|
+
end
|
@@ -0,0 +1,51 @@
|
|
1
|
+
module SweetActions
|
2
|
+
module SaveConcerns
|
3
|
+
include AuthorizationConcerns
|
4
|
+
|
5
|
+
def action
|
6
|
+
@resource = set_resource
|
7
|
+
authorize
|
8
|
+
validate_and_save ? success : failure
|
9
|
+
end
|
10
|
+
|
11
|
+
def root_key
|
12
|
+
singular_key
|
13
|
+
end
|
14
|
+
|
15
|
+
def validate_and_save
|
16
|
+
valid? && save
|
17
|
+
end
|
18
|
+
|
19
|
+
def valid?
|
20
|
+
true
|
21
|
+
end
|
22
|
+
|
23
|
+
def save
|
24
|
+
raise "save method must be implemented by #{self.class.name} since it includes SaveConcerns"
|
25
|
+
end
|
26
|
+
|
27
|
+
def success
|
28
|
+
after_save
|
29
|
+
serialize
|
30
|
+
end
|
31
|
+
|
32
|
+
def failure
|
33
|
+
after_fail
|
34
|
+
@response_code = '422'
|
35
|
+
serialize_errors
|
36
|
+
end
|
37
|
+
|
38
|
+
def after_save
|
39
|
+
# hook
|
40
|
+
end
|
41
|
+
|
42
|
+
def after_fail
|
43
|
+
# hook
|
44
|
+
end
|
45
|
+
|
46
|
+
def map_base_to__error(error_obj)
|
47
|
+
error_obj[:_error] = error_obj.delete(:base) if error_obj.key? :base
|
48
|
+
error_obj
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
Binary file
|
@@ -0,0 +1,36 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require 'sweet_actions/version'
|
5
|
+
|
6
|
+
Gem::Specification.new do |spec|
|
7
|
+
spec.name = "sweet_actions"
|
8
|
+
spec.version = SweetActions::VERSION
|
9
|
+
spec.authors = ["Ryan Francis"]
|
10
|
+
spec.email = ["ryan@launchpadlab.com"]
|
11
|
+
|
12
|
+
spec.summary = %q{A more object oriented approach to controller actions}
|
13
|
+
spec.description = %q{Each controller action is its own class, making it possible to abstract tasks like authorization, deserialization, serialization, and callbacks.}
|
14
|
+
spec.homepage = "https://github.com/launchpadlab/sweet_actions"
|
15
|
+
spec.license = "MIT"
|
16
|
+
|
17
|
+
# Prevent pushing this gem to RubyGems.org. To allow pushes either set the 'allowed_push_host'
|
18
|
+
# to allow pushing to a single host or delete this section to allow pushing to any host.
|
19
|
+
if spec.respond_to?(:metadata)
|
20
|
+
spec.metadata['allowed_push_host'] = "https://rubygems.org"
|
21
|
+
else
|
22
|
+
raise "RubyGems 2.0 or newer is required to protect against " \
|
23
|
+
"public gem pushes."
|
24
|
+
end
|
25
|
+
|
26
|
+
spec.files = `git ls-files -z`.split("\x0").reject do |f|
|
27
|
+
f.match(%r{^(test|spec|features)/})
|
28
|
+
end
|
29
|
+
spec.bindir = "exe"
|
30
|
+
spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
|
31
|
+
spec.require_paths = ["lib"]
|
32
|
+
|
33
|
+
spec.add_development_dependency "bundler", "~> 1.14"
|
34
|
+
spec.add_development_dependency "rake", "~> 10.0"
|
35
|
+
spec.add_development_dependency "rspec", "~> 3.0"
|
36
|
+
end
|
metadata
ADDED
@@ -0,0 +1,139 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: sweet_actions
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.4
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Ryan Francis
|
8
|
+
autorequire:
|
9
|
+
bindir: exe
|
10
|
+
cert_chain: []
|
11
|
+
date: 2017-08-30 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: bundler
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - "~>"
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '1.14'
|
20
|
+
type: :development
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - "~>"
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '1.14'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: rake
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - "~>"
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '10.0'
|
34
|
+
type: :development
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - "~>"
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '10.0'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: rspec
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - "~>"
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '3.0'
|
48
|
+
type: :development
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - "~>"
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '3.0'
|
55
|
+
description: Each controller action is its own class, making it possible to abstract
|
56
|
+
tasks like authorization, deserialization, serialization, and callbacks.
|
57
|
+
email:
|
58
|
+
- ryan@launchpadlab.com
|
59
|
+
executables: []
|
60
|
+
extensions: []
|
61
|
+
extra_rdoc_files: []
|
62
|
+
files:
|
63
|
+
- ".gitignore"
|
64
|
+
- ".rspec"
|
65
|
+
- ".travis.yml"
|
66
|
+
- Gemfile
|
67
|
+
- LICENSE.txt
|
68
|
+
- PITCHME.md
|
69
|
+
- PITCHME.yaml
|
70
|
+
- README.md
|
71
|
+
- Rakefile
|
72
|
+
- bin/console
|
73
|
+
- bin/setup
|
74
|
+
- lib/.DS_Store
|
75
|
+
- lib/generators/.DS_Store
|
76
|
+
- lib/generators/rails/.DS_Store
|
77
|
+
- lib/generators/rails/actions_generator.rb
|
78
|
+
- lib/generators/rails/resource_override.rb
|
79
|
+
- lib/generators/rails/templates/.DS_Store
|
80
|
+
- lib/generators/rails/templates/collect.rb.erb
|
81
|
+
- lib/generators/rails/templates/create.rb.erb
|
82
|
+
- lib/generators/rails/templates/destroy.rb.erb
|
83
|
+
- lib/generators/rails/templates/show.rb.erb
|
84
|
+
- lib/generators/rails/templates/update.rb.erb
|
85
|
+
- lib/generators/sweet_actions/install_generator.rb
|
86
|
+
- lib/generators/sweet_actions/templates/collect_action.rb
|
87
|
+
- lib/generators/sweet_actions/templates/create_action.rb
|
88
|
+
- lib/generators/sweet_actions/templates/destroy_action.rb
|
89
|
+
- lib/generators/sweet_actions/templates/initializer.rb
|
90
|
+
- lib/generators/sweet_actions/templates/show_action.rb
|
91
|
+
- lib/generators/sweet_actions/templates/update_action.rb
|
92
|
+
- lib/sweet_actions.rb
|
93
|
+
- lib/sweet_actions/.DS_Store
|
94
|
+
- lib/sweet_actions/action_factory.rb
|
95
|
+
- lib/sweet_actions/api_action.rb
|
96
|
+
- lib/sweet_actions/authorization_concerns.rb
|
97
|
+
- lib/sweet_actions/collect_action.rb
|
98
|
+
- lib/sweet_actions/configuration.rb
|
99
|
+
- lib/sweet_actions/controller_concerns.rb
|
100
|
+
- lib/sweet_actions/create_action.rb
|
101
|
+
- lib/sweet_actions/destroy_action.rb
|
102
|
+
- lib/sweet_actions/exceptions.rb
|
103
|
+
- lib/sweet_actions/railtie.rb
|
104
|
+
- lib/sweet_actions/read_concerns.rb
|
105
|
+
- lib/sweet_actions/rest_concerns.rb
|
106
|
+
- lib/sweet_actions/rest_serializer_concerns.rb
|
107
|
+
- lib/sweet_actions/routes_helpers.rb
|
108
|
+
- lib/sweet_actions/save_concerns.rb
|
109
|
+
- lib/sweet_actions/show_action.rb
|
110
|
+
- lib/sweet_actions/update_action.rb
|
111
|
+
- lib/sweet_actions/version.rb
|
112
|
+
- sweet_actions-0.1.0.gem
|
113
|
+
- sweet_actions.gemspec
|
114
|
+
homepage: https://github.com/launchpadlab/sweet_actions
|
115
|
+
licenses:
|
116
|
+
- MIT
|
117
|
+
metadata:
|
118
|
+
allowed_push_host: https://rubygems.org
|
119
|
+
post_install_message:
|
120
|
+
rdoc_options: []
|
121
|
+
require_paths:
|
122
|
+
- lib
|
123
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
124
|
+
requirements:
|
125
|
+
- - ">="
|
126
|
+
- !ruby/object:Gem::Version
|
127
|
+
version: '0'
|
128
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
129
|
+
requirements:
|
130
|
+
- - ">="
|
131
|
+
- !ruby/object:Gem::Version
|
132
|
+
version: '0'
|
133
|
+
requirements: []
|
134
|
+
rubyforge_project:
|
135
|
+
rubygems_version: 2.6.13
|
136
|
+
signing_key:
|
137
|
+
specification_version: 4
|
138
|
+
summary: A more object oriented approach to controller actions
|
139
|
+
test_files: []
|