
Security News
New Website “Is It Really FOSS?” Tracks Transparency in Open Source Distribution Models
A new site reviews software projects to reveal if they’re truly FOSS, making complex licensing and distribution models easy to understand.
Wait a minute, I thought that was bottled_services?, well nevermind. bottled_decorators are here to make your life easier, and provide decorators that are actually decorators and not just View Objects / View Helpers with the name 'decorator'. bottled_decorators encourage the use of DRY and reusable code by stopping the direct model relation and 'my job is to prepare something for the view' mentality seen in some gems and implementations, and to bring decorators back to what they should be, a reusable and stackable extra layer of functionality to be used anywhere and not just in views. Creating your decorators are also as easy as pie with the botted_decorator generator. All you need to worry about is your method logic, let bottled_decorators do the rest for you!
Add this line to your application's Gemfile:
gem 'bottled_decorators'
And then execute:
$ bundle
Or install it yourself as:
$ gem install bottled_decorators
Creating new decorators is as easy as pie with the BottledDecorator Generator. just add the decorator name, and if you want the decorator methods, to the generator command:
rails g bottled_decorator LargeFoodItem
rails g bottled_decorator PiratizedUser name greeting
Just like that we have two new decorators ready for use, a currently empty decorator for decorating food as large food items, and a decorator with two methods prepared for us, name and greeting, that decorates users with pirate like behaviour.
A possible implementation of the two decorators we generated above could be:
class LargeFoodItem
include BottledDecorator
# A large food item has 50 cents added onto its cost
def cost
super + 50
end
end
class PiratizedUser
include BottledDecorator
# Pirates all dream of being the captain of their own ship
def name
"Cap'n #{super}"
end
# And its a well studied fact that Rum is a pirates poison of choice
def greeting
"Yo ho ho and a bottle of rum!"
end
end
Once generated, the next things to do is decorate loads of stuff!
Unlike some other implementations of decorators (many of which I dare to say are not actually decorators but just View Objects / Helpers that are hijacking the word decorator), BottledDecorators do not use an extension style of decorating. Instead they wrap up our objects in a lovely cosy blanket of decoration:
pirate_user = PiratizedUser.(@user)
# or
@large_burger = LargeFoodItem.(burger)
You can also wrap a collection, to get an Array of decorated objects:
@pirates = PiratizedUser.(@users)
# returns an Array
As can be seen above, this wrapping is done using the decorator class' ::call
method, so a simple .()
will suffice to get the job done, or any other preferred choice of envoking the call method.
Once we have our decorated object, its just a case of invoking your methods:
@user.name
# => "John Hayes-Reed"
@user.age
# => 27
@user = PiratizedUser.(@user)
@user.name
# => "Cap'n John Hayes-Reed"
@user.greeting
# => "Yo ho ho and a bottle of rum!"
# of course we can still access the components original methods as well
@user.age
# => 27
Because BottledDecorators wrap instead of extend, we can also keep wrapping on multiple layers, adding on functionality to overridden methods indefinately, because each layer looks at its own component for its super
, and not the original instance:
class DrunkUser
include BottledDecorator
def name
"#{super}, the drunkard!"
end
def greeting
"#{super} (hiccup)"
end
end
@user.name
# => "John Hayes-Reed"
@user = PiratizedUser.(@user)
@user.name
# => "Cap'n John Hayes-Reed"
@user.greeting
# => "Yo ho ho and a bottle of rum!"
@user = DrunkUser.(@user)
@user.name
# => "Cap'n John Hayes-Reed, the drunkard!"
@user.greeting
# => "Yo ho ho and a bottle of rum! (hiccup)"
Because of this layering ability, we can use a single decorator to represent multiple possible states of objects:
# a regular burger
@burger.cost
# => 100
# a large burger
LargeFoodItem.(@burger).cost
# => 150
# an extra large burger
LargeFoodItem.(LargeFoodItem.(@burger)).cost
# => 200
# SUPERSIIIIIZE
LargeFoodItem.(LargeFoodItem.(LargeFoodItem.(@burger))).cost
# => 250
This can be done with multiple decorators to build up the cost of a whole variety of possibilites:
class WithDrink
include BottledDecorator
def cost
super + 15
end
end
# a regular burger
@burger.cost
# => 100
# with a side order drink
WithDrink.(@burger).cost
# => 115
# a large burger with a side order drink
LargeFoodItem.(WithDrink.(@burger)).cost
# => 165
Currently BottledDecorators come with a few serializer methods and checker methods to add all decorated methods onto the converted object as well, currently supported are #to_json
, #as_json
, #to_h
, #respond_to?
, each of which will drill down through each component layer all the way to the root component to provide / access the whole scope available.
After checking out the repo, run bin/setup
to install dependencies. Then, run rake spec
to run the tests. You can also run bin/console
for an interactive prompt that will allow you to experiment.
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 tags, and push the .gem
file to rubygems.org.
All and any contributions to improve Bottled Decorators and make them useful for as many people as possible are gratefully welcomed. I hope all contributions can keep in line with the philosophy of Bottled Technology, which is to make simple and easy-to-use tools.
Bug reports and pull requests are welcome on GitHub at https://github.com/John-Hayes-Reed/bottled_decorators. This project is intended to be a safe, welcoming space for collaboration, and contributors are expected to adhere to the Contributor Covenant code of conduct.
The gem is available as open source under the terms of the MIT License.
FAQs
Unknown package
We found that bottled_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
A new site reviews software projects to reveal if they’re truly FOSS, making complex licensing and distribution models easy to understand.
Security News
Astral unveils pyx, a Python-native package registry in beta, designed to speed installs, enhance security, and integrate deeply with uv.
Security News
The Latio podcast explores how static and runtime reachability help teams prioritize exploitable vulnerabilities and streamline AppSec workflows.