Memcached with Rails 3

Rails,Ruby — Dillon @ 6:13 pm

I never had a reason to play with memcached and it was on my list of things to learn. Below I will demonstrate an example app very quickly and simply. I’m not doing anything more complicated than simple primitive storing. If you are going to store any objects in memcached, dalli gem will take care of this for you (ymmv).

First let’s create a rails app and an rvm gemset to play in.

rvm use 1.9.2@memcache --create

If you don’t have rails in your global gemset, you can install rails now. I used the 3.1 RC here just to test out 3.1 and memcached at the same time.

gem install rails --pre
gem install dalli

Dalli is written by Mike Perham (awesome guy) and simply wires up Rails.cache to be our memcached server. This is convenient and more standard than creating your own global variable or other configuration.

Next, let’s install memcached if we haven’t already:

brew install memcached
memcached -v

You can also start memcached as a service under Mac using the homebrew instructions. I like to leave things in the foreground when I’m first setting them up or grok’ing.

Ok, now we can create our dummy app.

rails new memcache_test

Our dummy rails app is going to have a slow controller action in it. In this case, it could be a row count of a huge database. In your case it could be a slow network call or a result of an expensive SQL operation.

First, edit your Gemfile:

gem 'dalli'

Edit config/environments/development.rb

# Memcached
  config.perform_caching = true
  config.action_controller.perform_caching = true
  config.cache_store = :dalli_store, 'localhost:11211'

Rails c should work at this point and this line:

Rails.cache.read('foo')
=> nil

Now generate a controller:

rails g controller posts
class PostsController < ApplicationController
  def index
    @posts_count = Rails.cache.read 'posts_count'
    if @posts_count
    else
      # expensive operation
      sleep 3
      @posts_count = 321
      Rails.cache.write('posts_count', @posts_count, :expires_in => 3)
    end
  end
end

Create a route in routes.rb:

resources :posts

Create a simple view in app/views/posts/index.json.erb:

{ posts: <%= @posts_count %> }

Now when you hit the page it should be slow the first time but fast the second time. After 3 seconds, it’s slow again.

$ time wget -O - localhost:3000/posts.json
HTTP request sent, awaiting response... 200 OK
Length: 14 [application/json]
real	0m3.049s
user	0m0.001s
sys	0m0.003s
$ time wget -O - localhost:3000/posts.json
HTTP request sent, awaiting response... 200 OK
Length: 14 [application/json]
real	0m0.049s
user	0m0.001s
sys	0m0.003s

So you can see that memcached returned the cached object and avoided the sleep call. In the real world, this would equate to lower page rendering time or better application performance.

How to write a Ruby and Rails 3 REST API

Rails,Ruby — Dillon @ 11:18 pm

Background

I’ve always wondered how I’d go about publishing a real REST API on the web to do something. In this example, we’ll create an employee manager app-thing. It’s not particularly interesting but it shows what “API” means. In another bit, we’ll create an “API” meaning a library to interact with this web service.

The rails app

First, create a new rails app.
rails new rest_api

Edit config/database.yml:

  # MySQL
  #   gem install mysql2
  development:
    adapter: mysql2
    host: localhost
    database: rest_api
    username: rest_api
    password: rest_api
    pool: 5
    timeout: 5000

(more…)

Arduino Cat Faucet with Mongodb and Rails

Arduino,Noteworthy,Rails,Ruby — Dillon @ 11:01 pm

I built a robot arm for my cat during a month-long geekcation. :) Here are some shots of the web interface. The graph shows the percentage of the day that she drinks.

Final hardware rig

Background

My cat likes to drink fresh and cold water directly from the faucet. We get up and turn on the faucet only to leave it running after she’s jumped down. It’s not really a big problem for us but I saw a fun problem that I could work on. As much as this seems like a weird and freakish oddity, it’s a potential start of a smarthome sensor network that may provide some utility. I also saw an opportunity to learn various things such as MongoDB, mechanical construction with Microrax, Rails3 and more development on Arduino with an Xbee module.

(more…)

Rails behind Enterprise SSO

Rails,Systems — Dillon @ 8:12 pm

