Showing posts with label Ruby. Show all posts
Showing posts with label Ruby. Show all posts

Wednesday, January 15, 2014

Sinatra Caches Templates

Yesterday, I learned the hard way that Sinatra caches templates when running under a non-development environment by default.

How I Found Out

My company site (Leavins-Software.com) was having serious issues where changes in layouts were not reflected in web browsers. I originally thought that this was a bug in how I set the Last-Modified HTTP header. Then I looked closely at Firefox's web console (specifically, the 'Network' tab). Last-Modified was being set properly!

I started making template changes in production to see what the real cause was. Please don't try this at home. I only did it because I'm a cheapskate working on a low-traffic site.

The test page seemed to update with every other change (which is odd behavior). Last-Modified was being updated properly, but the page wasn't changing. And then I got lucky: I was served an old version of the site with a properly-set Last-Modified date! Then a question hit me: "does Sinatra cache templates?"

Yes, Sinatra caches templates. Just not under the default development environment.

How Sinatra Caches Templates

Sinatra uses Tilt to render templates. While digging around Sinatra's source code, I discovered that Sinatra also uses Tilt's built-in caching for rendered templates. Tilt uses a Ruby Hash object for caching, meaning that Tilt's cache is per-instance.

This is different from how Rails does this. I'm not a Rails expert (I should probably change this if I want to continue working with Ruby), but I know that it uses a variety of different caching methods including page caching, and, to quote Caching with Rails, "Page caches are always stored on disk."

Each Sinatra app instance has its own cache, and I managed to hit the instance with a previously cached version of the template.

There is a Sinatra app setting named 'reload_templates' that controls caching behavior. The default setting is "true" for development and "false" for everywhere else. This is why Sinatra doesn't cache templates by default for the development environment.

Fixing Related Issues

The easiest way to resolve a template update issue is to just restart the Ruby app server. Really!

Monday, September 2, 2013

Using factory_bot with Sequel Models

factory_bot builds objects. Sequel is a database toolkit with support for models and model validation. It's very easy to use factory_bot to test Sequel models.

Out of the box, factory_bot can build non-persisted instances of Sequel models by calling FactoryBot.build(:symbol). It just can't create them and save them in a single method call with FactoryBot.create(:symbol). In fact, if you try calling factory_bot's create method, you will get an error message that looks like this:

NoMethodError: undefined method `save!' for #<Model:...>

There are two ways around this:
  1. Call FactoryBot.build(:symbol) to build a non-persisted Model instance and then call that instance's create() method
  2. Modify your FactoryBot definitions to specify a different method to call on create() 
Method #2 is better because your testing code becomes clearer. Just put this at the top of your FactoryBot definitions for Sequel models:

to_create { |i| i.save }

2018-08-12 Edit: 'factory_girl' was renamed to 'factory_bot' in 2017 and I found out about it today :-) Also updated the link to Sequel.

Monday, August 6, 2012

InvalidURIError For pg Gem - Connection String Issue

While working on my Sinatra & PostgreSQL-powered web-site (using Sequel 3.37.0 and pg 0.14.0), I encountered an odd URI-related error message. When connecting to the server, the resulting error message looked like this:

Error: URI::InvalidURIError: the scheme postgres does not accept registry part:

The root cause was that part of the connection string has a question mark in it. A question mark is used to separate the query string part of a URL from the rest of the URL. In the above connection string example, Ruby's URI-related code seems to treat the part of the connection string past the question mark as an invalid query string.
To resolve the problem, call CGI.escape to fix issues with the conection string.

Thanks

Stack Overflow - In Ruby, how do I replace the question mark character in a string?

This SO question (and the accepted answer by kmkaplan) suggested the use of CGI's escape method.

Tuesday, May 15, 2012

Pros and Cons of Using Sinatra

Since last October, I have been busy developing a commercial inventory management system. This system needed a website, and part of that website managed download access to the system. Much of the site used Jekyll, but Jekyll (being a static content generator) wasn't appropriate for the job. After considering a few different choices, I decided to use Sinatra, a Ruby framework for web development. I have used Sinatra for the last few months, so I have some idea about the pros and cons of using it.