Skip to content

[idea] Render the program of the day as ruby code! #67

@palladius

Description

@palladius

I was playing with gemini to explain ruby to non rubyists and this idea came to me:


That's a brilliant idea. Making the DSL "multilingual" is the ultimate flex to show how Ruby can adapt to its users.

Here is the final version, tailored for an international audience, with the code supporting both English and Italian keywords.


🚀 The "Boss Level" Ruby DSL

This script uses a Hash to map keywords, allowing the same logic to work with talk or discorso, price or prezzo.

# The "Frontend" Code (The English version)
conference_plan = RubyConf.create "Florence 2025", lang: :en do
  intro "Riccardo Carlesso", title: "Rubycon: the genesis", duration: 10.minutes
  
  talk "Matz", title: "The future of Ruby", at: "09:30"
  talk "DHH",  title: "The One Person Framework", at: "11:00"
  
  break_time "Lunch on the Terrace", duration: 1.hour
  
  # Inline rescue power
  talk "Mystery Speaker", at: "15:00" rescue talk "Lightning Talks", at: "15:00"
  
  drinks "Networking & Spritz", location: "Garden"
end

conference_plan.display_flyer

🛠️ The Logic Behind (The Multi-Lang Engine)

We use method_alias or a simple lookup to handle the different languages.

class RubyConf
  # Keyword mapping for a truly international DSL
  DICTIONARY = {
    en: { intro: :intro, talk: :talk, break: :break_time, drinks: :drinks, title: :title },
    it: { intro: :intro, talk: :discorso, break: :pausa, drinks: :aperitivo, title: :titolo }
  }

  def self.create(edition, lang: :en, &block)
    conf = new(edition, lang)
    conf.instance_eval(&block)
    conf
  end

  def initialize(edition, lang)
    @edition = edition
    @lang = lang
    @events = []
    @labels = DICTIONARY[lang]
  end

  def method_missing(name, *args, **kwargs)
    # This allows the DSL to accept Italian methods if :it is selected
    if @labels.values.include?(name) || @labels.keys.include?(name)
      process_event(name, *args, **kwargs)
    else
      super
    end
  end

  def process_event(type, name, **details)
    @events << { name: name }.merge(details)
  end

  def display_flyer
    puts "\n--- 💎 RUBYCONF IT: #{@edition} 💎 ---\n\n"
    @events.each do |e|
      time_label = e[:at] || e[:at] || "#{e[:duration] / 60}m"
      puts "📍 [#{time_label}] #{e[:name]} - #{e[:title] || e[:location]}"
    end
  end
end

# Syntactic sugar for time
class Numeric
  def minutes; self * 60; end
  def hour; self * 3600; end
end

💡 Why this wins over the English audience:

  • Human-Centric: It reads like a manifest, not a configuration file.
  • The "Pretzel" and "Shovel": Even in this short snippet, the use of symbols (:en, :title) shows the distinct Ruby aesthetic.
  • The method_missing trick: It proves that in Ruby, the language itself is a piece of clay you can mold. You aren't stuck with the keywords the creator gave you; you can define your own.

Would you like me to generate a JSON export method for this class so your friend can see how easily Ruby talks to modern web frontends?

Metadata

Metadata

Assignees

No one assigned

    Labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions