upframework 0.1.0 → 0.2.3

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 03201d4216dd3b35c2fc0868ab19a0c11f3b98f5e50a3e139934011732604073
4
- data.tar.gz: 90775fb0f00abfae7d19b8b7ee132c456a7dac32ab7de9e26f89799bce1d7b08
3
+ metadata.gz: 1acaf495ed6f2835c25eae1905515573ee647802879f43212ad934f6f3a4a3fb
4
+ data.tar.gz: 670163801f3ead631d142ef5840970833f48c069ba055ed19369a8a9e08fecc7
5
5
  SHA512:
6
- metadata.gz: be618352e1e443df2da7bedbe9b91d54db1acf0d98dbb42f7858568102480a0a847b706644368b840771bd3b6e116469d3d500b766b686ae42228ea5aa8b7e71
7
- data.tar.gz: 2c8395e1c8ef62b1ca8e58b3c6247a2742068cea4f2c3051e189b2a3e1517528d3f9522bcf90be229cb90d64297e0a484d65db86777c3d3816d164fb59946c80
6
+ metadata.gz: e6c44c39aae828c7b62cf450d47fe2d61200cc2e2e48af25c80abd6d3f631c060518b7fc15a64d912a2e3c386487a3f1b32edc6cef5bd808e22e443d5f7c863c
7
+ data.tar.gz: fa64458e28228ee45cac5d922ab848962dc313f8fb6481ffeecc1bd2d549512a73a96c6946922c65ffd57ddab6b43ab86db90120fe79440376fd3d0995f32d3e
data/README.md CHANGED
@@ -1,8 +1,42 @@
1
1
  # Upframework
2
- Short description and motivation.
2
+ Add features on top of Rails, Especially for APIs. This was created to make structural code reusable to other projects (not solving the same problem all over again). And to make the main application less bloated and only contain domain specific code as much as possible.
3
3
 
4
- ## Usage
5
- How to use my plugin.
4
+ #### The following features are available.
5
+ - Creates (create, read, update, destroy) action methods for resources.
6
+ - Has render helpers for API or socket responses. ex. Converting models to its designated serializer.
7
+ - Converts snake case request params (from js standard) to underscore params (ruby standard)
8
+ - Searches layer under app/searches. Usually used for form searches.
9
+ - Services layer under app/services. For single responsibility domain-specific logic code.
10
+ - Exception notifier and API error response handler.
11
+
12
+ ## Basic Usage
13
+ ####Controllers
14
+ ```ruby
15
+ #app/controllers
16
+ class ProjectsController < Upframework::ResourcesController
17
+ end
18
+ ```
19
+
20
+ ####Searches
21
+ ```ruby
22
+ #app/searches
23
+ class ProjectSearch < Upframework::BaseSearch
24
+ end
25
+ ```
26
+
27
+ ####Services
28
+ ```ruby
29
+ #app/services
30
+ class Project::SubmitService < Upframework::BaseService
31
+ end
32
+ ```
33
+
34
+ ####Routes
35
+ app/services
36
+ ```ruby
37
+ #config/routes
38
+ mount Upframework::Engine => /path
39
+ ```
6
40
 
7
41
  ## Installation
8
42
  Add this line to your application's Gemfile:
@@ -1,6 +1,5 @@
1
1
  # frozen_string_literal: true
2
-
3
- module Upframework::CrudExtensions
2
+ module Upframework::CrudEndpoint
4
3
  extend ::ActiveSupport::Concern
5
4
 
6
5
  included do
