Steppin’ Out: See You in Seattle »

Created at: 07.07.2011 02:20, source: Engine Yard Blog, tagged: community events cascasia rubyconf JRubyConf jrubykaigi OSCON RubyKaigi

Photo courtesy of Seattle Municipal Archives

It's summer time, and if you're anything like us, you're looking for some sweet Ruby conferences to put the cherry on top of this already awesome season. We had a great time at Structure and AWS Summit West, but we're getting back to our roots and heading North for two great events. First, our very own Wes Beary will be presenting about fog at OSCON July 27 in Portland, OR. If you'll be there too, be sure to give Wes a shout. If you're able to and track him down, you might be able to snag some fog swag. Then, we're heading up to Cascadia RubyConf July 29-30 in Seattle. The event is going to be radical, and it will be held right on the waterfront in beautiful Seattle --get your tickets to attend, or hop on the sponsor bandwagon before the event sells out. Sales end July 25. We couldn't be prouder of our own Shane Becker and his partner in organization, Ben Bleything, for putting together this awesome event. The slate of speakers includes such luminaries as Jim "Big Tiger" Remsik and Rich Kilmer, and Chad Fowler of Living Social. Finally, we'll also be in Tokyo for JRubyKaigi July 15 and RubyKaigi July 16-18, and then heading to our nation's fine capital for JRuby Conf August 3-5. We're cosponsoring JRubyConf again this year with our partner, EdgeCase Software, and LinkedIn. Keep your eye on @jrubyconf for details as they emerge!


more »

Ruby MRI, JRuby and Rubinius Throwdown Brodown »

Created at: 01.07.2011 01:34, source: Engine Yard Blog, tagged: community events Open Source jruby rubinius Ruby MRI Webinar

At RailsConf I had just given a thorough, yet humorous, overview of why everyone should run their production Ruby web applications on JRuby or Rubinius. I introduce into evidence exhibit A, the video replay of my 15 minute keynote. My beloved friend Aaron “Tenderlove” Patterson then stood up to give his own keynote and publicly rejected all my good advice with, "Ignore what Dr Nic said, [don’t use Rubinius or JRuby]. I’m on the MRI core team, so I think you should use that instead.” (paraphrased) Oh really, Aaron. This calls for a Ruby Platforms Virtual Brodown. I invite you all to join us for the webinar event. We’ve lined up a great panel of folks. Each awesome panelist will represent a different implementation: Ruby MRI, JRuby or Rubinius.

Ruby Platforms Virtual Brodown

Who: Aaron Patterson (Ruby MRI), Nick Sieger (JRuby), Brian Ford (Rubinius) and yours truly When: Thursday, July 21, 2011 from 10:00 to 10:50 AM Pacific Where: Online (WebEx) “Why should I attend? This sounds like it could get ugly...” some of you may be contemplating. Rightfully so. We know you have other options. Your 50 minutes could, very well, be better allocated to earning DJ points on turntable.fm, replying to heaps of email, or pondering summer getaways whilst billing hours. However, if you decide to join us, we’ll vow to leave you with a solid understanding of Ruby MRI, JRuby and Rubinius. More specifically, we will cover:
  • The Ecosystem: What works where, integrations and other capabilities to know about
  • Tooling: Profiling, debugging, monitoring, VPN introspection
  • Concurrency: Threading models and doing two things simultaneously
  • Windows: Life on planet Windows
  • Deployment: Sample stacks and how to run in production
We hope this laundry list of takeaways is enough to convince you to register to attend, or at least register to watch the recorded version we’ll email you post-event. Hope you can make it.


more »

Cloud Out Loud: Easy Listening »

Created at: 04.06.2011 03:51, source: Engine Yard Blog, tagged: community

With the weekend on the horizon, we'd like to leave you with some easy weekend listening. Nothing too intense, just a couple of recent Cloud Out Loud podcasts you might be interested to check out. Passionate folks ruminating on a variety of topics that move them in the Ruby, Rails, and open source space. Here are some recent episodes to get started with. Wesley Beary (geemus) muses on fog, the Cloud, Vibram Five Fingers and board games. Load Podcast Jeremy Hinegardner discusses Ruby 2.0, JRuby and MRI and the Boulder tech scene. Load Podcast Ron Evans talks about KidsRuby and the parallels between music and programming. Load Podcast We hope you enjoy 'em! If there is someone you want to hear from in an upcoming podcast, or if you're busy working on a cool new project you'd like to talk about, let us know. Drop us a line and let us know what you think.


more »

Using DataMapper and Rails with Legacy Schemas »

Created at: 01.06.2011 03:05, source: Engine Yard Blog, tagged: community Open Source Technology Tips & Tricks datamapper

