DEV Community

Serhii Jun
Serhii Jun

Posted on

Not-so-ugly styles code in your Rails app

Let's say, u already normally human and didn't use tailwindcss for your Rails app. Well, I just want to show you how I uses a feature from ruby-3.2 introduced by @zverok. It names Data and I use it together with ViewComponent and Rux to have a little less ugly code.

Gemfile:

group :development, :test do
  ...
  gem 'view_component', '~> 2.82'
  gem 'rux-rails', '~> 1.2', '>= 1.2.2'
  gem 'birdel', '~> 3.1'
end
Enter fullscreen mode Exit fullscreen mode
  1. Generate new component by ViewComponent or by Birdel
$ birdel gcom Ui::Mix::BarComponent

# app/
# ├─ components/
# │  ├─ ui/
# │  │  ├─ mix/
# │  │  │  ├─ bar_component/
# │  │  │  │  ├─ bar_component.rb
# │  │  │  │  ├─ bar_component.js
# │  │  │  │  ├─ bar_component.css
# │  │  │  │  ├─ bar_component.html.erb
# │  │  │  │  ├─ bar_component_controller.js
# │  │  │  │  └─ bar_component_actor.js
Enter fullscreen mode Exit fullscreen mode
  1. remove your bar_component.html.erb file

  2. Write your styles into bar_component.css

  3. Rename bar_component.rb file to bar_component.rux

#app/components/ui/mix/bar_component/bar_component.rux
class Ui::Mix::BarComponent::BarComponent < ViewComponent::Base
  Styles = Data.define(
    :nav_bar,
    :nav_item,
    :btn,
    :btn_active,
    :nav_item__logo
  )

  attr_reader :styles
  def initialize()
  end

  def styles
    @styles ||= Styles.new(
      nav_bar:        'nav-bar',
      nav_item:       'nav-item',
      btn:            'nav-item-btn',
      btn_active:     'nav-item-btn--active',
      nav_item__logo: 'nav-item-logo'
    )
  end

  def call
    <div class={css_class} data-controller={css_class}>
      <div class={styles.nav_bar}>
        <div class="#{styles.nav_item} #{styles.nav_item__logo}">
        </div>
        <div class={styles.nav_item}>
          <div class={styles.btn} data-action="click->#{css_class}#handleLeftBtn">Left</div>
          <div class="#{styles.btn} #{styles.btn_active}">Center</div>
          <div class={styles.btn}>Right</div>
        </div>
        <div class={styles.nav_item}>
        </div>
      </div>
    </div>
  end

  def css_class
    @css_class ||= "ui--mix--blabla..."
  end
end
Enter fullscreen mode Exit fullscreen mode

Explanation:

In this part we define a custom Data class named Styles with fields, which will be used as the names of classes from our style file:

  Styles = Data.define(
    :nav_bar,
    :nav_item,
    :btn,
    :btn_active,
    :nav_item__logo
  )
Enter fullscreen mode Exit fullscreen mode

And here we just set a value for each field of our Styles data object:

  def styles
    @styles ||= Styles.new(
      nav_bar:        'nav-bar',
      nav_item:       'nav-item',
      btn:            'nav-item-btn',
      btn_active:     'nav-item-btn--active',
      nav_item__logo: 'nav-item-logo'
    )
  end
Enter fullscreen mode Exit fullscreen mode

Great now we can use that @styles object inside #call method which allows us to write the same to JSX-styled syntax code. Like:

<div class={styles.nav_item}>
Enter fullscreen mode Exit fullscreen mode

Example rendered HTML:

<div class="nav-bar">
  <div class="nav-item nav-item-logo">
  </div>
  <div class="nav-item">
    <div class="nav-item-btn" data_action="click->ui--mix--bar-component#handleLeftBtn">
      Left
    </div>
    <div class="nav-item-btn nav-item-btn--active">
      Center
    </div>
    <div class="nav-item-btn">
      Right
    </div>
  </div>
  <div class="nav-item">
  </div>
</div>
Enter fullscreen mode Exit fullscreen mode

Btw, Birdel (https://github.com/serhiijun/birdel) is my microframework which is not ready yet and you can help me by contributing. It's revolutionized tool for rails assets management and WebSocket components rendering which will replace sucks rails-turbo.

Sentry image

Hands-on debugging session: instrument, monitor, and fix

Join Lazar for a hands-on session where you’ll build it, break it, debug it, and fix it. You’ll set up Sentry, track errors, use Session Replay and Tracing, and leverage some good ol’ AI to find and fix issues fast.

RSVP here →

Top comments (0)

Billboard image

Create up to 10 Postgres Databases on Neon's free plan.

If you're starting a new project, Neon has got your databases covered. No credit cards. No trials. No getting in your way.

Try Neon for Free →