mime_actor 0.4.0 → 0.5.2

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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 7f099315434127b3b7044aad85eca2f69664521753dd339af0f8b6829e0ef8dc
4
- data.tar.gz: f8d79ab0813b5f3d63a8a991c9a0f39f328cc67e991738a21030a7fcaee3eae6
3
+ metadata.gz: a7a720ab3e8cb8cb9c3ba54e47f7b05272d0420ec2ba3194b739b07c4dee9e9b
4
+ data.tar.gz: 1f359c60a87f39261fbcab5b6f0d153a79a4fd936439e7d8d749970a544c2a59
5
5
  SHA512:
6
- metadata.gz: ba11f403b7031051f9d56577a34dc7b2c63906aabe7b6e663fa9ef87225e0a9334d3a9f08eabbefc5f85a201c8ed73e231e4c616a2f0bac7d1a37e05607a4e81
7
- data.tar.gz: 3f21642e23e14ef5a175740e7916618ed3fb99b8395197d7b5239abe0ead83d0ea498ed1b6f63fa4830e9803e2bc16c04f32c43b25544bcf57c9986f2999f528
6
+ metadata.gz: d40d5fdd4e8b21f4a1b1e30e26ed66f653caef5f0ee0696cc844a2dfe355eeda95be62911b2973293f0c97c048d06c0b9e7a2ed0ae2733223340433a2abab9cb
7
+ data.tar.gz: 16ff17b8a4c96a99a396e7d417ad4f5f0fa50dce86f82b5071f35e88994f6bc4155e9bdd85dc59c3ef1902ed60282267c946f9509478566132155d71097dc8bf
data/.hound.yml ADDED
@@ -0,0 +1,2 @@
1
+ rubocop:
2
+ enabled: false
data/.rubocop.yml CHANGED
@@ -7,6 +7,7 @@ AllCops:
7
7
  NewCops: enable
8
8
  Exclude:
9
9
  - bin/*
10
+ - vendor/**/*
10
11
 
11
12
  Style/Documentation:
12
13
  Enabled: false
data/README.md CHANGED
@@ -1,25 +1,96 @@
1
1
  # mime_actor
2
2
 
