After being absence for a while, I recently began to reshape my Rails skills.
A basic Rails7-setup now includes TailwindCSS and TurboFrames.
I designed a simple Website providing a carousel as eye-catcher. Sure – you can copy the code from Tailwind Elements, install the tw-elements
javascript-library and anything runs out of the box.
But that's not very rubyish. Each time you want to change something, you have to touch the source-code. I like the approach to have a configuration file, providing input-data for a helper to create the carousel on the fly.
What defines a Carousel
As shown in the Cover Photo (which is taken from the Tailwind Elements Page, we need
- an image file
- a title
- a short description
- a link to other content
Configuration in config/carousel.yml
It seems only natural to put anything in a yaml-config-file. Lets create /config/carousel.yml
---
- :first:
:link: first
:image: dizzy-analyst.png
:title: Our amazing Approach
:text: Explore our unique Solution for all your Problems.
- :second:
:link: option
:image: dizzy-woman.png
:title: Feedback
:text: We encourage you to provide critical feedback.
The image-files have to be copied into /app/assets/images
! Its assumed, that the links just point to anchors on the same page.
The Controller
Assuming, you have setup a User
-Resource and want to place the carousel on the Index
-Page.
# app/controller/users_controller.rb
class UsersController < ApplicationController
(...)
def index
@users = User.all
@carousel = YAML.load_file(Rails.root + 'config/carousel.yml')
end
Its very simple: We define the @users
the usual way and read the complete yaml-file into @carousel
.
Display carousel in the viewfile
The view-file is evenly simple
# app/views/users/index.html.erb
<header> {some stuff for the header section} </header>
<%= carousel "testCarousel", @carousel %>
....
The hole code is delegated to the carousel
-helper.
The code: Carousel-Helper
Essentially the Tailwind Elements -code is translated to fit into Rails-content_tag elements.
# /app/helpers/users_helper.rb
module UsersHelper
def carusel id, content
slides = content.count
note = ->(n){ "<h2 class=\"text-4xl\">#{n[:title]}</h2> <p class=\"text-xl\">#{n[:text]}</p> "}
content_tag( :div, class: %w( carousel slide carousel-fade carousel-dark relative ), :"data-bs-ride" => 'carousel', id: id ) do
content_tag( :div , class: %w( carousel-indicators absolute right-0 bottom-0 left-0 flex justify-center p-0 mb-4 ) ) do
raw( (0 .. slides).map do | count |
label = "Slide #{count + 1}"
raw( if count.zero?
content_tag( :button , nil, type: 'button', :"data-bs-target" => "##{id}" , :"data-bs-slide-to" => count, :"aria-current" => "true", :"aria-label" => label, class: "active" )
else
content_tag( :button , nil, type: 'button', :"data-bs-target" => "##{id}" , :"data-bs-slide-to" => count, :"aria-label" => label )
end
)
end.join)
end +
content_tag( :div, class: %w( carousel-inner relative w-3/2 overflow-hidden ) ) do
raw( content.map.with_index do | c,index |
h = c.values.first
# first image ist active
class_attributes = index.zero? ? %w( carousel-item active relative float-left w-full ) : %w( carousel-item relative float-left w-full)
content_tag( :div, class: class_attributes ) do
content_tag( :a, href: "##{h[:link]}" ) do
image_tag( h[:image] , class: %w( block w-full)) +
content_tag( :div , raw(note[h]), class: %w( carousel-caption hidden sm:block absolute text-center ) )
end
end
end.join)
end +
content_tag( :button, class: %w( carousel-control-prev absolute top-0 bottom-0 flex items-center justify-center p-0 text-center border-0 hover:outline-none hover:no-underline focus:outline-none focus:no-underline left-0 ),
type: 'button', :"data-bs-target" => "##{id}", :"data-bs-slide" => "prev") do
content_tag( :span, nil, class: %w( carousel-control-prev-icon inline-block bg-no-repeat ), :"aria-hidden" => "true") +
content_tag( :span, "Previous", class: "visually-hidden")
end +
content_tag( :button, class: %w(carousel-control-next absolute top-0 bottom-0 flex items-center justify-center p-0 text-center border-0 hover:outline-none hover:no-underline focus:outline-none focus:no-underline right-0) ,
type: 'button', :"data-bs-target" => "##{id}", :"data-bs-slide"=> "next") do
content_tag( :span, nil, class: %w( carousel-control-next-icon inline-block bg-no-repeat ), :"aria-hidden" => "true") +
content_tag( :span, "Next", class: "visually-hidden")
end
end
end
end
Et voila, the carousel is displayed in localhost:3000/users
.
Further customization happens in the helper-code (by trained personal). The display-format for title
and description
, for example, can be changed in the Lambda in row 3.
Conclusion
The goal was, to separate Content and Function. Its just a matter of editing the `config/carousel.yml' file to update the contents of the carousel.
Top comments (0)