Security News
38% of CISOs Fear They’re Not Moving Fast Enough on AI
CISOs are racing to adopt AI for cybersecurity, but hurdles in budgets and governance may leave some falling behind in the fight against cyber threats.
Using Rails engines extensively, we needed a way to customize behavior for implementations of the platform. Rails provides a great mechanism for views and assets, but doesn't offer any functionality to handle controller/model/lib overriding/customizing. The suggested mechanism in the documentation is class_eval
or ActiveSupport::Concern. Our preferred method for this is module prepending, which is cleaner than class_eval
in that it avoids alias method chaining and becomes part of the ancestor chain.
We also want junior developers to be able to jump in and be productive ASAP - not necessarily requiring they learn the techniques of class_eval
to fix a bug or get a simple task done. Yes, we educate and promote this as the developer grows, but we want the barriers to contribution as low as possible.
We like the ActiveSupport::Concern
API, so this library mimics the API of ActiveSupport::Concern
and layers on top some niceties for the specific task of customizing a Rails engine. Also, we don't like having to store decorated behavior in a separate directory (like https://github.com/parndt/decorators). Storing decorations in the same place as new classes makes it much easier to see the overall picture of how the engine has been customized/extended in one shot.
Say we have a class in an engine like so:
# in ecommerce/app/models/ecommerce/product.rb
module Ecommerce
class Product < ApplicationRecord
def price
skus.first.price
end
end
end
Rails::Decorators
allows customizing this class like so:
# in Rails.root/app/models/ecommerce/product.decorator
module Ecommerce
decorate Product do
decorated do
# Class methods may be called here. Evaluates after prepending module.
attr_writer :on_sale
end
class_methods do
# Methods defined here extend/decorate static methods on the
# decorated class.
def sorts
super + ['discount_rate']
end
end
# Methods defined here extend/decorate instance methods on the
# decorated class.
def price
result = super
result *= discount_rate if on_sale?
result
end
end
end
Rails::Decorators
achieves this in a manner similar to ActiveSupport::Concern
- it dynamically creates a module out of the block passed, and then prepends that into the original class. The above is equivalent to (note that this would need to be required using require_dependency
as well):
# in Rails.root/app/models/ecommerce/product_decorator.rb
module Ecommerce
class Product
module Decorator
module ClassMethods
# Methods defined here extend/decorate static methods on the
# decorated class.
def sorts
super + ['discount_rate']
end
end
# Methods defined here extend/decorate instance methods on the
# decorated class.
def price
result = super
result *= discount_rate if on_sale?
result
end
end
end
Product.send(:prepend, Product::Decorator)
Product.singleton_class.send(:prepend, Product::Decorator::ClassMethods)
Product.class_eval do
# Class methods may be called here. Evaluates after prepending module.
attr_writer :on_sale
end
end
You can also decorate more than one class at a time:
# in Rails.root/app/models/ecommerce/navigable.decorator
module Ecommerce
decorate Product, Category, Page do
def generate_slug
# my custom logic here
end
end
end
Other engines may want to namespace their customizations so as not to collide with further customizations:
# in ecommerce_blog/app/models/ecommerce/product.decorator
module Ecommerce
decorate Product, with: 'blog' do
def blog_entries
BlogEntry.for_product(id)
end
end
end
It is strongly suggested you update your editor of choice to use Ruby syntax highlighting on *.decorator files.
Add this line to your application's Gemfile:
gem 'rails-decorators'
And then execute:
$ bundle
Or install it yourself as:
$ gem install rails-decorators
Contribution directions go here.
The gem is available as open source under the terms of the MIT License.
FAQs
Unknown package
We found that rails-decorators 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
CISOs are racing to adopt AI for cybersecurity, but hurdles in budgets and governance may leave some falling behind in the fight against cyber threats.
Research
Security News
Socket researchers uncovered a backdoored typosquat of BoltDB in the Go ecosystem, exploiting Go Module Proxy caching to persist undetected for years.
Security News
Company News
Socket is joining TC54 to help develop standards for software supply chain security, contributing to the evolution of SBOMs, CycloneDX, and Package URL specifications.