
Security News
Rspack Introduces Rslint, a TypeScript-First Linter Written in Go
Rspack launches Rslint, a fast TypeScript-first linter built on typescript-go, joining in on the trend of toolchains creating their own linters.
Here are other implementations:
See why we decided to implement this differently.
Add gem 'decors'
to your Gemfile
Then run bundle
# Create a new decorator
module DB
class WithinTransaction < ::Decors::DecoratorBase
def call(*)
DB.transaction { super }
end
end
end
# Define the alias on the class/module you want to use it
class Item
define_decorator :WithinTransaction, DB::WithinTransaction
# From now on you can use the decorator to decorate any method/singleton method
WithinTransaction()
def do_stuff_in_db
# do_stuff_in_db within a db transaction
end
WithinTransaction()
def self.do_stuff_in_db
# do_stuff_in_db within a db transaction
end
end
# Create a new decorator
module DbDecorator
class WithinTransaction < ::Decors::DecoratorBase; end
class LogBeforeDbHit < ::Decors::DecoratorBase; end
# define decorator that can be mixed with other classes/modules
define_mixin_decorator :WithinTransaction, WithinTransaction
define_mixin_decorator :LogBeforeDbHit, LogBeforeDbHit
end
class Item
extend DbDecorator
WithinTransaction()
LogBeforeDbHit()
def do_stuff_in_db
# do_stuff_in_db within a db transaction
end
end
Sometimes you want the decorator to modify your method arguments. For example a generic way to define an api that handles pagination and filtering.
module Api
class SimpleApi < ::Decors::DecoratorBase
attr_reader :model_store, :pagination, :filtering
def initialize(*, model_store, pagination:, filtering:)
@model_store = model_store
@pagination = pagination
@filtering = filtering
super
end
def call(this, *)
models, page, per_page = paginate(filter(model_store.all))
super(this, models, page: page, per_page: per_page)
end
...
end
end
class ItemController
SimpleApi(Item, pagination: true, filtering: true)
def index(items, page:, per_page:)
render json: { items: items.map(&:as_json), page: page, per_page: per_page }
end
end
class User
define_decorator :Delay, Async::Delay
Delay(priority: :high)
def delayed_computation(*args, &blk)
# CODE here
end
end
# Is strictly equivalent to
class User
def secret_computation(*args, &blk)
Async::Delay.new(User, User.instance_method(:secret_computation), priority: :high)
.call(self, *args, &blk) do
# CODE here
end
end
end
Method modifiers modify methods, specifically those are class methods which:
The limitation of those are:
with decorator you can do the following
class User
...
Delay(priority: :high)
Retry(3)
DbTransaction()
def secret_computation
# computation inside transaction retried up to 3 times if an error occurs.
# All that performed async
end
end
# VS
class User
...
db_transaction def secret_computation
end
retry_when_failing :secret_computation, 3
handle_async :secret_computation, priority: :high
end
Most of the implementation use the unary operator +@
syntax to define the decorator which leads to a lost reference to the caller instance. This imply a global state of what are the current decorators to apply to the next method definition (which is not always threadsafe depending on the implementation).
Current implementations wasn't handling nested singleton (see https://github.com/getbannerman/decors/issues/2)
Current implementations have a rather large footprint. A class that needs a decorated method have all of its method definition hooked on the method_added
callback. In our case it's only added at the decorator call. And we'll soon support callback removal after method definition.
The obvious drawback of our approach are: The syntax that might be less comprehensive for a new comer, and the namespacing which we handle via aliasing at decorator declaration.
By convention we use ConstantName case for the decorators in order not to mix them with other method call/DSL. This is not enforced and you can have the text case you like.
Note that, this syntax is also used in other gems such as Contract
Copyright (c) 2017 Bannerman, Vivien Meyet
Licensed under the MIT license.
FAQs
Unknown package
We found that decors demonstrated a not healthy version release cadence and project activity because the last version was released a year ago. It has 1 open source maintainer collaborating on the project.
Did you know?
Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.
Security News
Rspack launches Rslint, a fast TypeScript-first linter built on typescript-go, joining in on the trend of toolchains creating their own linters.
Security News
Hacker Demonstrates How Easy It Is To Steal Data From Popular Password Managers
Security News
Oxlint’s new preview brings type-aware linting powered by typescript-go, combining advanced TypeScript rules with native-speed performance.