This is a quick write-up without a lot of detail. We hacked together a quick rails app to do provisioning in the style of OIM behind an OAM SSO webgate. The complete guide and detail would be tens of pages so I’ll just give a quick overview for the strategy.

The Goal

  • Ldap authentication
  • No db
  • Sso protected
  • Weblogic deployment

Develop app steps and failures

We used activeldap for the LDAP pieces and defined our user model to narrowly search for a particular objectclass and attributes. Tried to use Authlogic. Fail. Acts as authenticated fail. Devise fail. Ended up using filters and activeldap. Integrating the gems and activeldap was actually kind of hard. A lot of the security gems assume you’ve got activerecord users and depend a lot on the validation helpers etc. So some of the authN gems didn’t work for us. We also had to hack a bit on the activeldap validations. Password policy was non-trivial. I just rolled my own like so:


def validate_password(password)
// initialize a password score
// call password rule methods like:
// check_special_characters
// check_length
// check_uppercase
end

The score from each check method is added to a total score. If the score is greater than zero then your password fails the checks. Each check, a hash for flash[:error] is used so that a precise error message is possible. It works ok except the flash error display is for some reason not ordered correctly.

All configuration constants are stored as YML as an app_config.yml file. For example, the LDAP server, port, password policy rules etc.

For the SSO config, we just detect header as HTTP_REMOTE_USER even though OAM is creating REMOTE_USER. Quick and easy. You have to append the “HTTP_” for the name. It’s a naming convention thing that you can’t do anything about. If your OAM header variable is UNICORNS, then you have to use HTTP_UNICORNS.

We used formtastic for the forms. This was a bit problematic with it trying to detect the activeldap model instead of activerecord.

Testing while developing

Ok so how do you test integration? Are you going to SSO enable your dev laptop? That’s way too hard. You can hardcode the credentials for a while but then eventually you’re going to want to test. I got around this by using a firefox plugin called modify headers. It’s pretty straight forward except for the small detail that you have to keep it open while hitting pages. I thought it would run in the background but it doesn’t. Just keep the modify headers firefox plugin open and it’ll let you create an auth cookie. Don’t worry, this isn’t a security hole. OAM in production won’t let you do this. It’s just used for development.

Warble

install warbler with gem install warbler
Generate default config warble config
Install jruby-openssl because activeldap requires it
Edit config/warble.rb to include jruby-openssl note that you don’t have to have jruby installed or anything.

The rest of the steps are not rails related. Deploy war to Weblogic as usual. Set up a Proxy webgate back to Weblogic for /app (you can’t protecte Weblogic directly with OAM). Protect /app with an OAM policy. If your firefox header test worked then when you turn that off and hit it behind OAM it will work the same. I was able to identify and trust the REMOTE_USER header coming in.

Bam, you’ve got a rails app working in a big scary enterprise SSO environment. The best part about all of this was how fast it went. Compared to JSP/Java EE dev, it was a breeze. The only big multi-day hangups we had was with activeldap. Many gems and auth models really expect you do have your user in the DB. Unfortunately, putting users in the DB creates a silo. Fine for small shops, not so good if you’re using Active Directory, OID, OpenLDAP or Fedora DS (389) for a centralized login.

Alphabet sequences with factorygirl

Rails,Ruby — Dillon @ 1:37 pm


I was trying to use this in a factorygirl class to create test data with names like Product A, Product B etc. This isn’t very sophisticated. If you want some smarter dummy data generation with factorygirl, check out this post at the PMA media group.

Anyway, here’s the pure ruby part if you fire up irb:

i = 0
hash = Hash.new
"a".upto("z") do |letter|
hash[i] = letter
i+=1
end

Gives you:
hash.sort
=> [[0, "a"], [1, "b"], [2, "c"], [3, "d"], [4, "e"], [5, "f"], [6, "g"], [7, "h"], [8, "i"], [9, "j"], [10, "k"], [11, "l"], [12, "m"], [13, "n"], [14, "o"], [15, "p"], [16, "q"], [17, "r"], [18, "s"], [19, "t"], [20, "u"], [21, "v"], [22, "w"], [23, "x"], [24, "y"], [25, "z"]]

