View Helpers
View helpers are methods available in your views that help format data, generate URLs, create form elements, and more. Rails provides many built-in helpers, and you can create your own.
URL Helpers
erb
1<!-- Link helpers -->
2<%= link_to "Home", root_path %>
3<%= link_to "Article", @article %>
4<%= link_to "Edit", edit_article_path(@article) %>
5<%= link_to "Delete", @article, method: :delete, data: { confirm: "Are you sure?" } %>
6
7<!-- With classes -->
8<%= link_to "Articles", articles_path, class: "btn btn-primary" %>
9
10<!-- With block for complex content -->
11<%= link_to @article do %>
12 <h3><%= @article.title %></h3>
13 <span><%= @article.author.name %></span>
14<% end %>
15
16<!-- URL helpers (without link) -->
17<%= article_path(@article) %> <!-- /articles/1 -->
18<%= article_url(@article) %> <!-- http://example.com/articles/1 -->
19<%= new_article_path %> <!-- /articles/new -->
20<%= edit_article_path(@article) %> <!-- /articles/1/edit -->
21
22<!-- Button to (creates a form) -->
23<%= button_to "Delete", @article, method: :delete %>
24<%= button_to "Subscribe", subscribe_path, method: :post %>Text Helpers
erb
1<!-- Truncate -->
2<%= truncate(@article.body, length: 100) %>
3<%= truncate(@article.body, length: 100, separator: ' ') %>
4<%= truncate(@article.body, length: 100, omission: '... (more)') %>
5
6<!-- Simple format (converts newlines to <br> and paragraphs) -->
7<%= simple_format(@article.body) %>
8
9<!-- Pluralize -->
10<%= pluralize(@articles.count, 'article') %>
11<!-- "5 articles" or "1 article" -->
12
13<!-- Highlight -->
14<%= highlight(@article.body, 'keyword') %>
15<!-- Wraps matches in <mark> tags -->
16
17<!-- Excerpt -->
18<%= excerpt(@article.body, 'keyword', radius: 50) %>
19<!-- Shows text around the keyword -->
20
21<!-- Word wrap -->
22<%= word_wrap(@long_text, line_width: 80) %>
23
24<!-- Strip tags -->
25<%= strip_tags(@html_content) %>
26
27<!-- Strip links -->
28<%= strip_links(@html_with_links) %>Number Helpers
erb
1<!-- Currency -->
2<%= number_to_currency(1234.50) %>
3<!-- $1,234.50 -->
4<%= number_to_currency(1234.50, unit: "€", format: "%n %u") %>
5<!-- 1,234.50 € -->
6
7<!-- Percentage -->
8<%= number_to_percentage(75.5) %>
9<!-- 75.500% -->
10<%= number_to_percentage(75.5, precision: 0) %>
11<!-- 76% -->
12
13<!-- Delimiter -->
14<%= number_with_delimiter(1234567) %>
15<!-- 1,234,567 -->
16
17<!-- Precision -->
18<%= number_with_precision(3.14159, precision: 2) %>
19<!-- 3.14 -->
20
21<!-- Human readable -->
22<%= number_to_human(1234567) %>
23<!-- 1.23 Million -->
24
25<!-- File size -->
26<%= number_to_human_size(1234567) %>
27<!-- 1.18 MB -->
28
29<!-- Phone -->
30<%= number_to_phone(5551234567) %>
31<!-- 555-123-4567 -->Date and Time Helpers
erb
1<!-- Time ago -->
2<%= time_ago_in_words(@article.created_at) %>
3<!-- "3 days ago" -->
4
5<!-- Distance in words -->
6<%= distance_of_time_in_words(Time.now, @event.starts_at) %>
7<!-- "about 2 hours" -->
8
9<!-- Date formatting with strftime -->
10<%= @article.created_at.strftime("%B %d, %Y") %>
11<!-- "January 15, 2024" -->
12
13<!-- Using I18n localize -->
14<%= l(@article.created_at, format: :long) %>
15<%= l(@article.created_at, format: :short) %>
16
17<!-- Time tag (with HTML5 time element) -->
18<%= time_tag(@article.created_at) %>
19<!-- <time datetime="2024-01-15T10:30:00Z">January 15, 2024</time> -->
20
21<%= time_tag(@article.created_at) do %>
22 Published <%= time_ago_in_words(@article.created_at) %> ago
23<% end %>Asset Helpers
erb
1<!-- Images -->
2<%= image_tag "logo.png" %>
3<%= image_tag "logo.png", alt: "Company Logo", class: "logo" %>
4<%= image_tag "logo.png", size: "100x100" %>
5<%= image_tag @user.avatar, width: 50, height: 50 %>
6
7<!-- Image path -->
8<%= image_path "icon.png" %>
9<!-- /assets/icon-abc123.png -->
10
11<!-- Stylesheets -->
12<%= stylesheet_link_tag "application" %>
13<%= stylesheet_link_tag "print", media: "print" %>
14
15<!-- JavaScript -->
16<%= javascript_include_tag "application" %>
17<%= javascript_include_tag "custom", defer: true %>
18
19<!-- Favicon -->
20<%= favicon_link_tag "favicon.ico" %>
21
22<!-- Audio/Video -->
23<%= audio_tag "sound.mp3" %>
24<%= video_tag "movie.mp4", controls: true %>Tag Helpers
erb
1<!-- Content tag -->
2<%= content_tag :div, "Hello", class: "greeting" %>
3<!-- <div class="greeting">Hello</div> -->
4
5<%= content_tag :ul, class: "list" do %>
6 <li>Item 1</li>
7 <li>Item 2</li>
8<% end %>
9
10<!-- Tag builder (Rails 5.1+) -->
11<%= tag.div "Hello", class: "greeting" %>
12<%= tag.p class: "intro" do %>
13 Welcome to our site!
14<% end %>
15
16<!-- Self-closing tags -->
17<%= tag.br %>
18<%= tag.hr %>
19<%= tag.img src: "photo.jpg", alt: "Photo" %>
20
21<!-- Data attributes -->
22<%= tag.div data: { controller: "modal", action: "click->modal#open" } %>
23<!-- <div data-controller="modal" data-action="click->modal#open"></div> -->Conditional Classes
erb
1<!-- Rails 6.1+ class helper -->
2<div class="<%= class_names('base', active: @active, hidden: @hidden) %>">
3<!-- active and hidden only added if their values are truthy -->
4
5<!-- Array syntax -->
6<div class="<%= ['card', ('featured' if @article.featured?)].compact.join(' ') %>">Custom Helpers
ruby
1# app/helpers/application_helper.rb
2module ApplicationHelper
3 def full_title(page_title = "")
4 base_title = "My App"
5 page_title.empty? ? base_title : "#{page_title} | #{base_title}"
6 end
7
8 def nav_link(text, path)
9 css_class = current_page?(path) ? "nav-link active" : "nav-link"
10 link_to text, path, class: css_class
11 end
12
13 def format_date(date)
14 date.strftime("%B %d, %Y") if date
15 end
16
17 def avatar_for(user, size: 50)
18 if user.avatar.attached?
19 image_tag user.avatar, size: "#{size}x#{size}", class: "avatar"
20 else
21 image_tag "default_avatar.png", size: "#{size}x#{size}", class: "avatar"
22 end
23 end
24
25 def markdown(text)
26 renderer = Redcarpet::Render::HTML.new
27 markdown = Redcarpet::Markdown.new(renderer)
28 markdown.render(text).html_safe
29 end
30enderb
1<title><%= full_title(@article&.title) %></title>
2
3<nav>
4 <%= nav_link "Home", root_path %>
5 <%= nav_link "Articles", articles_path %>
6</nav>
7
8<%= avatar_for(@user, size: 100) %>
9<%= format_date(@article.published_at) %>
10<%= markdown(@article.body) %>Model-Specific Helpers
ruby
1# app/helpers/articles_helper.rb
2module ArticlesHelper
3 def article_status_badge(article)
4 if article.published?
5 tag.span "Published", class: "badge badge-success"
6 else
7 tag.span "Draft", class: "badge badge-warning"
8 end
9 end
10
11 def reading_time(article)
12 minutes = (article.body.split.size / 200.0).ceil
13 "#{minutes} min read"
14 end
15endView helpers keep your templates clean and maintainable!