Today's guest post hails from community contributor Piotr Solnica of Code Benders, an agile software collective based in Bend, Oregon. In his free time Piotr supports OSS, is a DataMapper core contributor, an author of DataMapper plugins and adapters and one of the developers of rubytime.org and coderack.org.
Ruby on Rails makes it easy to bootstrap a greenfield project. Unfortunately not all projects are greenfield, so sometimes you need to work with a legacy database schema. ActiveRecord is a great choice when you have a full control over your database from the very beginning, but what should you do if you need to connect to a database with a schema that isn’t in-line with Rails conventions? In this post I will explain how to setup a Rails application that uses DataMapper as the ORM. I'll also guide you through configuring your models to work with a legacy schema. If you are not familiar with DataMapper I recommend reading the “Getting Started” section of the official documentation.

A legacy schema

For the sake of this post let’s use an example schema of a blog application using MySQL:
CREATE TABLE `post` (
 `postId` varchar(45) NOT NULL,
 `postAuthorId` int(11) DEFAULT NULL,
 `postTitle` varchar(45) DEFAULT NULL,
 `postContent` text,
 `postPublishTime` varchar(45) DEFAULT NULL,
 PRIMARY KEY (`postId`),
) ENGINE=InnoDB DEFAULT CHARSET=utf8;     

