Ruby, Sinatra, and static content (You know, JavaScript)

Sinatra: A quick look at how to set the default static content folder name to anything other than “public”.

Good news: If you were searching on how to server up static files with Sinatra, you’re in luck.

Bad news: I’m using Ruby…

As I stumble through the use of Sinatra (and to a lesser extent Ruby) one of the first issues I ran into was self loathing, followed by a need to have the server actually find my main JavaScript and CSS files. Well this is the current set up in a really poorly done folder rendition:

- content/script/live
 |-- final.js
- content/style/css
 |-- final.css
- view
 |-- main.html
- base.rb

Pretty simple.

At first main.html had what I thought would be the correct link to both:

  <link rel="stylesheet" href="content/style/css/final.css" type="text/css"/>
  <script type="text/javascript" src="content/script/live/final.js"></script>

Turns out, that wasn’t right. After a few attempts to get the server to actually do what it’s supposed to (and there by giving my powers of deduction too much credit), I went a huntin’.

So today I learned that Sinatra by default expects there to be a folder named “public” that would hold the /style, and /script folders. Go figure. Being stubborn as I am, I didn’t want to put them in a parent folder named ‘public’, I wanted it name ‘content’. Don’t hate. Note: the folder has to be on the same level as the file that was used to start the server.

So this is more than possible. Just takes one line it the base file (the one you used to start your server):

require 'sinatra'
require 'json'

set :bind, '0.0.0.0'
set :public_folder, Proc.new { File.join(File.dirname(__FILE__), 'content') } <--- HERE

Yes there are five lines… No the other four aren’t part of this problem… You done?

Ok so it’s now looking at that folder, but there’s still one more step. Remember those links?

  <link rel="stylesheet" href="/style/css/final.css" type="text/css" />
  <script type="text/javascript" src="/script/live/final.js"></script>

Just had to remove the content folder mention in the links, and everything is happy. Except me… because it’s Ruby.

Use of Ruby lambda expressions as method parameters like C# ones

So as I transition from the world of C# to Ruby due to a change in employment (And that I have grown to hate C#), I’ve been spending time getting used to certain concepts I’ve used heavily in C# done in Ruby. One big one is the ability to pass anonymous methods into other methods. So something like this in C#:

 public void LambdaHolder()
  {
    MethodThatUsesTheLambda(x => { Console.WriteLine(x +1));
  }

  public void MethodThatUsesTheLambda(Action<int> passedInMethod)
  {
    foreach(var item in Enumerable.Range(0, 10)
    {
      passedInMethod(item);
    }
  }

When done in Ruby it looks like this:

 def lambda_holder
    method_that_uses_the_lambda (lambda {|x| puts x +1}) 
  end

  def method_that_uses_the_lambda (passed_in_method)
    (1...10).each &passed_in_method
  end

The main thing is the & character. This allows the each method to recognize passed_in_method as an expression it can call and pass an argument to. Essential the same as:

  def method_that_uses_the_lambda (passed_in_method)
    (1...10).each {|x| passed_in_method.call(x)}
  end

Why would you want to do that? Readability if nothing else.

 def method_that_uses_the_lambda (will_output_a_number)
    (1...10).each &will_output_a_number
  end 

Compared to:

 def method_that_uses_the_lambda (will_output_a_number)
    (1...10).each {|x| will_output_a_number.call(x)}
  end 

Yeah… so there it is… I got nothin’ else… this is really awkward.