Using ViewComponent in all Views #588
Replies: 3 comments 3 replies
-
At my company we decided to completely replace rails' view layer with view component about a year ago. The coding style we follow is one of very focused, single-responsibility objects (queries, commands, etc) so this was a natural transition for us. It's still uncharted territory and we haven't set any rules/conventions in stone yet but this is what regularly happens: Note: this examples use rails 6.0. I'll explain some differences with rails 6.1 below Controller Actions# app/controllers/posts_controller.rb
class PostsController < ApplicationController
def index
# Posts are injected as a dependency of the component.
# We'd like to do this query inside the component but pagination with Pagy
# has proven to be a bit harder than it seems.
@posts = Post.all
# We sometimes inject params as well because some part of the component usually needs them.
@component = Posts::IndexComponent.new(posts: @posts, params: params)
end
def show
# In this example, as I don't have to paginate, I'd rather do the query to retrieve the post inside the component
@component = Posts::ShowComponent.new(params: params)
end
end ViewsThis is super boilerplatey but it's necessary in rails 6.0.x # app/views/posts_controller/index.html.erb
<%= render @component =>
# app/views/posts_controller/show.html.erb
<%= render @component => We've had to render views this way because in rails 6.0 you can't render components from the controller. This was fixed in rails 6.1 where you can call The good1 object, 1 action is liberatingIt allows you to think of views in an object oriented way and frees you up to use as many methods as you want to process your data and create your view. I know this is possible in a controller as well but you end up mixing methods for different actions and the private section of your controller ends up being a mess. The badYou don't always need this amount of complexity.Sometimes I find myself having to write a ton of boilerplate just to render a simple thing in the screen which is in part a problem of... Not having conventionsIf this was a conventional approach where, say, in a generator, all files were created for me, that'd be awesome. Losing some of rails's nicest magicI love things that rails does like The futureIt's funny you mentioned this just now because a couple of days ago I started a personal project trying to fix the lack of conventions. I've slightly monkeypatched Ok, I won't spoil it anymore. I hope this helps! |
Beta Was this translation helpful? Give feedback.
-
Maybe ViewComponent could allow changing |
Beta Was this translation helpful? Give feedback.
-
I'd also like to be able to specify the directory in which a component should attempt to look for its erb template. To use @pinzonjulian's example above, when rendering Taking this thinking further, my application will contain components that power pages, page-specific ui, site-wide ui, and elements from our pattern library. I'd like to be able to better control the separation of these templates, and also to keep them somewhere other than the So with my four component types I'd like to be able to specificy the following template locations:
This is just an example. I'm not saying this is the best way to organise component templates. I'm just trying to illustrate that having the option to tell a component where its corresponding template file lives might be of some use! I've had a quick look through the Gem, but there doesn't appear to be an obvious way to specify the location of a component's view. If anyone has any tips on what the monkey-patch would look like for this then I could help put together a PR too, if others think that this might be a useful feature? |
Beta Was this translation helpful? Give feedback.
-
Rails lacks a proper view layer. The separation between view and template is default in many frameworks: Elixir's Phoenix and Hanami are examples.
ViewComponents addresses this issue in a small scale. I wonder if there's any common pattern (or pitfall) in using ViewComponent to render all views (directly from controllers). This would allow separation of concerns that presenters / decorators / helpers currently try to fix.
Any thoughts on that? Someone already going this route?
Beta Was this translation helpful? Give feedback.
All reactions