3
- [![Gem Version](https://badge.fury.io/rb/mime_actor.png)](https://badge.fury.io/rb/mime_actor)
4
- [![Build](https://github.com/ryancyq/mime_actor/actions/workflows/build.yml/badge.svg)](https://github.com/ryancyq/mime_actor/actions/workflows/build.yml)
3
+ [![Version][rubygems_badge]][rubygems]
4
+ [![CI][ci_badge]][ci_workflows]
5
+ [![Coverage][coverage_badge]][coverage]
6
+ [![Maintainability][maintainability_badge]][maintainability]
5
7
 
6
- Action rendering and rescue with mime type via configuration in actionpack
8
+ Action Render + Rescue handlers for different MIME types in Rails
7
9
 
8
- ## Installation
10
+ ## Usage
9
11
 
10
- Install the gem and add to the application's Gemfile by executing:
12
+ MimeActor allows you to do something like below:
13
+ ```rb
14
+ class EventsController < ActionController::Base
15
+ # AbstractController::Callbacks here to load model with params
16
+ before_action only: :index { @events = Event.all }
17
+ before_action only: [:show, :update] { @event = Event.find(params.require(:event_id)) }
11
18
 
12
- $ bundle add mime_actor
19
+ compose_scene :html, :json, on: :index
20
+ compose_scene :html, :json, on: [:show, :update]
13
21
 
14
- If bundler is not being used to manage dependencies, install the gem by executing:
22
+ rescue_actor_from ActiveRecord::RecordNotFound, format: :json do |ex|
23
+ render status: :bad_request, json: { error: "Resouce not found" }
24
+ end
25
+
26
+ rescue_actor_from ActiveRecord::RecordNotFound, format: :html, action: :show do |ex|
27
+ redirect_to events_path
28
+ end
29
+
30
+ def index_html
31
+ @event_categories = EventCategory.all
32
+ render :index # render html using @events and @event_categories
33
+ end
34
+
35
+ def index_json
36
+ render json: @events # render json using #as_json
37
+ end
38
+
39
+ def show_html
40
+ render :show # render html using @event
41
+ end
42
+
43
+ def update_html
44
+ redirect_to event_path(@event.id) # redirect to show upon sucessful update
45
+ rescue ActiveRecord::RecordNotFound
46
+ render :edit
47
+ end
48
+
49
+ def show_json
50
+ render json: @event # render json using #as_json
51
+ end
52
+
53
+ def update_json
54
+ # ...
55
+ render json: @event # render json using #as_json
56
+ end
57
+ end
58
+ ```
59
+
60
+ Seems useful? See the [Comparison][doc_comparison] on how it can improve your existing code
61
+
62
+ ## Features
15
63
 
16
- $ gem install mime_actor
64
+ - Action customisation for [ActionController][doc_action_controller] per MIME type
65
+ - Customisation are deduplicated automatically when configured multiple times
66
+ - Flexible rescue handler definition for the combination of Action/MIME type or both
67
+ - Built on top of [ActionController::Metal::MimeResponds][doc_action_controller_mime_responds]
68
+ - Fully compatible with other [ActionController][doc_action_controller] functionalities
17
69
 
18
- ## Getting Started
70
+ ## Documentation
71
+
72
+ You can find the documentation on [RubyDoc][doc_mime_actor].
73
+
74
+ ## Requirements
75
+
76
+ - Ruby: MRI 3.1+
77
+ - Rails: 5.0+
78
+
79
+ ## Installation
80
+
81
+ Install the gem and add to the application's Gemfile by executing:
82
+ ```sh
83
+ bundle add mime_actor
84
+ ```
85
+
86
+ If bundler is not being used to manage dependencies, install the gem by executing:
87
+ ```sh
88
+ gem install mime_actor
89
+ ```
19
90
 
20
91
  ## Development
21
92
 
22
- After checking out the repo, run `bin/setup` to install dependencies. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
93
+ After checking out the repo, run `bin/setup` to install dependencies. Then, run `bundle exec rake spec` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
23
94
 
24
95
  To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and the created tag, and push the `.gem` file to [rubygems.org](https://rubygems.org).
25
96
 
@@ -29,3 +100,17 @@ Please see [LICENSE](https://github.com/ryancyq/mime_actor/blob/main/LICENSE) fo
29
100
  ## Contributing
30
101
 
31
102
  Bug reports and pull requests are welcome on GitHub at https://github.com/ryancyq/mime_actor.
103
+
104
+ [rubygems_badge]: https://img.shields.io/gem/v/mime_actor.svg
105
+ [rubygems]: https://rubygems.org/gems/mime_actor
106
+ [ci_badge]: https://github.com/ryancyq/mime_actor/actions/workflows/build.yml/badge.svg
107
+ [ci_workflows]: https://github.com/ryancyq/mime_actor/actions/workflows/
108
+ [coverage_badge]: https://codecov.io/gh/ryancyq/mime_actor/graph/badge.svg?token=4C091RHXC3
109
+ [coverage]: https://codecov.io/gh/ryancyq/mime_actor
110
+ [maintainability_badge]: https://api.codeclimate.com/v1/badges/06689606dc3f3945dc1b/maintainability
111
+ [maintainability]: https://codeclimate.com/github/ryancyq/mime_actor/maintainability
112
+
113
+ [doc_mime_actor]: https://rubydoc.info/gems/mime_actor
114
+ [doc_action_controller]: https://rubydoc.info/gems/actionpack/ActionController/Metal
115
+ [doc_action_controller_mime_responds]: https://rubydoc.info/gems/actionpack/ActionController/MimeResponds
116
+ [doc_comparison]: https://github.com/ryancyq/mime_actor/blob/main/COMPARE.md
data/lib/COMPARE.md ADDED
@@ -0,0 +1,124 @@
1
+ ## Comparison in Rails
2
+
3
+ ### MIME Rendering
4
+
5
+ #### before
6
+ ```rb
7
+ class EventsController < ActionController::Base
8
+ def index
9
+ @events = Event.all
10
+ respond_to do |format|
11
+ format.html do
12
+ @event_categories = EventCategory.all
13
+
14
+ # render html using @events and @event_categories
15
+ render :index
16
+ end
17
+ format.json { render json: @events } # render json using #as_json
18
+ end
19
+ end
20
+ end
21
+ ```
22
+ #### after
23
+ ```rb
24
+ class EventsController < ActionController::Base
25
+ include MimeActor::Action
26
+
27
+ before_action only: :index { @events = Event.all }
28
+
29
+ # dynamically defines the action method according to on: argument
30
+ compose_scene :html, :json, on: :index
31
+
32
+ def index_html
33
+ @event_categories = EventCategory.all
34
+
35
+ # render html using @events and @event_categories
36
+ render :index
37
+ end
38
+
39
+ def index_json
40
+ # render json using #as_json
41
+ render json: @events
42
+ end
43
+ end
44
+ ```
45
+
46
+ ### MIME Rescuing
47
+
48
+ #### before
49
+ ```rb
50
+ class EventsController < ActionController::Base
51
+ # AbstractController::Callbacks here to load model with params
52
+ before_action only: [:show, :update] { @event = Event.find(params.require(:event_id)) }
53
+
54
+ rescue_from ActiveRecord::RecordNotFound do |ex|
55
+ case action_name.to_s
56
+ when "show"
57
+ respond_to do |format|
58
+ format.html { redirect_to events_path } # redirect to index
59
+ format.json { render status: :bad_request, json: { error: ex.message } }
60
+ end
61
+ when "update"
62
+ respond_to do |format|
63
+ format.html { render :edit }
64
+ format.json { render status: :bad_request, json: { error: ex.message } }
65
+ end
66
+ else
67
+ raise ex # re-raise since we are not handling it
68
+ end
69
+ end
70
+
71
+ def show
72
+ respond_to do |format|
73
+ format.html { render :show } # render html using @event
74
+ format.json { render json: @event } # render json using #as_json
75
+ end
76
+ end
77
+
78
+ def update
79
+ # ...
80
+ respond_to do |format|
81
+ format.html { redirect_to event_path(@event.id) } # redirect to show upon sucessful update
82
+ format.json { render json: @event } # render json using #as_json
83
+ end
84
+ end
85
+ end
86
+ ```
87
+ #### after
88
+ ```rb
89
+ class EventsController < ActionController::Base
90
+ include MimeActor::Action
91
+
92
+ # AbstractController::Callbacks here to load model with params
93
+ before_action only: [:show, :update] { @event = Event.find(params.require(:event_id)) }
94
+
95
+ compose_scene :html, :json, on: [:show, :update]
96
+
97
+ rescue_actor_from ActiveRecord::RecordNotFound, format: :json do |ex|
98
+ render status: :bad_request, json: { error: ex.message }
99
+ end
100
+
101
+ rescue_actor_from ActiveRecord::RecordNotFound, format: :html, action: :show do |ex|
102
+ redirect_to events_path
103
+ end
104
+
105
+ def show_html
106
+ render :show # render html using @event
107
+ end
108
+
109
+ def update_html
110
+ redirect_to event_path(@event.id) # redirect to show upon sucessful update
111
+ rescue ActiveRecord::RecordNotFound
112
+ render :edit
113
+ end
114
+
115
+ def show_json
116
+ render json: @event # render json using #as_json
117
+ end
118
+
119
+ def update_json
120
+ # ...
121
+ render json: @event # render json using #as_json
122
+ end
123
+ end
124
+ ```
@@ -10,7 +10,13 @@ require "abstract_controller/rendering"
10
10
  require "action_controller/metal/mime_responds"
11
11
 
12
12
  module MimeActor
13
- module Act
13
+ # # MimeActor Action
14
+ #
15
+ # Action is the recommended Module to be included in ActionController.
16
+ #
17
+ # Provides intuitive way of action rendering for a specific MIME type with rescue handlers.
18
+ #
19
+ module Action
14
20
  extend ActiveSupport::Concern
15
21
 
16
22
  include AbstractController::Rendering # required by MimeResponds
@@ -21,12 +27,14 @@ module MimeActor
21
27
  include Rescue
22
28
  include Logging
23
29
 
30
+ ##
31
+ # The core logic where rendering logics are collected as Proc through configuration and passed over to ActionController::MimeResponds
24
32
  def start_scene(action)
25
33
  action = action&.to_sym
26
34
  formats = acting_scenes.fetch(action, Set.new)
27
35
 
28
36
  if formats.empty?
29
- logger.warn { "format is empty, action: #{action}" }
37
+ logger.warn { "format is empty for action :#{action}" }
30
38
  return
31
39
  end
32
40
 
@@ -1,5 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ # :markup: markdown
4
+
3
5
  require "active_support/concern"
4
6
  require "active_support/configurable"
5
7
  require "active_support/isolated_execution_state" # required by active_support/logger
@@ -7,6 +9,9 @@ require "active_support/logger"
7
9
  require "active_support/tagged_logging"
8
10
 
9
11
  module MimeActor
12
+ # # MimeActor Logging
13
+ #
14
+ # Provides a configurable logger.
10
15
  module Logging
11
16
  extend ActiveSupport::Concern
12
17
 
@@ -1,5 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ # :markup: markdown
4
+
3
5
  require "mime_actor/stage"
4
6
  require "mime_actor/validator"
5
7
 
@@ -9,6 +11,10 @@ require "active_support/core_ext/module/attribute_accessors"
9
11
  require "active_support/core_ext/string/inflections"
10
12
 
11
13
  module MimeActor
14
+ # # MimeActor Rescue
15
+ #
16
+ # Simillar to ActionController::Rescue but with additional filtering logic on Action/Format.
17
+ #
12
18
  module Rescue
13
19
  extend ActiveSupport::Concern
14
20
 
@@ -20,6 +26,15 @@ module MimeActor
20
26
  end
21
27
 
22
28
  module ClassMethods
29
+ ##
30
+ # Registers a rescue handler for the given error classes with action/format filter
31
+ #
32
+ # rescue_actor_from StandardError, format: :json, action: :show do |ex|
33
+ # render status: :bad_request, json: { error: ex.message }
34
+ # end
35
+ #
36
+ # rescue_actor_from StandardError, format: :html, with: :handle_html_error
37
+ #
23
38
  def rescue_actor_from(*klazzes, action: nil, format: nil, with: nil, &block)
24
39
  raise ArgumentError, "error filter is required" if klazzes.empty?
25
40
 
@@ -58,6 +73,9 @@ module MimeActor
58
73
  end
59
74
  end
60
75
 
76
+ ##
77
+ # Resolve the error provided with the registered handlers.
78
+ # The handled error will be returned to indicate successful handling
61
79
  def rescue_actor(error, action: nil, format: nil, context: self, visited: [])
62
80
  return if visited.include?(error)
63
81
 
@@ -1,5 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ # :markup: markdown
4
+
3
5
  require "mime_actor/errors"
4
6
  require "mime_actor/validator"
5
7
 
@@ -9,6 +11,15 @@ require "active_support/core_ext/array/wrap"
9
11
  require "active_support/core_ext/module/attribute_accessors"
10
12
 
11
13
  module MimeActor
14
+ # # MimeActor Scene
15
+ #
16
+ # Scene provides configuration for Action + Format definitions
17
+ #
18
+ # compose_scene :html, on: :index
19
+ # compose_scene :html, :json , on: [:index, :show]
20
+ #
21
+ # NOTE: Calling the same action/format multiple times will overwrite previous Action + Format definitions.
22
+ #
12
23
  module Scene
13
24
  extend ActiveSupport::Concern
14
25
 
@@ -19,6 +30,10 @@ module MimeActor
19
30
  end
20
31
 
21
32
  module ClassMethods
33
+ ##
34
+ # Register Action + Format definitions.
35
+ #
36
+ # For each unique action being registered, it will have a corresponding method being defined.
22
37
  def compose_scene(*options)
23
38
  config = options.extract_options!
24
39
  validate!(:formats, options)
@@ -1,5 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ # :markup: markdown
4
+
3
5
  require "mime_actor/errors"
4
6
  require "mime_actor/logging"
5
7
 
@@ -7,6 +9,10 @@ require "active_support/concern"
7
9
  require "active_support/core_ext/module/attribute_accessors"
8
10
 
9
11
  module MimeActor
12
+ # # MimeActor Stage
13
+ #
14
+ # Stage provides helpers for actor lookup and invocation.
15
+ #
10
16
  module Stage
11
17
  extend ActiveSupport::Concern
12
18
 
@@ -17,6 +23,8 @@ module MimeActor
17
23
  end
18
24
 
19
25
  module ClassMethods
26
+ ##
27
+ # Determine if the name belongs to a public instance method excluding methods inherited from ancesstors
20
28
  def actor?(actor_name)
21
29
  # exclude public methods from ancestors
22
30
  found = public_instance_methods(false).include?(actor_name.to_sym)
@@ -27,7 +35,11 @@ module MimeActor
27
35
  found
28
36
  end
29
37
 
38
+ ##
39
+ # Wraps the given block with lambda, rescue any error raised from the block via #rescue_actor if defined, otherwise, error will be re-raised
30
40
  def dispatch_cue(action: nil, format: nil, context: self, &block)
41
+ raise ArgumentError, "block must be provided" unless block_given?
42
+
31
43
  lambda do
32
44
  context.instance_exec(&block)
33
45
  rescue StandardError => e
@@ -36,11 +48,15 @@ module MimeActor
36
48
  end
37
49
  end
38
50
 
51
+ ##
52
+ # Call the actor method if defined, supports passing arguments to the actor method.
53
+ #
54
+ # If a block is given, the result from the actor method will be yieled to the block
39
55
  def cue_actor(actor_name, *args)
40
56
  unless self.class.actor?(actor_name)
41
57
  raise MimeActor::ActorNotFound, actor_name if raise_on_missing_actor
42
58
 
43
- logger.warn { "actor not found, got: #{actor_name}" }
59
+ logger.warn { "actor not found, expected :#{actor_name}" }
44
60
  return
45
61
  end
46
62
 
@@ -1,10 +1,23 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ # :markup: markdown
4
+
3
5
  require "active_support/concern"
4
6
  require "set" # required by mime_type with ruby <= 3.1
5
7
  require "action_dispatch/http/mime_type"
6
8
 
7
9
  module MimeActor
10
+ # # MimeActor Validator
11
+ #
12
+ # Validator provides validation rules for action, format, and rescue handlers by default.
13
+ #
14
+ # # raise error when rule is violated
15
+ # validate!(:action, action_param)
16
+ #
17
+ # # return the error when rule is violated
18
+ # ex = validate_action(action_param)
19
+ # raise ex if error
20
+ #
8
21
  module Validator
9
22
  extend ActiveSupport::Concern
10
23
 
@@ -13,6 +26,8 @@ module MimeActor
13
26
  end
14
27
 
15
28
  module ClassMethods
29
+ ##
30
+ # Raise the error returned by validator if present.
16
31
  def validate!(rule, *args)
17
32
  validator = "validate_#{rule}"
18
33
  raise NameError, "Validator not found, got: #{validator}" unless respond_to?(validator, true)
@@ -21,21 +36,29 @@ module MimeActor
21
36
  raise error if error
22
37
  end
23
38
 
39
+ ##
40
+ # validate :action must be a Symbol
24
41
  def validate_action(unchecked)
25
42
  ArgumentError.new("action must be a Symbol") unless unchecked.is_a?(Symbol)
26
43
  end
27
44
 
45
+ ##
46
+ # validate :actions must be an Array of Symbol
28
47
  def validate_actions(unchecked)
29
48
  rejected = unchecked.reject { |action| action.is_a?(Symbol) }
30
49
  NameError.new("invalid actions, got: #{rejected.join(", ")}") if rejected.size.positive?
31
50
  end
32
51
 
52
+ ##
53
+ # validate :format must be a Symbol + a valid MIME type
33
54
  def validate_format(unchecked)
34
55
  return ArgumentError.new("format must be a Symbol") unless unchecked.is_a?(Symbol)
35
56
 
36
57
  NameError.new("invalid format, got: #{unchecked}") unless scene_formats.include?(unchecked)
37
58
  end
38
59
 
60
+ ##
61
+ # validate :formats must be an Array of Symbol which each of them is a valid MIME type
39
62
  def validate_formats(unchecked)
40
63
  unfiltered = unchecked.to_set
41
64
  filtered = unfiltered & scene_formats
@@ -44,6 +67,8 @@ module MimeActor
44
67
  NameError.new("invalid formats, got: #{rejected.join(", ")}") if rejected.size.positive?
45
68
  end
46
69
 
70
+ ##
71
+ # validate :with or &block must be provided + :with must be a Symbol or Proc
47
72
  def validate_with(unchecked, block)
48
73
  if unchecked.present? && block.present?
49
74
  return ArgumentError.new("provide either the with: keyword argument or a block")
@@ -11,8 +11,8 @@ module MimeActor
11
11
 
12
12
  module VERSION
13
13
  MAJOR = 0
14
- MINOR = 4
15
- BUILD = 0
14
+ MINOR = 5
15
+ BUILD = 2
16
16
  PRE = nil
17
17
 
18
18
  STRING = [MAJOR, MINOR, BUILD, PRE].compact.join(".")
data/lib/mime_actor.rb CHANGED
@@ -1,5 +1,8 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ # :markup: markdown
4
+ # :include: ../README.md
5
+
3
6
  require "mime_actor/version"
4
7
  require "mime_actor/errors"
5
8
 
@@ -8,7 +11,7 @@ require "active_support/dependencies/autoload"
8
11
  module MimeActor
9
12
  extend ActiveSupport::Autoload
10
13
 
11
- autoload :Act
14
+ autoload :Action
12
15
  autoload :Scene
13
16
  autoload :Stage
14
17
  autoload :Rescue
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: mime_actor
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.4.0
4
+ version: 0.5.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Ryan Chang
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2024-06-27 00:00:00.000000000 Z
11
+ date: 2024-06-29 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: actionpack
@@ -59,14 +59,16 @@ executables: []
59
59
  extensions: []
60
60
  extra_rdoc_files: []
61
61
  files:
62
+ - ".hound.yml"
62
63
  - ".rspec"
63
64
  - ".rubocop.yml"
64
65
  - ".ruby-version"
65
66
  - LICENSE
66
67
  - README.md
67
68
  - Rakefile
69
+ - lib/COMPARE.md
68
70
  - lib/mime_actor.rb
69
- - lib/mime_actor/act.rb
71
+ - lib/mime_actor/action.rb
70
72
  - lib/mime_actor/errors.rb
71
73
  - lib/mime_actor/logging.rb
72
74
  - lib/mime_actor/rescue.rb
@@ -102,5 +104,5 @@ requirements: []
102
104
  rubygems_version: 3.5.9
103
105
  signing_key:
104
106
  specification_version: 4
105
- summary: action rendering and rescue with mime type via configuration in actionpack
107
+ summary: Action Render + Rescue handlers for different MIME types in Rails
106
108
  test_files: []