Hello children! Today, we’re going to learn:
- How to get an edge rails app up and running with a redis backend
- How to create the familiar rails tutorial scaffold
- How to extend the scaffold to make a simple calendar system
Before you follow along this code – it turns out that we don’t have a happy ending, and actually are going to suffer for the v0.0.2 dm-redis-adapter we’re using. So read and enjoy, but don’t expect to get it working on your machine just yet.
A Running App
The first thing we need to do is get a valid rails3 app up and running. Luckily, Yehuda got this done for us, and so we can find it here: http://weblog.rubyonrails.org/2010/1/1/getting-a-new-app-running-on-edge (Also found http://yehudakatz.com/2009/12/31/spinning-up-a-new-rails-app/)
After that, we’ll need to tell rails that we’re going to use our own database framework, so we’re going to make our Rails.root/app/config/boot.rb look like this:
# require 'rails/all'
# To pick the frameworks you want, remove 'require "rails/all"'
# and list the framework railties that you want:
#
require "active_support/railtie"
require "active_model/railtie"
# require "active_record/railtie"
require "action_controller/railtie"
require "action_view/railtie"
# require "action_mailer/railtie"
# require "active_resource/railtie"
require "rails/test_unit/railtie"
I don’t plan on using active_resource for this app, so I’m going to leave that out. Then, delete your database.yml file (or keep it, to remember the bygone days.)
Also, if you comment out action_mailer be sure you go through your config/environments and delete out anywhere it says config.action_mailer, or you’ll crash.
After this is done, you should be able to run a basic script/server, and not have rails complain that you’ve done something wrong.
[alex-bartlows-macbook:: ~/Projects/rails3/redis_on_rails]
script/server
=> Booting WEBrick
=> Rails 3.0.pre application starting in development on http://0.0.0.0:3000
=> Call with -d to detach
=> Ctrl-C to shutdown server
[2010-01-30 13:40:14] INFO WEBrick 1.3.1
[2010-01-30 13:40:14] INFO ruby 1.9.1 (2009-07-16) [i386-darwin9.8.0]
[2010-01-30 13:40:14] INFO WEBrick::HTTPServer#start: pid=67476 port=3000
Woo!
Alright, now we’re getting somewhere. I’ll assume you’ve already installed Redis from http://code.google.com/p/redis/, and that you already have redis-server up and running happily in the background.
There are a couple options for your ORM. There’s an interesting project called ‘ohm’ (http://github.com/soveran/ohm) that I’ve forked (http://github.com/alexbartlow/ohm) to do some work in it’s associations, but it’s still in infancy, and it needs a bit more work until it’s fully production ready.
Datamapper, however, has a redis interface from whoahbot (http://github.com/whoahbot/dm-redis-adapter/), who is himself a luminous being, and looks like the ruby community’s _why replacement. Also, did you know there are no good GIS results for ‘Shekinah Glory?’
Anyway, so we’re going with datamapper. Let’s get it, and set up whoahbot’s adapter.
Add the following to your Gemfile:
gem "dm-core", "0.10.2"
gem "redis", "0.1.2"
And then run:
gem bundler
This is one of the most awesome things about Rails3. Native extension gems baked right into the app. rake:gems:freeze could be finnicky sometimes.
OK, now we need the adapter.
git submodule add git://github.com/whoahbot/dm-redis-adapter.git
vendor/plugins/dm-redis-adapter
I don’t know how you feel about git submodules, feel free to just copy the files. It might be a good call to keep these in your capistrano (http://capify.org) shared folder and just symlink to them. Anyway, you’re smart, and therefore capable of figuring this out yourself.
Finally, we’ll need to tell Rails to tell DataMapper that it should use Redis.
#config/initializers/datamapper.rb
require 'dm-core'
require 'dm_redis'
DataMapper.setup(:default, {:adapter => "redis"})
Setting up your model:
And so now we FINALLY can make a model.
touch app/models/person.rb
touch test/unit/person_test.rb
We’re using touch because the following doesn’t work:
[alex-bartlows-macbook:: ~/Projects/rails3/redis_on_rails]
script/generate model Person --orm=datamapper
error datamapper [not found]
But someday will!
In the true spirit of TDD, we will write some test cases before we write our application code.
require File.join(File.basename(__FILE__), '..', 'test_helper')
class PersonTest < ActiveModel::TestCase
include ActiveModel::Lint::Tests
setup do
@model = Person.create(:name => "Alex Bartlow")
end
end
This ensures that whatever model we create is compatible with the ActiveModel interface. Make sure redis is running, and run that muh!
Loaded suite /Users/bartlowa/Projects/rails3/redis_on_rails/test/unit/person_test
Started
FFFFFF
Finished in 0.101574 seconds.
Glorious failure! Lets make some of these pass.
#app/models/person.rb
require 'dm-validations'
class Person
include DataMapper::Resource
property :id, Serial
property :name, Text
def to_model
self
end
def self.model_name
self.to_s
end
validates_is_unique :name
end
I also needed to add the following to a rails initializer:
String.send(:alias_method, :human, :humanize)
String.class_eval do
def partial_path
self.downcase.pluralize << '/' << self.downcase.singular
end
end
Though this should really be default on ActiveSupport’s monkeypatching of String.
Now we should be able to play with our Person in a script/console.
irb(main):005:0> Person.create(:name => "Whoahbot!")
=> #<Person @id=63 @name="Whoahbot!">
irb(main):006:0> Person.get(63)
=> nil
irb(main):007:0>
Crap! Looks like the dm adapter is borked. Or I’m just doing something wrong.
Anyone have any suggestions? Otherwise I’ll have to tweak whoahbot’s stuff and/or re-implement a dm adapter. Looks like it might not be that hard (http://www.theamazingrando.com/blog/?p=95)