@@ -0,0 +1,30 @@
1
+ module Upframework
2
+ module ApiExtensions
3
+ extend ::ActiveSupport::Concern
4
+
5
+ included do
6
+ include ::DeviseTokenAuth::Concerns::SetUserByToken
7
+ include ::Upframework::ErrorHandler
8
+ include ::Upframework::TransformParamKeys
9
+ include ::Upframework::ServiceEndpoint
10
+ include ::Upframework::RenderExtensions
11
+
12
+ # need to skip this on non-resource controller
13
+ # > skip_authorize_resource
14
+ authorize_resource unless: :devise_controller?
15
+
16
+ rescue_from CanCan::AccessDenied do |exception|
17
+ respond_to do |format|
18
+ format.json { render json: { success: false, error: exception.message }, status: :forbidden }
19
+ format.html { redirect_to main_app.root_url, alert: exception.message }
20
+ end
21
+ end
22
+
23
+ protected
24
+
25
+ def extra_params
26
+ [] # Override in specific controllers for custom params
27
+ end
28
+ end
29
+ end
30
+ end
@@ -0,0 +1,95 @@
1
+ module Upframework
2
+ class ResourcesController < ApplicationController
3
+ before_action :set_base_resource
4
+
5
+ def show
6
+ base_resource
7
+
8
+ yield if block_given?
9
+ render_serialized base_resource
10
+ end
11
+
12
+ def update
13
+ if base_resource.update(base_resource_params)
14
+ yield if block_given?
15
+ render_serialized base_resource
16
+ else
17
+ render_errors base_resource.errors.full_messages
18
+ end
19
+ end
20
+
21
+ def index
22
+ base_resource
23
+
24
+ yield if block_given?
25
+ render_serialized base_resource, includes: params[:includes]
26
+ end
27
+
28
+ def create
29
+ if base_resource.save
30
+
31
+ yield if block_given?
32
+ render_serialized base_resource
33
+ else
34
+ render_errors base_resource.errors.full_messages
35
+ end
36
+ end
37
+
38
+ def destroy
39
+ base_resource.destroy
40
+ head :no_content
41
+ end
42
+
43
+ private
44
+
45
+ def base_resource
46
+ if params[:id]
47
+ instance_variable_get("@#{base_resource_name}")
48
+ else
49
+ instance_variable_get("@#{base_resource_name.pluralize}")
50
+ end
51
+ end
52
+
53
+ def set_base_resource
54
+ data =
55
+ if params[:id]
56
+ base_resource_class.find(params[:id])
57
+ elsif action_name == 'index'
58
+ base_resource_class.accessible_by(current_ability).where(base_resource_params || {})
59
+ elsif action_name == 'create'
60
+ base_resource_class.new(base_resource_params)
61
+ end
62
+
63
+ resource_name = %w[index create].include?(action_name) \
64
+ ? base_resource_name.pluralize \
65
+ : base_resource_name
66
+
67
+ instance_variable_set("@#{resource_name}", data) if data
68
+ end
69
+
70
+ def base_resource_params
71
+ base_name = base_resource_name
72
+
73
+ base_name = base_name.pluralize unless params.key?(base_name)
74
+
75
+ params.fetch(base_name).permit(*permitted_columns)
76
+ end
77
+
78
+ def permitted_columns
79
+ columns = base_resource_class.accessible_fields_by(accessors)
80
+ columns.concat(extra_params)
81
+ end
82
+
83
+ def accessors
84
+ current_user
85
+ end
86
+
87
+ def base_resource_name
88
+ controller_name.singularize
89
+ end
90
+
91
+ def base_resource_class
92
+ base_resource_name.classify.safe_constantize
93
+ end
94
+ end
95
+ end
@@ -0,0 +1,26 @@
1
+ module Upframework
2
+ class SearchesController < ApplicationController
3
+ skip_authorize_resource
4
+
5
+ def index
6
+ args = { current_ability: current_ability, current_user: current_user }
7
+ args.merge!(permitted_params)
8
+
9
+ resource_scope = search_class.run(args).result
10
+ render_serialized resource_scope
11
+ end
12
+
13
+ private
14
+
15
+ def search_class
16
+ "#{params[:resource].classify}Search".constantize
17
+ end
18
+
19
+ def permitted_params
20
+ excluded_keys = %w[resource format controller action search]
21
+ permitted_keys = params.keys - excluded_keys
22
+
23
+ params.slice(*permitted_keys).permit(permitted_keys)
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,30 @@
1
+ class Upframework::BaseSearch < Upframework::BaseService
2
+ DEFAULT_PAGE = 1
3
+ DEFAULT_PER_PAGE = 12
4
+
5
+ def result
6
+ @model_scope
7
+ end
8
+
9
+ def query(field)
10
+ @model_scope = yield if field.present?
11
+ end
12
+
13
+ def paginate_scope
14
+ return if @model_scope.nil?
15
+
16
+ @model_scope = @model_scope.
17
+ page(@page || DEFAULT_PAGE).
18
+ per(@per_page || DEFAULT_PER_PAGE).
19
+ order(created_at: :desc)
20
+ end
21
+
22
+ module ExecuteWrapper
23
+ def execute
24
+ super
25
+ paginate_scope
26
+ end
27
+ end
28
+
29
+ include ExecuteWrapper
30
+ end
@@ -1,5 +1,5 @@
1
1
  module Upframework
