Looking for some new & interesting gems to try?
Then have a look at dry-rb, a set of gems that bring solutions to common problems. Dry-rb is composed of over 18 Ruby gems that can work together or by themselves.
Some of these gems include:
- dry-initializer
- dry-struct
- dry-validations
- dry-events
- dry-transaction
In this post, you’ll learn about 3 of these gems so you can get a taste of what dry-rb has to offer!
How to Create Better Structs With dry-struct
A Ruby Struct is a kind of object that you can create from the Struct class, but they have some limitations.
For example:
You can create a struct with a number of missing arguments & get no complaints from Ruby.
With the dry-struct
gem you can create stricter structs.
Here’s how:
require 'dry-struct' module Types include Dry::Types.module end class Video < Dry::Struct attribute :title, Types::String attribute :views, Types::Views attribute :comments, Types::Array end Video.new(title: "abc", views: 10, comments: [])
Now if you miss one of the attributes, you get this error:
[Video.new] :comments is missing in Hash input
Not the most user-friendly error message, but it gets things done.
You can create your own types & add constraints to them:
module Types include Dry::Types.module Age = Integer.constrained(gt: 0) end
This "gt" means "greater than".
So Age
must be an integer greater than 0.
Can you have default values?
Yes, here's how:
module Types include Dry::Types.module Name = String.default('') end
There is a shorter version for creating Dry structs, which resembles regular Ruby structs.
Example:
Book = Dry::Struct(title: Dry::Types["string"]) Book.new(title: "Computer Science 101")
Implementing the Observer Pattern With dry-events
The Observer design pattern is when one source publishes an update to many listeners, this could be a news update, stock alerts, new message in a group chat, etc.
It's a common pattern.
Ruby includes an observable module that helps you implement this.
But dry-events
is another option.
You can create a publisher like this:
require 'dry/events/publisher' class Blog include Dry::Events::Publisher[:blog] register_event('article.published') register_event('article.upated') end
Now:
Any class can register itself to receive these events when they happen.
Here's how:
class Reader def on_article_published(event) puts "New article published: #{event[:title]}" end def on_article_updated(event) puts "Article has been updated: #{event[:title]}" end end blog = Blog.new reader = Reader.new blog.subscribe(reader)
You can broadcast an event with the publish
method:
blog.publish('article.published', title: 'How to Use The dry-events Gem')
One thing I noticed with this gem is that if you subscribe or publish an event that doesn't exist it will fail silently.
Dependency Injection With dry-auto_inject
What is a dependency?
A dependency is something that a class needs to work, like other objects & classes.
You can create these objects directly in your class...
Or you can use dependency injection.
Dependency injection is when the dependencies are "injected" into the class. In other words, they are passed in as parameters.
Example:
require 'faraday' class GitHubAPI def initialize(http_client = Faraday.new) @http_client = http_client end end
Doing this allows you to control the dependency & make testing easier.
Now:
dry-auto_inject
creates these objects for you. All you have to do is declare what dependencies are needed.
In this example Fruit
depends on Store
:
require 'dry/auto_inject' class Store def bananas puts 'Have some organic bananas!' end end Import = Dry::AutoInject({ 'store' => Store.new }) class Fruit include Import['store'] def eat store.bananas end end fruit = Fruit.new fruit.eat
You have to say how the object is created:
Import = Dry::AutoInject({ 'store' => Store.new })
And make it available for the class:
include Import['store']
Then you can create a Fruit
with a different Store
like this:
Fruit.new(store: MyStore.new)
You don't need a gem to use dependency injection, but it's interesting to see another way to do it.
Summary
You have learned about dry-rb, a set of interesting Ruby gems that you can use to solve specific design problems in your code.
Now it's your turn to practice & give this a try!
Thanks for reading.
It’s great!!! Please write article about new gem dry-schema (https://github.com/dry-rb/dry-schema), differents from dry-validation (https://github.com/dry-rb/dry-validation), how this gems can used in rails app, for example where i can place dry-schema in rails?
Hi,
Thanks for reading & leaving a comment! I haven’t looked into dry-schema yet, but it seems like you can find the documentation here.