CREATE TABLE `user` (
 `userId` int(11) NOT NULL AUTO_INCREMENT,
 `userName` varchar(45) DEFAULT NULL,
 `userEmail` varchar(45) DEFAULT NULL,
 PRIMARY KEY (`userId`)
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8;
Here’s what’s “wrong” with it:
  • table names are singularized
  • column names use camel-case naming convention prefixed with a table name
  • post primary key is an md5 sum of concatenated values of “author” and “publishTime”
  • post => user foreign key has a custom name “author”
  • “postPublishTime” is stored as a string and we would like to use DateTime object

Creating a rails application with DataMapper as ORM

This is actually a straight-forward task. All you need to do is to use a template provided by DataMapper when generating an application skeleton as follows: rails new blog-legacy -m http://datamapper.org/templates/rails.rb By default the skeleton uses sqlite as the database. To change that, simply edit Gemfile and change ‘dm-sqlite-adapter’ to ‘dm-mysql-adapter’ and run bundle install. To generate empty models run:
script/rails g model user
script/rails g model post

Naming conventions

DataMapper gives you two ways of defining table and column names. You can either set it manually in every model or you can configure global naming conventions for all models. Here’s how to set table and field names explicitly in the model:
class User
  include DataMapper::Resource
   
  storage_names[:default] = "user"     

  property :id,	Serial, :field => "userId"
  property :name,  String, :field => "userName"
  property :email, String, :field => "userEmail"
end
With many properties it would add clutter to our models, that is why it is better to set global naming conventions for resources and fields. Those conventions will be applied to every model and will eliminate the need to define storage names and set :field options for every property. To set global naming conventions, we can create datamapper.rb initializer like this:
# config/initializers/datamapper.rb   
Rails::DataMapper.configuration.resource_naming_convention[:default] = lambda do |name|
  name.downcase.singularize
end

# note: this will be available in dm-rails 1.1.1
Rails::DataMapper.configuration.field_naming_convention[:default] = lambda do |property|
  "#{property.model.name.downcase}#{property.name.to_s.camelize}"
end
Now we can clean up our User model like this:
class User
  include DataMapper::Resource     

  property :id,	Serial
  property :name,  String
  property :email, String
end
Much better!

Dealing with natural primary keys

In our example schema, a post’s primary key is an MD5 sum of concatenated fields “postAuthorId” and “postPublishTime”. If we want to have the value generated in Ruby we can use :default options in property declaration:
class Post
  include DataMapper::Resource     

  property :id, String, :key => true, :default => lambda { |resource, property|
	Digest::MD5.hexdigest("#{author}#{publish_time}") }     

  # ...
end
Now whenever you create a post and don’t provide :id it will be generated automatically based on the values of :author and :publish_time properties. As you can see this doesn’t look very nice in the model. So, we could create a custom property with a generalized functionality to clean this up! This way we can re-use this code in different scenarios whenever we want an MD5 sum of concatenated fields. You might be surprised how easy this is to do:
 module ::DataMapper
   class Property
     class MD5 < String
   	key	true
   	length 32     

   	accept_options :fields     

   	default lambda { |resource, property|
     	  Digest::MD5.hexdigest(property.options[:fields].join) }
     end
   end
 end
Now we can define post :id like this:
class Post
 include DataMapper::Resource     

 property :id, MD5, :fields => [ :author, :publish_time ]
end
How easy was that?!?

Associations with custom foreign keys

Our database has a basic 1:M relationship between User and Post models. The only caveat is that foreign key on post table pointing to user id has a name that doesn’t follow our global naming conventions. To configure the association we must override our defaults:
class User
  include DataMapper::Resource     

  property :id,	Serial
  property :name,  String
  property :email, String     

  # We need to set child_key otherwise DataMapper would use :user_id
  has n, :posts, :child_key => :author_id
end

class Post
  include DataMapper::Resource     

  property :id,	MD5, :fields => [ :author, :publish_time ]
  property :title,  String
  property :content, Text     

  # This creates a property called :author_id for you. We also set “User” as the parent model
  belongs_to :author, “User”
end
Easy enough.

Fine tuning - typecasting properties

Post :publish_time is a String property as values are stored in a VARCHAR column. Our goal is to work with DateTime objects, not strings. To achieve that we could simply override property accessor and do typecasting like this:
class Post
  # …     

  def publish_time
    DateTime.parse(super)
  end
end
While this approach works, it is not a recommended approach. DataMapper is based on the concept that a model’s logic should be decoupled from the database schema. A much better and cleaner way is to abstract away that logic in to a custom property object. An extra benefit comes with that too - you can re-use that code in many applications as it’s not tied to a specific model. Here’s another approach:
module DataMapper
  class Property
    class DateTimeString < String
      def load(value)
        ::DateTime.parse(value)
      end     

      def dump(value)
        value.to_s
      end
    end
  end
end
Better?

Wrap-up

All right! We’ve got all we need to work with our legacy schema. Let’s take a look at the final version of the models:
class User
  include DataMapper::Resource     

  property :id,            Serial
  property :name,  String
  property :email, String     

  has n, :posts, :child_key => :author_id
end     

class Post
  include DataMapper::Resource     

  property :id, MD5, :fields => [ :author, :publish_time ]  

  property :publish_time, DateTimeString
  property :title,    	 String
  property :content,  Text     

  belongs_to :author, "User"
end
At first sight it is hard to tell that the underlying database has a funky schema, isn’t it? These models look almost as if you were starting a fresh project. Let’s take a look at how we could work with them:
user = User.create(:name => "John Doe", :email => "john.doe@example.com")
=> #<User @id=2 @name="John Doe" @email="john.doe@example.com">
This creates a following insert statement:
INSERT INTO `user` (`userName`, `userEmail`) VALUES ('John Doe', 'john.doe@example.com')
Let’s create some posts too:
user.posts.create(:title => "Hello World!", :content => "DataMapper is awesome :)", :publish_time => DateTime.now)
=>  #<Post @id="4a585935e1d2dd21da146f6d3bcfc41b"  @publish_time="2011-05-12T13:39:04+02:00" @title="Hello World!"  @content="DataMapper is awesome :)" @author_id=2>
And SQL:
INSERT  INTO `post` (`postId`, `postPublishTime`, `postTitle`, `postContent`,  `postAuthorId`) VALUES ('4a585935e1d2dd21da146f6d3bcfc41b',  '2011-05-12T13:39:04+02:00', 'Hello World!', 'DataMapper is awesome :)',  2)

Further reading and resources

This post explains basics as well as some more advanced things you can do with DataMapper. If you would like to learn more, please take a look at the documentation, subscribe to the Mailing List or jump into the #datamapper IRC channel. Other useful links:
Author Bio Piotr Solnica is a team member at Code Benders, an agile software collective based in Bend, Oregon. When Piotr’s not writing great code, he’s writing awesome code. He has been working as a web developer for 6+ years and has solid experience with Ruby-based technologies and frameworks. His proficiencies include a range of JavaScript libraries such as Prototype, jQuery, YUI and MooTools. Piotr is an unobtrusive JavaScript evangelist, an HTML/CSS purist and a linux geek. In his free time he supports OSS, is a DataMapper core contributor, an author of DataMapper plugins and adapters and one of the developers of rubytime.org and coderack.org.


more »

Get your Rubinius T-Shirts and Stickers at RailsConf »

Created at: 12.05.2011 04:02, source: Engine Yard Blog, tagged: community Open Source rubinius swag

Hey kids, Rubinius is going to Baltimore! We've got a lot of rad stuff planned for next week, but wait -- there's more. Rubinius "Use Ruby™" TShirts at the Farmhouse in Hollywood, CA Photo by Tj Nelson Jr @tjnelsonjr It’s been a long time coming, but we’ve finally made some t-shirts and stickers for you to show your love and support of your Rubinius. Two different shirts and four different stickers, to be exact. “How do I get my grubby paws on one of those them there shirts?” That’s great question (if not a weird way to ask it). The answer is simple — go to the Engine Yard booth at RailsConf next week in Baltimore. We’ll have 500 shirts on hand and a giant pile of stickers. Both are free. You don’t have to sing for your supper. All you do is show up. “But I won’t be at RailsConf. How do I get one?” Don’t worry. We’ve got you covered. This first batch is all for RailsConf, but right afterward we’ll have lots more of this kind of stuff available. We’ll have a way for you to order them from us. Rubinius logo diecut sticker Stroll on over to the Rubinius blog to read all about it. See you in Baltimore (or not). If you will be in B'more, hit up Brian Ford (@brixen) to talk shop during Rubinius Office Hours. — Use Ruby™ PS. This is just the tip of the iceberg of what all we have planned. Stay tuned.


more »