2
- module ServiceActionController
2
+ module ServiceEndpoint
3
3
  extend ::ActiveSupport::Concern
4
4
 
5
5
  included do
@@ -0,0 +1,52 @@
1
+ module Upframework
2
+ class BaseService
3
+ attr_reader :errors
4
+
5
+ class << self
6
+ def run(attributes = {})
7
+ attributes = Hash[attributes.to_h.map { |k, v| [k.to_sym, v] }]
8
+ new(**attributes).tap(&:execute)
9
+ end
10
+ end
11
+
12
+ def initialize(**attributes)
13
+ @errors = []
14
+
15
+ self.class.send(:attr_reader, *attributes.keys)
16
+
17
+ #TODO: Remove. This should be handled on the child class.
18
+ attributes.each do |key, value|
19
+ instance_variable_set("@#{key}", value)
20
+ end
21
+
22
+ post_initialize(**attributes)
23
+ end
24
+
25
+ def post_initialize(**attributes)
26
+ end
27
+
28
+ def execute
29
+ end
30
+
31
+ def result
32
+ end
33
+
34
+ def success?
35
+ @errors.blank?
36
+ end
37
+
38
+ def error?
39
+ @errors.present?
40
+ end
41
+
42
+ def error_messages
43
+ @errors.join('. ')
44
+ end
45
+
46
+ protected
47
+
48
+ def add_error(error)
49
+ @errors << error
50
+ end
51
+ end
52
+ end
@@ -1,3 +1,3 @@
1
1
  Upframework::Engine.routes.draw do
2
- ::Upframework::Services::Routes.load
2
+ get "search", to: "searches#index"
3
3
  end
@@ -1,5 +1,9 @@
1
1
  module Upframework
2
2
  class Engine < ::Rails::Engine
3
3
  isolate_namespace Upframework
4
+
5
+ config.to_prepare do
6
+ ApplicationController.include ::Upframework::ApiExtensions
7
+ end
4
8
  end
5
9
  end
@@ -1,17 +1,26 @@
1
1
  module Upframework
2
2
  module Services
3
3
  module Routes
4
- def self.load
4
+ def self.load(namespace: nil, **options)
5
+ scope_name = namespace
6
+
5
7
  Rails.application.routes.draw do
6
8
  source_path = Rails.root.join('app', 'services')
7
9
 
8
- namespace :api, defaults: { format: 'json' } do
10
+ service_routes = proc do
9
11
  Dir.glob("#{source_path}/*/").map{ |e| File.basename e }.each do |resource|
10
- #TODO: check resource exists in controller
11
- # config to exclude some services in the routes
12
+ # Create a post route for services
13
+ # ex.
14
+ # POST users/service/my_custom_service
12
15
  post "#{resource}/service/:service_name", to: "#{resource}#service"
13
16
  end
14
17
  end
18
+
19
+ if scope_name
20
+ namespace scope_name, defaults: { format: :json }, &service_routes
21
+ else
22
+ service_routes.call
23
+ end
15
24
  end
16
25
  end
17
26
  end
@@ -1,3 +1,3 @@
1
1
  module Upframework
2
- VERSION = '0.1.0'
2
+ VERSION = '0.2.3'
3
3
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: upframework
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0
4
+ version: 0.2.3
5
5
  platform: ruby
