Fish0
The fish doesn't think because the fish knows everything.
Fish0 is the plugin for read-only content websites with MongoDB storage. Works perfect with Rambler&Co CQRS architecture.
Installation
Simply add gem to your Gemfile
gem 'fish0'
Configuration
# config/initializers/fish0.rb
Fish0::Configuration.configure do |config|
config.mongo_uri = 'mongodb://user:password@host_1:27017,replica_host_2:27017/project_db?auth_source=admin'
config.mongo_params = { read: { mode: :secondary } }
end
Models
Inherit your model class from Fish0::Model
and feel the power of the Fish!
With attribute
define your attributes and with primary_key
set your main primary key, e.g. id
, slug
, etc.
# app/models/article.rb
class Article < Fish0::Model
# Define some attributes
attribute :headline, String
attribute :slug, String
attribute :content, Array[Hash]
attribute :published_at, DateTime
primary_key :slug
# ...
end
# app/controllers/articles_controller.rb
class ArticlesController < ApplicationController
# ...
def show
@article = Article.where(slug: params[:slug]).first
end
# ...
end
Repository
Basic repository usage
This code will get first article with slug: 'content123'
from articles
MongoDB collection, and return content with class Article
.
Fish0::Repository.new(:articles)
.where(slug: 'content123')
.first!
By default Fish0::Repository will coerce :entity_class
from :collection
, so you can skip this parameter.
Writing your own repository
# app/services/article_repository.rb
class ArticleRepository < Fish0::Repository
def initialize
super(:articles)
end
def published
where(visible: true, published_at: { '$lt': DateTime.now })
end
end
# app/controllers/articles_controller.rb
class ArticlesController < ApplicationController
# ...
def show
@article = Article.where(slug: params[:slug]).published.first!
end
# ...
end
Pagination
# app/controllers/articles_controller.rb
class ArticlesController < ApplicationController
include Fish0::Concerns::Paginatable
def index
@articles = paginate(Article.published)
end
# ...
protected
def per_page
31
end
# ...
end
ViewModel
ViewModel concern wraps Virtus around your models. It also adds #to_partial_path
and #type
methods. Method #to_partial_path
helps render your models via render
helper.
# app/models/article.rb
class Article
include Fish0::Concerns::ViewModel
attribute :headline, String
attribute :slug, String
attribute :content, Array[Hash]
attribute :published_at, DateTime
# ...
end
Cacheable
If you want your models to support #cache_key
method and use Rails caching, you should include Fish0::Concerns::Cacheable to such models.
Your model should respond to :updated_at
with DateTime object.
# app/models/article.rb
class Article
# ...
cacheable
# ...
end
# app/controllers/articles_controller.rb
class ArticlesController < ApplicationController
# ...
def show
@article = Article.where(slug: params[:slug]).first!
if stale?(@article)
respond_to do |format|
format.html
end
end
end
# ...
end