Wednesday, May 17, 2017

MOVED TO https://www.jimmenard.com/blog.html

This blog has moved to https://www.jimmenard.com/blog.html.

Asynchronous Audits are Awesome

Over on The Dirty Birds, Chloe + Isabel's tech blog, I've written about improving the performance of Ruby on Rails model change auditing in Asynchronous Audits are Awesome.

Emacs and Rails Testing

Over on The Dirty Birds, Chloe + Isabel's tech blog, I've written about Emacs and Rails Testing.

Tuesday, September 8, 2015

Phoenix: Seeding Your Tests

If you need to seed your test database when running Phoenix tests, you can require the seed file in test/test_helper.exs:

ExUnit.start

Mix.Task.run "ecto.create", ["--quiet"]
Mix.Task.run "ecto.migrate", ["--quiet"]
# Add this line:
Code.require_file("priv/repo/seeds.exs")
Ecto.Adapters.SQL.begin_test_transaction(Expensive.Repo)

You can, of course, require a different file instead.

Wednesday, July 4, 2012

Emptying Full Client-Side Browser Storage

This morning I started seeing the following error on all preview pages generated by an app running on my development machine:

QUOTA_EXCEEDED_ERR: DOM EXCEPTION 22
in http://localhost:8080/sites/1341373150.915000/public_html/layout.less

This error message isn't caused by the application, it's because the generated HTML uses client-side LESS to render its CSS. The LESS processing had filled up local storage, because each preview generates new storage keys due to the ever-changing timestamp part of the URL.

The solution: here's how to manually clear your browser's local storage of any data whose keys match a particular value:

// Clears local storage of keys that match a regular expression.
function clear_local_storage(key_regexp, keep_key=null) {
  var r = new RegExp(key_regexp);
  for (var key in localStorage) {
    if (key != keep_key && r.test(key))
      localStorage.removeItem(key);
  }
}

A sample of its use:

clear_local_storage("^http://localhost:8080/sites.*layout.less(:timestamp)?$");

Since I wrote the app that's publishing the pages that generate this error, I'm considering making the app inject this JavaScript code into the pages to make sure that end users never see this error message.

Saturday, June 4, 2011

Identity Recall

io.com is going away. It's funny how upsetting this is to me. I've been jimm@io.com since 1994 or so—maybe a year or two earlier than that. You know what I'm worried about most? All those open source projects, emails, and other digital resources that point to jimm@io.com are going to be pointing nowhere in a month. It feels like my online identity is being stolen. Except it's not being stolen, of course—merely recalled.

A Slashdot commenter also pointed out the potential security risk: "Think about it, among other things whoever owns that domain now will be able to intercept all mail to io.com accounts, and with the quickness and suddenness of the transfer not everyone's who uses those addresses is going to be able to completely transition off them before the transfer happens"

io.com was the ISP run by Steve Jackson Games—the company raided by the Secret Service because they were writing a role playing game called "Hacker". SJ Games fought the Secret Service and won. I think the EFF grew out of that case.

io.com was bought by prismnet.com years ago. PrismNet changed hands a few times. The last guy who sold it to the current owner (for $20) didn't sell the io.com domain. He kept it but let them use it until July 1, 2011. My guess is he wants to sell it to I/O Digital for a skillion dollars.

From now on, I'm jim@jimmenard.com. Also jim.menard@gmail.com, or jimm@prismnet.com. Time to start wrapping my head around being jim@jimmenard.com instead of jimm@io.com. Bye, jimm@io.com.

io.com is dead. Long live io.com.

Sunday, July 25, 2010

Play Framework Configuration

I've been using the Play framework for a big project at work. It's fantastic. I almost hesitate to say it, but it's like Ruby on Rails for Java. Watch the video that's on the home page; it's a good quick introduction.

The Tech Ops team at work wants control over configuration of the app. This makes sense for a few reasons. First, they're responsible for running it so they should be able to tweak things like memory settings. Second, they need to tell the app where the database lives, what the password is, etc. Tech Ops also wants the app to run as a WAR inside an app server. That's fine: Play comes with a war command that bundles your app into either an exploded WAR or a WAR file.

The problem is, Play doesn't know how to read any configuration file other than the one that's in its conf directory. At least, that's what I thought. It turns out there is an undocumented feature of Play configuration files: If any configuration key is named@include.foo, then the value is used as a path and that file is read, too.

A few caveats.

  • The path is relative to the application directory within the WAR. So, for example, to find a file in Tomcat's conf directory, the path will have to be something like ../../../../../conf/play.conf.
  • The file that gets included isn't treated exactly like the normal configuration file. Magic values like ${play.path} and ${application.path} are not interpreted,.
  • The current Play framework id (similar to Rails' environment) is ignored. However, since the include code is run after everything else is loaded, this isn't really a problem since the external configuration file you're loading is presumably for the environment you're running.

There is also a plugin architecture, and a hook that runs after the configuration file is read. This means that, even if @include.foo didn't exist, you can write a plugin to do anything you want to alter the app's configuration.

Update: Core Play developer Guillaume Bort wrote on the email list, "This feature is not yet documented because it is not ready: as you observed it the placeholders and the framework id stuff are not handled properly." Caveat emptor.