6
6
  authors:
7
7
  - jude_cali
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2020-04-02 00:00:00.000000000 Z
11
+ date: 2020-05-26 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rails
@@ -30,6 +30,34 @@ dependencies:
30
30
  - - ">="
31
31
  - !ruby/object:Gem::Version
32
32
  version: 6.0.2.1
33
+ - !ruby/object:Gem::Dependency
34
+ name: cancancan
35
+ requirement: !ruby/object:Gem::Requirement
36
+ requirements:
37
+ - - "~>"
38
+ - !ruby/object:Gem::Version
39
+ version: 3.1.0
40
+ type: :runtime
41
+ prerelease: false
42
+ version_requirements: !ruby/object:Gem::Requirement
43
+ requirements:
44
+ - - "~>"
45
+ - !ruby/object:Gem::Version
46
+ version: 3.1.0
47
+ - !ruby/object:Gem::Dependency
48
+ name: fast_jsonapi
49
+ requirement: !ruby/object:Gem::Requirement
50
+ requirements:
51
+ - - "~>"
52
+ - !ruby/object:Gem::Version
53
+ version: '1.5'
54
+ type: :runtime
55
+ prerelease: false
56
+ version_requirements: !ruby/object:Gem::Requirement
57
+ requirements:
58
+ - - "~>"
59
+ - !ruby/object:Gem::Version
60
+ version: '1.5'
33
61
  description: Rails framework extensions
34
62
  email:
35
63
  - jcalimbas@fullscale.io
@@ -42,16 +70,20 @@ files:
42
70
  - Rakefile
43
71
  - app/assets/config/upframework_manifest.js
44
72
  - app/assets/stylesheets/upframework/application.css
45
- - app/controllers/concerns/upframework/crud_extensions.rb
73
+ - app/controllers/concerns/upframework/crud_endpoint.rb
46
74
  - app/controllers/concerns/upframework/error_handler.rb
47
75
  - app/controllers/concerns/upframework/render_extensions.rb
48
76
  - app/controllers/concerns/upframework/transform_param_keys.rb
49
- - app/controllers/upframework/api_controller.rb
77
+ - app/controllers/upframework/api_extensions.rb
78
+ - app/controllers/upframework/resources_controller.rb
79
+ - app/controllers/upframework/searches_controller.rb
50
80
  - app/helpers/upframework/application_helper.rb
51
81
  - app/jobs/upframework/application_job.rb
52
82
  - app/mailers/upframework/application_mailer.rb
53
83
  - app/models/upframework/application_record.rb
54
- - app/services/concerns/service_action_controller.rb
84
+ - app/searches/upframework/base_search.rb
85
+ - app/services/concerns/upframework/service_endpoint.rb
86
+ - app/services/upframework/base_service.rb
55
87
  - app/views/layouts/upframework/application.html.erb
56
88
  - config/routes.rb
57
89
  - lib/tasks/upframework_tasks.rake
@@ -1,33 +0,0 @@
1
- module Upframework
2
- class ApiController < ::ApplicationController
3
- include ::DeviseTokenAuth::Concerns::SetUserByToken
4
- include ::Upframework::ErrorHandler
5
- include ::Upframework::TransformParamKeys
6
- include ::Upframework::CrudExtensions
7
- include ::Upframework::RenderExtensions
8
- include ::Upframework::ServiceActionController
9
-
10
- before_action :authenticate!
11
-
12
- # need to skip this on non-resource controller
13
- # > skip_authorize_resource
14
- authorize_resource
15
-
16
- rescue_from CanCan::AccessDenied do |exception|
17
- respond_to do |format|
18
- format.json { render json: { success: false, error: exception.message }, status: :forbidden }
19
- format.html { redirect_to main_app.root_url, alert: exception.message }
20
- end
21
- end
22
-
23
- def authenticate!
24
- super || authenticate_user!
25
- end
26
-
27
- protected
28
-
29
- def extra_params
30
- [] # Override in specific controllers for custom params
31
- end
32
- end
33
- end