Yuba
warning
Version of this gem is now 0.0.x. It works but there must be occasional breaking changes to the API.
Summary
Yuba add new layers to rails.
- Service
- Form
- ViewModel
It is convenient to use them in combination, but you can use them even by themselves.
If you have difficulties with large rails application, Yuba help you.
Installation
Add this line to your application's Gemfile:
gem 'yuba'
And then execute:
$ bundle install
Support
- Rails 5.2+
- Ruby 2.5+
ViewModel
ViewModel is useful when there are many instance variables in controller.
class PostViewModel < Yuba::ViewModel
property :post
property :author, public: true
property :other, optional: true
def title
post.title
end
def body
post.body
end
end
Post = Struct.new(:title, :body)
post = Post.new('hello', 'world')
view_model = PostViewModel.new(post: post, author: 'willnet')
view.title #=> 'hello'
view.body #=> 'world'
view. #=> 'willnet'
view.post #=> NoMethodError
property
.property method register property to the class.
Those registered by property need to be passed as arguments to the initialize except when optional: true is attached. You get ArgumentError if you don't pass property to initialize.
Property is default to private. This means you can use it in internal the instance. If you want to use it as public, use public: true option.
Auto Assign
You can use ViewModel in a controller like following
class PostsController < ApplicationController
def show
@view_model = PostViewModel.new(post: post, author: 'willnet')
end
end
In view template, if you want to access post and author, you have to use @view_model instance variable like @view_model.post.title. if it feels troublesome, you can write like following
class PostsController < ApplicationController
def show
view_model = PostViewModel.new(post: post, author: 'willnet')
render view_model: view_model
end
end
view_model option of render takes ViewModel, which get it's public methods (include public property) and assign them to instance variables in view template. So you can write <%= @post.title %> instead of <%= @view_model.post.title %>
Service
Service is useful when controller has many application logic.
class PostController < ApplicationController
def new
@post = CreatePostService.call(user: current_user).post
end
def create
service = CreatePostService.call(user: current_user, params: params)
if service.success?
redirect_to root_path
else
@post = service.post
render :new
end
end
end
class CreatePostService < Yuba::Service
property :user, public: true
property :params, optional: true
def call
if post.save
notify_to_admin
else
fail!
end
end
def post
user.posts.build(post_params)
end
private
def notify_to_admin
AdminMailer.notify_create_post(post).deliver_later
end
def post_params
params.require(:post).permit(:title, :body)
end
end
.propertymethod register property to the class like ViewModel..callinvokes#callafter assigning arguments as properties.#success?returnstrueif you don't invoke#fail!
You have inspection methods for properties.
service = CreatePostService.new(user: someuser)
service.has_property?(:user) #=> true
service.has_public_property?(:user) #=> true
service.has_private_property?(:user) #=> false
service.has_required_property?(:user) #=> true
service.has_optional_property?(:user) #=> false
Form
Form is just wrapper of reform-rails for now.
You can see documentation here.
Combination Sample
class ArtistsController < ApplicationController
def new
@view_model = Artist::CreateService.new(params: params).view_model
end
def create
service = Artist::CreateService.call(params: params)
if service.success?
redirect_to artists_path
else
@view_model = service.view_model
render :new
end
end
end
class Artist::CreateService < Yuba::Service
property :params
def call
if form.validate(params)
form.save
else
fail!
end
end
def view_model
Artist::CreateViewModel.new(form: form)
end
private
def form
@form ||= ArtistForm.new(Artist.new)
end
end
class ArtistForm < Yuba::Form
property :name
validates :name, presence: true, length: { maximum: 100 }
end
class Artist::CreateViewModel < Yuba::ViewModel
property :form, public: true
end
generators
You can use generators.
rails generate yuba:service create_artist
rails generate yuba:form artist
rails generate yuba:view_model artist_index
Contributing
You can try to test by doing as following
git clone https://github.com/willnet/yuba.git
cd yuba
bundle
bundle exec rake
License
The gem is available as open source under the terms of the MIT License.