Start tinkering

Single-File Ruby Templates

Experimenting with Ruby, a new Ruby gem or full-blown Rails?
Start with a no-fuss single-file Ruby script template.

  • Most basic template with just bundler/inline.

    require "bundler/inline"
    
    gemfile do
      source "https://rubygems.org"
      # add gems you need here
    end
    
    puts "Start tinkering!"
    
  • Basic template with some auto-run magic by keepgoing.

    require "bundler/inline"
    
    gemfile do
      source "https://rubygems.org"
      gem "keepgoing" # auto-runs script on changes
      # add gems you need here
    end
    
    puts "Keep tinkering!"
    
  • Template coming with active_support and auto-run by keepgoing.

    require "bundler/inline"
    
    gemfile do
      source "https://rubygems.org"
      gem "keepgoing" # auto-runs script on changes
      gem "activesupport"
      # add gems you need here
    end
    require "active_support/all"
    
    puts "Ain't nobody got time for this".truncate(25)
    
  • Connect to a PostgreSQL database, query and create records using ActiveRecord.

    require "bundler/inline"
    
    gemfile do
      source "https://rubygems.org"
    
      gem "activerecord"
      gem "pg"
    end
    
    require "active_record"
    
    ActiveRecord::Base.establish_connection(adapter: "postgresql", database: "ruby_starters_development")
    ActiveRecord::Base.logger = Logger.new(STDOUT)
    
    # Get list of tables in the database
    tables =
      ActiveRecord::Base
      .connection
      .execute("select * from pg_catalog.pg_tables where schemaname = 'public'")
      .pluck('tablename')
    
    # Define ActiveRecord Model classes for all tables
    puts "\n\nAvailable Models (and tables):\n\n"
    tables.each do |table, model: table.classify|
      puts "#{model} (#{table})"
      Object.const_set(model, Class.new(ActiveRecord::Base))
    end
    
    # When connecting to a Rails generated db, chances are there is a schema_migrations table:
    puts SchemaMigration.last.inspect
    
    # Suppose there is a users table we can query that:
    puts User.where(first_name: "Wolfgang").count
    
    # WE can create records, too!
    # But mind you are bound by db constraints only,
    # there are no validations unless you defined them here:
    # User.create!(email: "starters@wolfgangrittner.dev", first_name: "Wolfgang")
    
  • HTTP requests to httpbingo.org with Faraday incl. some middleware.

    require "bundler/inline"
    
    gemfile do
      source "https://rubygems.org"
      gem "keepgoing" # auto-runs script on changes
      gem "faraday", "~> 2.3"
      gem "faraday-retry", "~> 1.0"
    end
    
    require "faraday"
    require "faraday/retry"
    
    # configure Faraday incl. some middleware
    retry_options = {
      max: 2,
      interval: 0.5,
      retry_statuses: [500],
      retry_block: -> (env, _options, _retries, _exc) { puts "\n\ngot #{env.status} 😱 will retry\n\n" }
    }
    
    connection = Faraday.new("http://httpbingo.org") do |f|
      f.request :json # encode req bodies as JSON and automatically set the Content-Type header
      f.request :retry, retry_options
      f.response :json # decode response bodies as JSON
      f.response :logger
    end
    
    # POST request
    response = connection.post("/post") do |req|
      req.params["limit"] = 100
      req.body = {query: "chunky bacon"}
    end
    
    # GET some json
    response = connection.get("/json")
    puts "\n", response.body.dig("slideshow", "title"), "\n"
    
    # test-drive retries
    response = connection.get("/unstable")
    puts "\n", response.status
    
  • Full-blown Rails app with SQLite database (in-memory). No setup required.

    require "bundler/inline"
    
    gemfile do
      source "https://rubygems.org"
    
      gem "rails"
      gem "sqlite3"
      gem "puma"
      # add gems you need here
    end
    
    # using SQLite in memory; mind that's only working with max. 1 connection
    require "active_record"
    require "action_controller/railtie"
    ActiveRecord::Base.establish_connection(adapter: "sqlite3", database: ":memory:", pool: 1)
    ActiveRecord::Base.logger = Logger.new(STDOUT)
    
    ActiveRecord::Schema.define do
      create_table :notes do |t|
        t.string :title
        t.text :body
        t.timestamps
      end
    end
    
    class Note < ActiveRecord::Base
      validates :title, presence: true
    end
    
    Note.create(title: "Hello World!", body: "Greetings from Single-File Rails 👋")
    Note.create(title: "Reminder", body: "You need to stop and restart for changes to take effect")
    Note.create(title: "Missing Feature", body: %(Sadly the <a class="text-blue-400 hover:text-blue-600" href="https://github.com/wolfgangrittner/keepgoing">keepgoing gem</a> does not play nicely with Rails yet.))
    Note.create(title: "Still great", body: "This is still a great way to quickly try something out 🎉<br>Even with full-blown Rails 🛤")
    
    # Put back the db connection, because there's only 1, remember
    ActiveRecord::Base.connection_pool.checkin(ActiveRecord::Base.connection)
    
    class InlineApp < Rails::Application
      secrets.secret_token    = "secret_token"
      secrets.secret_key_base = "secret_key_base"
    
      config.logger = Logger.new($stdout)
      Rails.logger = config.logger
    
      routes.draw do
        resources :notes, only: %i[index create]
        root to: redirect('/notes')
      end
    end
    
    class NotesController < ActionController::Base
      include Rails.application.routes.url_helpers
    
      def index
        @notes = Note.all
        render inline: notes_html
      end
    
      def create
        Note.create(title: "New Note #{Note.count + 1}", body: "This is your new note")
        redirect_to notes_path
      end
    
      private
    
      def notes_html
        <<~ERB
          <!DOCTYPE html>
          <title>Single-File Rails</title>
          <script src="https://cdn.tailwindcss.com"></script>
          <body class="bg-zinc-50 flex gap-5 p-5 flex-wrap">
            <h1 class="font-bold text-xl text-red-500 w-full">Single-File Rails Notes</h1>
            <% @notes.each do |note| %>
              <div class="bg-white rounded shadow p-5 w-full sm:max-w-sm">
                <h2 class="font-bold text-emerald-400 mb-1"><%= note.title %></h1>
                <p><%= note.body.html_safe %></p>
              </div>
            <% end %>
            <%= form_with url: notes_path, class: "w-full" do |form| %>
              <%= form.submit "Create New Note", class: "rounded bg-emerald-300 px-3 py-1 border border-emerald-500 hover:bg-emerald-400 text-emerald-900" %>
            <% end %>
          </body>
        ERB
      end
    end
    
    require "puma"
    require "rails/command"
    require "rails/commands/server/server_command"
    
    options = {
      app: InlineApp,
      Port: 3000,
      min_threads: 1,
      max_threads: 1
    }
    Rails::Server.new(options).start