Or even cleaner:
hash.sort.each {|k,v| print "#{v} "}
a b c d e f g h i j k l m n o p q r s t u v w x y z

It has an off-by-one problem for readability. You actually need to change the i=0 to i=1 for factory girl because the factorygirl sequence starts on 1. Here’s my factorygirl product class:

# let's make an alphabet.
i = 1
hash = Hash.new
"A".upto("Z") do |letter|
hash[i] = letter
i+=1
end

Factory.define :product do |p|
p.sequence(:name) { |n| "Product #{hash[n]}" }
p.price 19.95
p.platform "Example Platform"
end

If you need more than 26 products, just change the upto(“Z”) to “ZZ” or whatever. It’ll scale as far as you want. If you need infinite scaling, don’t use letters. :)

To test, in the console:
script/console test
> 40.times { Factory(:product) }

And this will generate some madness as depicted in the screenshot to the right.

Watchr Unit Tests + Growl + Doomguy

Rails — Dillon @ 11:57 am


I read this post about setting up autotest with growl. The little doomguy was a nice effect and got a literal lol out of me (llol?). However, the post was from 2007 and apparently autotest has some problems with 1.9. I’m not running 1.9 but on the eve of rails3, I probably will be. Ok, what’s cooler than autotest? Apparently not much, three hits on google.

Install a gem
I found Watchr. It’s not too hard to set up. sudo gem install watchr to get the gem. If you’re on *nix, grab the filesystem event gem: sudo gem install rev. Now we have watchr up but we need a config.

Create the watchr config
The docs tell you to edit a config/watchr.rb file. Mine came from the examples on their wiki. It worked out of the box. It’s posted here. It’s a basic rails testing config that I haven’t had to edit. It’s very readable if you need to futz with it.

Create a test case
Ok so watchr just runs `rake test` which you can do in your rails app root. But perhaps you don’t have any test cases created. The generators will create them for you. But assuming you don’t have one, create a file named [rails app root]/test/functional/hello_test.rb.

require 'test_helper'
 
class HelloTest < ActiveSupport::TestCase
  def test_hello
    s = "Hello"
    assert_equal("Hello", s)
  end
 
end

Obviously this is a crappy assertion.

Get Growlnotify
Obviously, you’ll need growl installed. But you also need the growlnotify binary. It’s good to have anyway (I use it in Automator). I didn’t have it by default on two of my machines so I assume that the normal Growl install doesn’t install it. It’s on the Growl 1.2 dmg under extras. You just have to copy it to /usr/local/bin. Download the growl dmg, open the dmg. You don’t need to reinstall growl.
sudo cp /Volumes/Growl-1.2/Extras/growlnotify/growlnotify /usr/local/bin

You can test it with:
growlnotify -t "Title" -m "Message"

Make doomguy happen
Create a directory for the growl icons: mkdir ~/.watchr_images.
Copy these two doomguy faces to ~/.watchr_images/. On mac, hit Shift+Cmd+G and go to the hidden folder.

Now we should have two pngs in our hidden folder.

The watchr.rb file references these images. If you want to put it somewhere else (like maybe under ~/Pictures), you can change the .rb.

Ok Go!
Launch with: watchr config/watchr.rb from your rails app root. Watchr should be in your $PATH because you installed the gem. You should have a blank screen now where watchr is waiting.

When you save a file, watchr will fire. Depending on the file you saved, a different test will run. If you save a controller, for example, the functional test for that controller will fire. If you save a model object, a unit test for that model object will fire. If you want to force a whole test suite to run hit Ctrl+\ in the watchr window.

When things pass:

When things fail:

The growl display setting is “Music Video”. I have it popping up on my 3rd monitor which is less distracting but still visible. However if you put it on your main monitor, the overlay won’t interfere with mouse clicks, which is nice. It makes for a killer setup where I don’t have to test my app with a browser or with contrived/non-automated tests. Now I just need to write more tests.

This work is licensed under a Creative Commons Attribution-Noncommercial-Share Alike 3.0 Unported License.
(c) 2012 SQUARISM | powered by WordPress with Barecity