Showing posts with label rails. Show all posts
Showing posts with label rails. Show all posts

Sunday, June 13, 2010

How to generate forms in rails helpers

This is more of a note to myself than anything, since I find myself having to generate forms from helpers in Rails every once in a while. This is for Rails 2.3.5. I don’t know if Rails 3 has this problem.

I wrote my own in-place editor for model fields, and it generates a form through a helper.

 1 # used internally to generate the form for the en_place editor  2 def en_place_form(record_or_array, field_name,   3                   options = {}, html_options = {})  4   # process the options, and other misc details  5   form_block = proc do  6     form_for(record_or_array, :html => html_options) do |f|  7       concat(f.text_field field_name, :class => "en_place")  8       concat(f.submit "Update")  9     end       10   end 11   is_haml? ? capture_haml(&form_block) : capture(&form_block) 12 end

All you have to do is capture a block that calls form_for or form_tag. And then inside of the form, you can to call concat on the fields that you want inside of the form.

Then lastly, you have to capture the block. If you’re using haml, you have to call capture_haml() instead.

Posted via web from The Web and all that Jazz

Wednesday, August 19, 2009

Sending HTML emails with attachments in Rails

Here's something you might have missed in Rails.

From ActionMailer's Documentation:

Implicit template rendering is not performed if any attachments or parts have been added to the email. This means that you‘ll have to manually add each part to the email and set the content type of the email to multipart/alternative.

If you want to have pretty html templates and have an attached file, you can't just set the content_type to "text/html" and call attachment. You need to do it separately, like so:




There, now you can have html and your attachments too. Reference: http://am.rubyonrails.org/classes/ActionMailer/PartContainer.html#M000006


Wednesday, May 27, 2009

How to add helpers, controllers, models, and views of your plugin into the Rails loadpath


Sometimes, when you're writing a plugin, you end up writing models,
helpers, and controllers that the main app can use.  However, you
don't want to copy it into the main app all the time.  You'd like to
keep things separate between the plugin, but you'd like to be able to
include it in the path of the main app.

To do this, put the following in your init.rb file in the root
of your plugin.  To add a new view path in your plugin that's at
PLUGIN_ROOT/lib/views (where PLUGIN_ROOT is the root directory of your
plugin):


ActionController::Base.append_view_path(File.join(PLUGIN_ROOT, "lib", "views"))


Any template files (like html.erb) that you put in that path will be
seen in your app.

To add new helper, model, or controller directories in the rails load path:


%w{ helpers model controller }.each do |dir|
path = File.join(PLUGIN_ROOT, 'lib', dir)
$LOAD_PATH << path
Dependencies.load_paths << path
Dependencies.load_once_paths.delete(path)
end


And now, any models you put in lib/model, lib/controller, and
lib/helpers will be in the rails load path.

Of course, this might all be moot with the reintroduction of Rails
engines in 2.3.  I haven't gotten around to using them or figuring it
out yet, but for now, this is how you do it with plugins.  tip!

Posted via web from The Web and all that Jazz

Thursday, March 19, 2009

Bastardized recursion

I seem to be posting less. I've been thinking about why that is. Perhaps, less things are surprising to me now (i.e. I'm not learning as much as before). When doing this Rails stuff, the bulk is standard fare, and only occasionally do you run into something mildly interesting. I have been queuing up posts, however. Between work, small side projects, reading, and hanging, there's less time than before.

I stumbled on something, which I saw in the Rails source once. Thought I'd share.

Say I have a :blog that has_many :posts. But Posts are subclassed to have many different types. But I wanted that post_type information from Blog in different formats. Originally, it looked something like this

class Blog
has_many :posts

def post_types
Post.subclasses
end

def post_names
post_types.map { |pt| pt.name.gsub('Post::','') }
end

def post_string
post_names.map { |n| "'" + n + "'" }.join(",")
end
end

Since they progressively built off of each other, I figured I can use a bastardized recursion, like I saw in find() in ActiveRecord::Base.

class Blog
has_many :posts

def post_types(format = :classes)
case format
when :classes
Post.subclasses
when :names
post_types(:classes).map { |pt| pt.name.gsub('Post::','') }
when :string
post_types(:names).map { |n| "'" + n + "'" }.join(",")
end
end
end


Seems alright. Reduces the clutter of functions that are related to each other, so I'm on the lookout for being able to reduce related functions together like that. tip~!

Updated:
Found this reverse engineering brief on obfuscated code that recites the 12 days of Christmas. It uses the same technique that I described above. I suppose as always, case statements can be abused.

Wednesday, September 10, 2008

Anonymous scope, the unknown cousin of Named scope

Last time, I showed you the well known named scopes. This time, I'll talk about the little documented anonymous scopes.

Anonymous scopes were mentioned briefly on Ryan's Scraps. And in the API, I found it tucked away in ActiveRecord::NamedScope module documentation.
All subclasses of ActiveRecord::Base have two named_scopes:
  • all, which is similar to a find(:all) query, and
  • scoped, which allows for the creation of anonymous scopes, on the fly:
    Shirt.scoped(:conditions => {:color => ‘red’}).scoped(:include => :washing_instructions)
These anonymous scopes tend to be useful when procedurally generating complex queries, where passing intermediate values (scopes) around as first-class objects is convenient.
How would this be useful? In the example given, it's really not. And most of the time, what you need to do will suffice with named scope. However, there are times when named scope doesn't give you the flexibility that you need, and it is actually quite powerful when it's used in conjunction with association proxies.

I was using the better nested set plugin. It allows you to have a fast access tree structure in a relational database. And while it's a neat plugin, I couldn't chain my calls like such:
@father.subtree.with_email  # => fails

to find all the father's descendants that had an email. That's because subtree() exists in the plugin and it uses find(), and that returns an array of objects. You can't further extend the call, because by find returns an array, not an association proxy.

In our association proxies, if we expect to chain the calls, we can use scoped() instead of find(). Just to demonstrate:
class Person < ActiveRecord::Base
has_many :people do
def subtree
scoped(:conditions => ["lft between self.id and self.id", self.lft, self.rgt])
end
end

named_scope :with_emails, :conditions => ["email is not null"]
end

That means we would be able to change other scoped after subtree():
@father.subtree.with_emails # => returns all children

There's not much to it, but it's nice when, once again, you're into breaking Law of Demeter.

tip!

Wednesday, August 06, 2008

Named scope, how do I love thee

I'm not sure how I missed it, but named_scope is something that I've been looking for. I should really read more of Ryan's scraps. Just in case you don't know, named_scope is a way to add filters and conditions to the finder methods on your model.

There's a couple other hipper rails programmers that have covered it months ago, so I'll defer to original author and the aforementioned Ryan and his table scraps to tell you about the basic things you need to know. This functionality has been absorbed into Rails 2.1 and you can find it under the method name, named_scope.

In this post, I'll talk about some of the uses I've found for it. There's more code posting in this one than usual, but it's incremental, so all you have to do is notice what's different between the sets of code examples.

Lately, I've found that I needed to mix and match different kinds of conditions in my finder methods in my models. Let's say we have articles each that have many comments. How do we find comments that have an email address? How about if we wanted articles with a url address included in the comment post? We could make another has_many association.


class Article < ActiveRecord::Base
has_many :comments, :order => "comments.created_at desc"
has_many :comments_with_email,
:conditions => "email is not null",
:order => "comments.created_at desc"
has_many :comments_with_url,
:conditions => "url is not null",
:order => "comments.created_at desc"
end

class Comment < ActiveRecord::Base
belongs_to :article
end

Or instead of cluttering things up in the class namespace, we can use an association proxy extension so that instead of calling @article.comments_with_email, we can call @article.comments.with_email (and violate Law of Demeter)

class Article < ActiveRecord::Base
has_many :comments, :order => "comments.created_at desc" do
def with_email
# we can do it this way
with_scope(:find => { :conditions => "email is not null",
:order => "comments.created_at desc" }) do
find(:all)
end
end

def with_url
# or we can do it this way
find(:all, :conditions => "url is not null",
:order => "comments.created_at desc")
end
end
end

class Comment < ActiveRecord::Base
belongs_to :article
end

This is all fine and well, until you need to find all comments with emails and url. You can make finders that take arguments, but entertain the following possibility. find() in the association proxy extensions actually return an Array, so you cannot chain them, like @article.comments.with_email.with_url

How do we do this? named_scope() is one way to do it.

class Article < ActiveRecord::Base
has_many :comments. :order => "comments.created_at desc"
end

class Comment < ActiveRecord::Base
belongs_to :article

named_scope :with_email, :conditions => "email is not null"
named_scope :with_url, :conditions => "url is not null"
end

That means you can do things like

@article.comments.with_email

Or you can actually call count(), so that the sql is calling a count instead of instanciating all the active record objects in an array then calling size, which is much faster:

@article.comments.with_email.count

Not only that, but if there are other models that associate with comments, you have the scoping filters in one place in the code.

class User < ActiveRecord::Base
has_many :comments, :order => "comments.created_at desc"
end

class Article < ActiveRecord::Base
has_many :comments. :order => "comments.created_at desc"
end

class Comment < ActiveRecord::Base
belongs_to :article
belongs_to :user

named_scope :with_email, :conditions => "email is not null"
named_scope :with_url, :conditions => "url is not null"
end

So not only can you find all comments with both email and url for an article, you can do the same for users:

@article.comments.with_email.with_url # all comments with email and url of an article
@user.comments.with_email.with_url # all comments with email and url by a user

Therefore, if you have common intersecting conditions that you need to do, like all the comments in a period of time for an article, named scope will help. For, I'd like to be able to call:

class User < ActiveRecord::Base
has_many :comments, :order => "comments.created_at desc"
end

class Article < ActiveRecord::Base
has_many :comments. :order => "comments.created_at desc"
end

class Comment < ActiveRecord::Base
belongs_to :article
belongs_to :user

named_scope :with_email, :conditions => "email is not null"
named_scope :with_url, :conditions => "url is not null"
named_scope :in_period, lambda { |start_date, end_date|
{ :conditions => ["respondents.created_at >= ? and " +
"respondents.created_at <= ?",
start_date, end_date] }
}
end

So now we can call:

@article.comments.in_period(@start_date, @end_date)
@article.comments.with_email.in_period(@start_date, @end_date)


Cool you say! Now before you go back into your code and start replacing all of your stuff with named_scopes, keep in mind that there are edge cases where named_scopes wouldn't be appropriate. I fell into the trap of thinking that I could used named_scope for everything like a kid that found a new hammer, the world looked like a nail. So I spend more time than I should trying to bend named_scope to my will.

One of the things that fails is that there is no way (as far as I know) to override named scope conditions, like with_scope, outside of going into rails and messing with it and submitting a patch.

For example, if we already have an association of comments with the article that sorts in descending order, we cannot have named scopes that ask for the earliest and latest article using named_scope.

class Article < ActiveRecord::Base
has_many :comments. :order => "comments.created_at desc"
end

class Comment < ActiveRecord::Base
belongs_to :article

named_scope :earliest, :order => "comments.created_at asc",
:limit => 1
named_scope :latest, :order => "comments.created_at desc",
:limit => 1
end

This won't work because named_scope assumes that you'd want to merge all the conditions throughout the entire chain.

@article.comments.latest # will work because the sql will look like:
# SELECT * FROM `comments`
# ......blah blah....
# ORDER BY respondents.created_at desc,
# respondents.created_at desc
# LIMIT 1

@article.comments.earliest # will not work because the
# SELECT * FROM `comments`
# ......blah blah....
# ORDER BY respondents.created_at desc,
# respondents.created_at asc
# LIMIT 1

Next time, I'll cover named_scopes cousin that's not very documented, so it's easy to skip over: anonymous scopes.

Tip!

Tuesday, March 04, 2008

Foxy Fixtures and polymorphic tables

Well, I'm behind on everything, which means a bunch of interesting blog posts are queued up. But this one seemed short enough to warrant a small post.

I've always hated fixtures for the same reason that other people hate them, but nonetheless, I've bit the bullet to use them. Along comes Rails 2.0's foxy fixtures, and it becomes a little easier.

What it doesn't detail, however, is how to use your newly foxy fixtures for polymorphic models. If I have a vote model that I can use to vote on any type of table, with the old fixtures, I'd have:

my_vote:
id: 1
account_id: 1
votable_id: 3
votable_type: "Scene"

Normally, you just get rid of the foreign keys since it now checks the belongs_to associations of each model, and you can just use the label names. Same goes with the primary key id. It'll be autogenerated based on a hash of the fixture label.

my_vote:
account: my_account
votable: eat_hotdog
votable_type: "Scene"

Note that you're using the association names, and NOT the foreign key name, so you don't use "_id" anymore (that bit me in the ass for a little bit).

However, you'll find that with polymorphic models, you won't be able to do that. Searching around the good 'ole web lead me to find that Foxy Fixtures originally came from a plugin called Rathole, and at the very end of the README, it states:
Also, sometimes (like when porting older join table fixtures) you'll need to be able to get ahold of Rathole's identifier for a given label. ERB to the rescue:

Go John Barnette! That way, you can simply do this in your fixtures as a fall-back:

my_vote:
account: my_account
votable_id: <%= Fixtures.identify(:eat_hotdog) %>
votable_type: "Scene"

Tip!

Tuesday, February 26, 2008

Testing MIME response types

I feel like I might have covered this before, but I was looking for a way to test respond_to. I had found this post on how to test it, but after looking at it for a while, I found myself rewriting it. Mainly, I took out parts that convert the Mime types, and inserted Rail's own Mime type objects. You can use it like this:


request_mime(:fbml) do
get :list
assert_response_mime(:fbml)
end

request_mime("text/xml") do
get :list
assert_response_mime("text/xml")
end


Just include it in your test_helper.rb file in test/

class Test::Unit::TestCase
include Threecglabs::MimeTestHelpers
end


Here's "mime_test_helpers.rb". Just throw it in lib/

module Threecglabs
module MimeTestHelpers

def self.included(mod)
mod.class_eval do
include MimeRequest
include MimeAssertions
end
end

module MimeRequest
# changes the mime type of the request within the block
#
# request_mime(:fbml) do
# get :list
# assert_response_mime(:fbml)
# end
def request_mime(mime_type_name_or_extension)
if mime_type_name_or_extension.kind_of?(String)
mime_type = Mime::Type.lookup(mime_type_name_or_extension)
elsif mime_type_name_or_extension.kind_of?(Symbol)
mime_type = Mime::Type.lookup_by_extension(mime_type_name_or_extension.to_s)
else
raise ArgumentError.new("mime type must be string or symbol")
end
old_mime_type = @request.accepts
@request.accept = mime_type.to_s
yield
@request.accept = old_mime_type
end
end

# These are assertions to test respond_to, whether they return a specific mime type
# as a response to a request
module MimeAssertions

# Helps out with response testing, by letting to assert that the most recently-made
# request responded with a particular MIME extension, like :html, :fbml, :xml, etc.
def assert_response_mime(expected_mime_type_ext)
expected_mime_type = Mime::Type.lookup_by_extension(expected_mime_type_ext.to_s)

# Mime::Type.parse doesn't parse accept parameters correctly, therefore
# we account for having multiple types in the accept
response_mime_types = @response.headers['type'].split(/,\s*/).map do |accept_type|
mime_type_name = accept_type.split(/;\s*/).first
Mime::Type.parse(mime_type_name)
end
assert_block("Responded with #{response_mime_types.map(&:to_s).inspect} when expecting #{expected_mime_type}") {
response_mime_types.any? { |response_mime_type| expected_mime_type == response_mime_type }
}
end

end
end
end

Snippet!

irb console tricks

irb Mix Tape — err.the_blog

Not a big entry, but I think worth posting because it pays to learn your tools. I've got no insights of my own to add. Someone else's tip!

Wednesday, February 20, 2008

Render_to_string only counts if failed

render_to_string followed by render issues - Ruby Forum

I was puzzled by this yesterday, and good thing I went to do something else instead of tearing my hair out. Came back fresh today and found this. Apparently, render_to_string normally doesn't count as a render--given that it succeeds. If it throws an exception for some reason, then it'll get count as a double render if you rendered elsewhere. Small tip!

Wednesday, February 13, 2008

MIME responder filter for Rails

I didn't think I had to do this, but I ended up writing a filter that acts like a switch statement for different MIME types. Let me explain. Normally, in Rails, you can respond to different requests for different content with something like this:

class PostController < ActionController::Base
def list
@posts = Post.find(:all)
respond_to do |format|
format.html
format.fbml
format.xml { render :xml => @people.to_xml }
end
end
end

When you have something like this, the browser (or whatever client) can ask for different MIME types. Here, we can return html to a browser, xml to maybe a data importer, and fbml to facebook.

I spent last week integrating Mobtropolis with facebook. Mobtropolis doesn't require a facebook account to use it, so like other websites, it has its own authentication mechanism, something like:

class PostController < ActionController::Base
before_filter :website_authenticate_filter, :except => [:index, :list]
end

When I started using facebooker library, it already came with an authentication before_filter. That means we have two authentication filters, one native, and one for facebook. Mobtropolis users don't have to be in facebook to use it, and facebookers don't have to sign up again in mobtropolis to use it.

However, since before_filters are executed in succession, it leads to a case where the facebook authentication would be called if html was requested, and vice versa. The alternative was to take apart both authentication filters, and create a monolithic filter to handle the two different cases. Instead, I did this:

class PostController < ActionController::Base
before_respond_to_filter :except => [ :index, :list ] do |format|
format.html :website_authentication_filter
format.fbml :facebook_authentication_filter
end
end

That way, I didn't have to mix together the guts of each authentication filter, and it solved the problem of the wrong authentication filter being run. You can also use it like:

class PostController < ActionController::Base
before_responds_to_filter :only => :home do |format|
format.html do |controller|
return if controller.logged_in?
controller.send(:redirect_to, :controller => :home)
end
format.fbml :ensure_application_is_installed_by_facebook_user
end
end

By the way, I tried to alter the filter_chain as a request came in. Filter chains are copied and passed around the filters, so you can't write a filter that alters the filter chain. So don't waste your time crawling around in the guts of Rails to do this like I did. It's just as well, as that'd be a nightmare to maintain.

It does have some weaknesses though. You can only assign the filters to the same set of :except and :only options in the filters.

It ended up the code for this sort of magic was fairly easy. I'm not sure if there's an easier way to do what I wanted, but I'll see if Rails core people would find it useful (or not). In the meanwhile, for those of you Rubyists that have written plugins before that want to play with it. As with the usual mumbo jumbo, it's provided as is, I'm not maintaining it, and do whatever you want with it:


module Threecglabs
module Filters

# MimeResponderFilter
module MimeResponderFilter

def self.included(mod)
mod.extend(ClassMethods)
end

# Filters can respond to different mime types, so that you can use
# different filters depending on which mime type is being requested
#
# before_responds_to_filter :except => [:login, :signup, :forgot, :invite_request, :profile] do |format|
# format.html :authentication_filter
# format.fbml :ensure_application_is_installed_by_facebook_user
# end
#
# This way, one can take the appropriate actions in setting up authentication
# from different mime types, and still separate the implemenation of the different
# kinds of implementations
#
# The formats also take blocks, like regular filters
#
# before_responds_to_filter :only => :home do |format|
# format.html do |controller|
# return if controller.logged_in?
# controller.send(:redirect_to, :controller => :home)
# end
# format.fbml :ensure_application_is_installed_by_facebook_user
# end
#
# NOTE: an :all format defaults to :html, therefore, a format.html is required
module ClassMethods
def before_respond_to_filter(options = {}, &block)
before_filter MimeResponderFilter.new(&block), options
end

private
# This is a call that implements a MIME responder filter
class MimeResponderFilter#:nodoc:
attr_reader :filters

def initialize(&block)
@filters = {}
block.call(self)
end

def filter(controller)
filter = @filters[controller.request.format.to_sym] || @filters[:html]
if filter.kind_of?(Proc)
filter.call(controller)
else
controller.send!(filter)
end
end

# implements the "format.#{mime_type}" part of the filter
def method_missing(mime_type, method_name = nil, &block)
if block_given?
@filters[mime_type.to_sym] = block
else
@filters[mime_type.to_sym] = method_name.to_sym
end
end
end
end

end
end
end


Snippet!

Sunday, January 27, 2008

Making sure extra tasks get run when installing plugins with Piston

When I graduated college, I was a EE major that could code. However, in hindsight, I don't think I was as good because I had no idea how to put together moderate sized systems or above. One of the things that I like about Rails is that they have a system for plugins. I was too uncouth to consider it before. Once you extract a plugin out, you essentially have to treat it as a separate library or package. This forces you to encapsulate, because it's a bit of a pain changing plugins. I know you can extract code out to DLLs or Gems, but I never did it because it seemed like I didn't need it--plus it was extra steps.

I eventually would want a programming language that lets me extract out libraries inside the language, and make its public interface RESTful, and auto-extern its path in SVN and whatever the equivalent is in distributed version control like git/darcs.

Recently, I've started using Piston. It's a ruby plugin manager that's essentially a wrapper around svn:externals. It's been pretty easy to use. In addition, my plugins won't get stale. However, when you install a plugin with piston, you only import the files. It doesn't actually execute the install.rb file, like /script/plugin install would. I'll try to see if I can submit a patch to piston later, but for now, simply run "install.rb" in the root of the plugin, and it should do the install for you. small tip!

Thursday, January 24, 2008

Setting time in your fixtures

In your rails fixtures, you should be able to set the time dynamically. If you set your database to default to UTC, make sure you use:

post:
id: 1
body: "This is my witty post"
created_on: <%= 3.days.ago.utc.xmlschema %>

Unless you want to wreck havoc in your test cases. tip!

Wednesday, January 02, 2008

DRYing up your views with a TableBuilder

In the last two months, when I was adding more features to mobtropolis, I found it painful to try and lay things out all over again from scratch. As a result, it sucked to see ugly layouts on the new pages juxtaposed with all the styling I had done before. It wasn't until a week ago that I said to myself, "Stop the madness!" and started refactoring my views--something I never thought of doing much of until now. When you don't, the barrage of angle brackets blows out of proportion and it starts to look pretty damn fugly with complex views.

What I should be able to do is take common mini-layouts in my views and make them available as helpers so that I can think in terms of bigger chunks to piece together pages, rather than in divs and spans. In addition, it makes your interface more consistent for your users.

Some good resources were presentations from the 2007 RailsConf, like V is for Vexing and Keeping your views DRY. While a lot of view DRYing talks about form builders, I didn't see any on table builders, so I decided to take a stab at it. Personally, I don't like to overuse tables for layouts. But as certain elements in my page layouts have been repeated, I refactored them into first helpers, and then when I did more than one, I extracted it out into a simple table builder. This is how you'd use it:

For example, I have a mini-layout where I show simple stats:


Here's how I used a simple table builder to display the above:

<% score_card do |sc| -%>
<% sc.placard("Votes", "", num_voters, "") -%>
<% sc.placard("Sceneshots", "", num_sceneshots, "")-%>
<% sc.placard("Participants", "", num_participants, "") -%>
<% sc.placard("Challenges","", num_challenges, "") -%>
<% end -%>

And I find that I started using the same sort of thing in other places, like in a user's profile:



<% score_card do |sc| -%>
<% sc.placard("Submitted Scenes", "", num_scenes, "") -%>
<% sc.placard("Submitted Sceneshots", "", num_sceneshots, "") -%>
<% end -%>

I cut out some details so you can see that it's just a block that gets passed a ScoreCard object, from which you call placard to add another score to the score_card. It sure beats writing <table> and <td> over and over again.

To declare the helper, we create a helper with the structure of the table inside the declaration of a ScoreCard object. We have a ScoreCard object to hold the contents of the placards. When they're called in the block above in the template, they get stored in the ScoreCard object, and not written out to erb immediately. That way, we can place them wherever in the table we please, by making the call to card.display(:placards):

module ScorecardHelper
def score_card(html_options = {}, &block)
options = { :class => :scorecard, :width => "100%" }.merge(html_options)
ScoreCard.new(block) do |xm, card|
xm.table(options) do
xm.tr(:valign => :top) do
xm << card.display(:placards)
end
end
end
end
end

So then what's ScoreCard look like? Pretty simple. It has a call to each cell that can be filled in the mini-layout. It's kinda analogous to how form_for passes in a form object, on which you can call text_field, etc.

require 'lib/table_builder'

# Used to create a scorecard helper
class ScoreCard < TableBuilder
cells :placards

# a placard is placed into scorecards
def placard(text, text_id, score, widget)
xm = Builder::XmlMarkup.new
@placards[:html] += xm.td do
xm.span(:style => "font-size: 1.2em") { xm << "#{text}" }
xm.em(:id => text_id, :class => "primary_number") { xm << "#{score}" }
xm << "#{widget}"
end
end

end

Notice that there's a call to cells() to initialize the type of cell, and a method of the same name that builds the html for that cell. If you have other types of cells, you simply put it in the list of cells, and then create a method for it that is called in the template. By convention, you'd stick the html of the cell contents in "@#{name_of_cell}"[:html], and if you wanted, pass in the html_options, and stick it in "@#{name_of_cell}"[:options]. Then, you can access those in the helper wherever you want.

Let's try another one. I have a mini_layout with a picture, and some caption underneath it, like a polaroid.


<% polaroid_card do |p_card| -%>
<% p_card.picture do -%>
<%= sceneshot_for scene -%>
<% end -%>
<% p_card.caption do -%>
<%= pluralize(scene.num_of_sceneshots, "sceneshot") %>
<% end -%>
<% end -%>

The associated helper and PolaroidCard object are pretty simple:

module PolaroidCardHelper
# a polaroid card is used to show a picture with a caption below it.
def polaroid_card(html_options = {}, &block)
options = { :class => :polaroidcard, :style => "display: inline;" }
PolaroidCard.new(block) do |xm, card|
xm.table(options) do
xm.tr { xm.td(card.html_options(:picture)) {
xm << card.display(:picture)
}}
xm.tr { xm.td(card.html_options(:caption).merge(:class => "caption")) {
xm << card.display(:caption)
}}
end
end
end
end


require 'lib/table_builder'

class PolaroidCard < TableBuilder
cells :picture, :caption

def picture(html_options = {}, &block)
@picture[:html] = capture(&block)
@picture[:options] = html_options
end

def caption(html_options = {}, &block)
@caption[:html] = capture(&block)
@caption[:options] = html_options
end
end


I've tried to pull all the plumbing out into TableBuilder (dropped it into lib/), and only leave the flexibility of creating the table structure in the helper, and the format of the cell in the object. It ends up TableBuilder isn't too complex either. It uses some metaprogramming to create some instance variables. I know it pollutes the object instance variable namespace, but I wanted to be able to say @caption[:html], rather than @cells[:caption][:html].


class TableBuilder < ActionView::Base
class << self
# used in the child class declaration to name and initialize cells
def cells(*names)
define_method(:initialize_cells) do
@cell_names = names.map { |n| "@#{n}".to_sym }
@cell_names.each do |name|
if instance_variable_defined?(name)
raise Exception.new("name clash with ActionView::Base instance variables")
end
instance_variable_set(name, { :html => "", :options => {} })
end
end
end
end

def initialize(decor_block, &table_block)
super
initialize_cells
decor_block.call(self)
html = table_block.call(Builder::XmlMarkup.new, self)
concat(html, decor_block.binding)
end

def display(cell_name)
instance_variable_get("@#{cell_name}")[:html]
end

def html_options(cell_name)
instance_variable_get("@#{cell_name}")[:options]
end

end


I've found have these helpers cleans up my views significantly, though I have to admit, it's not exactly easiest to use yet. In addition, I'm not exactly thrilled about having TableBuilder inherit from ActionView::Base, but it was the only way I could figure out to get the call to concat() to work. In any case, the point is to show you that refactoring your views into helpers is a good idea, and even something like a table builder goes a long way, even if you don't do it the way I did it. Lemme know if this helps or hinders you. snippet!

Tuesday, December 18, 2007

(Aha!) Part of the reason why great hackers are 10 times as productive

I knew in college that some dudes were faster than I was in terms of programming. Since peer programming wasn't exactly encouraged in college, and at work I did mostly prototyping work, I never really knew how fast other programmers worked.

So when I read Paul Graham (and Joel's) claim that great hackers are at least ten times as productive as average programmers (too lazy to cite right now), I was kinda shocked. Surely, ten times is an order of magnitude! Something that takes an average programmer a 40 hour week to do the great hacker can do in a 4 hour afternoon?

I wondered about that, since there are times when I get stuck on something, then I just start stabbing around randomly out of frustration. I had assumed that great hackers were faster only because they had either the experience or insight to side-step whatever I was doing wrong.

But lately, I've been re-reading everyone's essays that write about programming productivity. And one thing that caught my eye the second time around was when Paul Graham was talking about bottom up programming and how he didn't really believe in objects, but rather, he bent the language to his will. He was building new blocks for himself so he could think about the problem at a higher level of abstraction.

This is basic stuff! I mean, that's the whole point of higher-level programming. When you refactor methods out, you're creating a vernacular so that you can express the problem in terms of the problem domain, not in terms of general computing. This is much like if you want to drive a car, you'd want to be able to step on the gas, rather than time the firings of the pistons. And if you want to control traffic in a city, you'd rather tell all cars to go to a destination, rather than stepping on the gas and turning the steering wheel for each one.

But taken into the light of bending a language to your will, it makes it more clear for me as to how great hackers are ten times as productive. Great hackers are productive not only because they know what problems to sidestep and can problem solve systematically and quickly, but they also build a set of tools for the problem domain as they go along. They are very good pattern recognizers and will be able to generalize a particular pattern of code, so that they can use it again. But not only that, great hackers will create an implicit understanding attached to the abstraction, ie. what we might call common sense.

A case in point. Before Ruby, I'd used for loops over and over again, never really thinking that I could abstract a for loop. It wasn't until they were taken away in Ruby did I realize that map, inject, and their cousins are all abstractions of the for loop. When I see "map" I know that it performs a transformation on every element. But I also know that the array I get back will be the same size, that each element operation doesn't affect other elements, among other things. These are implicitly stated, and they allow for shorter code.

When that happens, you can simply read "map", and get all the connotations it comes with, and hence it comes with meaning. It also becomes easier to remember, since it's a generalized concept that you can apply in different places in the code. The more times you use it, the easier it is to remember, instead of having specialized cases of the same kind of code where the behavior is different in different parts of the code.

A great hacker will take the initial time upfront to create this generalized code, and will save in the long run being able to use it. Done over and over again, it all adds up. So it's not that for any given problem, a great hacker will be done in 4 hours what it takes an average programmer 40 hours, but that over time, a great hacker will invest the time to create a tools and vocabulary that lets him express things easier. That leads to substantial savings in time over the long haul.

I hesitated writing about it, as it's nothing I (nor you) haven't heard before. But I noticed that until recently, I almost never lifted my level abstraction beyond what the library gave me. I would always be programming at the level of the framework, not at the level of the domain. It wasn't until I started writing plugins for rails extracted from my own work and reading the Paul Graham article that a light went off for me. It was easier to plug things like act_as_votable together, rather than to still mess around with associations (at the level of the framework). I still believe you should know how things work underneath the hood, but afterwards, but all means, go up to the level of abstraction appropriate for the problem domain.

DSLs (Domain specific languages) are really just tool-making and vernacular creation taken to the level of bending the language itself. It's especially powerful if you can add implicit meaning to the vernacular in your DSL. It's not only a way of giving your client power in their expression, but it's also a refactoring tool so that you can better express your problem in the language of the problem domain. Instead of only adding methods to your vernacular, you can change how the language works. It was with this in mind that I did a talk on DSLs this past weekend at the local Ruby meetup. First part is on Dwemthy's Array, and the second is using pattern matching to parse logo. Both seemed pretty neat when I first read about it. Enjoy!




DSL in Ruby through metaprogramming and pattern matching

Tuesday, December 11, 2007

The user owns this and that

In most any community-based website, your users are creating objects. And sometimes, you'd only like to display them when they're owned by the user. Usually, it's easy enough to do the check based on the association in the template views.

<% if @story.account == session[:member] %>
<%= render :partial => "story"
<% end %>

However, for the sake of perhaps over-reaching, but something more readable, we try:

class Story < ActiveRecord::Base
belongs_to :account

def owned_by?(user)
self.account == user
end
end


<% if @story.owned_by?(session[:member]) %>
<%= render :partial => "story"
<% end %>

But this gets to suck, because you have duplicate code in different classes that are just slightly different due to association names. One way to solve it is to put it in a module, and include it in different classes. After all, that's what mixins are for.

module Ownership
def owned_by?(user)
self.account == user
end
end

class Story < ActiveRecord::Base
include Ownership
belongs_to :account
# blah blah blah
end

class Post < ActiveRecord::Base
include Ownership
belongs_to :account
end

Or alternatively, you can put it in the account, but in reverse. But now, you have to search through the associations of the owned ActiveRecord object.

class Account < ActiveRecord::Base
def owns?(ar_object)
ar_object.class.reflect_on_all_associations(:belongs_to).detect { |assoc|
ar_object.send(assoc.name) == self
} ? true : false
end
end

I find the tertiary operator to be kinda ugly there, but it doesn't make sense to return the reflection object. Regardless, this lets you do:

<% if session[:member].owns?(@story) %>
<%= render :partial => "story"
<% end %>

However, this doesn't work for self-associated AR objects, or objects that have two or more belongs_to to the same account. It relies on a unique belongs_to association for every object belonging to account. I'm not sure yet, which way's the better way to go, and in the end it probably doesn't matter as much, but I do like being able to say user.owns?(anything) for any object without really thinking about what the associations are. half-tip.

Thursday, December 06, 2007

Communicating your intent in Ruby

I've been using Ruby most everyday for about two years now. While I'm no expert, I know enough to be fairly productive in it. And beyond liking the succinctness and power that you often hear other people talk about, it's made me a better programmer. But there's an aspect of Ruby that worries me somewhat.

To start, programming is recognized rightfully as a means to build something from pure thought. But it's also a form of communication, to other programmers that will touch your code later, and to yourself when you look at it months from now. We're at a point that other than embedded and spacecraft programming, we have the luxury of using programming languages that focus ease for the programmer, rather than for the ease of the machine. Fundamentally, that's the philosophy that Ruby takes.

And while Ruby's nice in a lot of ways, I'm not sure about how it communicates an object's interface. When you're allowed to modify objects and classes on the fly, how do you communicate interfaces between modules you mixin and methods/modules you add? By interface, I mean, how do you use this class so that it does what it's suppose to? Normally, it's pretty obvious--you look at the names of the methods declared in the code. A well-written class has public methods exposed, or you look at its ancestor's public methods. You might need some documentation to figure out how to call them in the right order, but generally, you have some idea just by looking at the method signatures.

However, when you throw mixins and metaprogramming in the mix, it becomes less easy to tell just from looking at the method signatures in the code--the structure of the code. You have to specifically read the code, or you have to rely on someone who knew intent to document it in detail.

An example communicating interfaces for mixins: the module Enumerable contains a lot of the Collections related methods. The cool thing is that if you wanted these functions in your own class, all you have to do is define each() in your class, mixin the Enumerable module, and you get all of these "for free". However, outside of documentation explicitly stating it, it's not as immediately obvious in method signatures that this is what you have to do in order to use it. It's only after scanning through the entire code that you notice each() being used for all the methods.

Of course, Ruby contains enough metaprogramming power to protect yourself against this. one can do something like this:

class MethodNeededError < RuntimeError
def initialize(method_symbol, klass)
super "Method #{method_symbol.to_s} needs to be in client class #{klass.inspect}"
end
end

module Enumerable
def self.included(mod)
raise MethodNeededError.new(:each, mod) unless mod.method_defined?(:each)
end
end

This only works if you put the include after you define each(). That's just asking for trouble when the order of your definitions in your class matter.

A fair number of people are writing mini-DSLs in ruby using metaprogramming tricks. One of the common ones is the use method_missing to define or execute methods on the fly. ActiveRecord's dynamic finds are implemented this way. The advantage of communication of interface here in the structure of the code is obvious. Unless it was documented well, you can't tell just by looking at the method signatures.

Why do I harp on interface signatures? I mean, in the instance of requiring each(), it works by just letting it fail in the enumerated methods, since it'll complain about each itself. In the instance of method_missing, just read the regex in the body. While these are true, none of these allow for rdoc to generate proper documentation. The whole point of documentation is to show you the interface--how to use that piece of code. I'm just afraid that given Ruby's philosophy of being able to write clear, powerful, and succinct code, it might fall short when people start using these metaprogramming tricks like alias_method_chain and method_missing more and more. Maybe rdoc needs to be more powerful and read code bodies for regex in method_missing?. It already documents yields in code bodies, but that seems awfully specific.

I'm not a exactly a fan of dictating interfaces like in Java. When you're first coding something up, you're sketching, so things are bound to change. Having plumbing like interface declaration gets in the way, imo. However, when something's a bit more nailed down, it'd be nice to be able to communicate to other programmers your intent without them having to read code bodies all the time.

In the end, I side on flexibility. However, I kinda wish Ruby had some type of pattern matching for methods so I didn't have to read method_missing all the time. But then again, that would be messy in all but the simplest schemes. Can you imagine a class that responded to email addresses as method calls? I guess I'd have to file this one under "bad ideas"

Don't reopen ActiveRecord in another file

The power of Ruby lies partially in how one can reopen classes to redefine them. Besides namespace clashes, this is usually a good way to extend and refine classes to your own uses. However, last night, I got bitten in the ass trying to refactor a couple classes. In Rails, you're allowed to extend associations by adding a class the association call.

class User < ActiveRecord::Base
has_many :stories, :through => :entries, :source => :story,
:extend => StoryAssociationExtensions
end

where StoryAssociationExtensions is a class module holding methods, like expired() that I can perform on the challenges association, so I can do stuff like

@user = User.find(:first)
@user.stories.expired # gives all expired stories

So when refactoring and cleaning up, I renamed StoryAssociationExtensions to AssociationExtensions and reopened up Story class and put it in there. I just wanted to clean up the namespace, and put the association extensions somewhere that made semantic sense. Naturally, I thought putting association extensions for a class belongs in a class. Well, it doesn't work. And don't do it. Hopefully, I'm saving you some pain.

class Story < ActiveRecord::Base
module AssociationExtensions
def expired
self.select { |c| c.expired? }
end
end
end

Well, this works if you've reopened the class within the same model file, story.rb in this case. However, if you reopen the class in another file elsewhere, your model definition won't get loaded properly, which leads to associations and methods you defined not to exist.

So imagine my bewilderment when associations didn't work on only certain ActiveRecord Models. In addition, they worked on the unit tests and script/console, but didn't work when the server was running. All that at 3am in the morning. :(

Good thing for source control, so I could revert (but I have to say, svn isn't as easy to use as it could be).

I ended up creating a directory in model called collection_associations and putting the associations in there under a module CollectionAssociations namespace. Not exactly the best arrangement but it'll do for now.

I'm still not sure why ActiveRecord::Base instances don't like being reopened, but I'm guessing it has something to do with only getting loaded once. If anyone has an explanation, I'd like to read about it.

free warning!

Friday, November 16, 2007

State change observer for ActiveRecord

When I started writing some code recently, I noticed that my controllers were getting fat. There was much to do, but there was a bunch of stuff in there that didn't have anything to do with actually carrying out the action--things like sending notifications. ActiveRecord already has observers to take action on certain callbacks. However, what I needed was to take actions on certain state transitions. Not seeing any immediate solutions in the Rails API, I decided to test myself and try writing one. I was bored too. So while I'm not sure if it was worth the time writing it, it certainly was kinda interesting. Here's what I came up with:

Just as a contrived example, let's say we are modeling the transmission of a car. It has three modes: "park", "reverse", "drive". We want to send a notification when a user tries to change it from "reverse" to "drive", but not when he tries to change it from "park" to "drive". If it didn't matter, and we just wanted to send notifications when the state changed to drive, we'd just use the observers that came with ActiveRecord. But since we do care where the state transition came from, here's what I came up with:


class CreateCarTransmission < ActiveRecord::Migration
def self.up
create_table :car_transmission do |t|
t.column :engine_id, :integer, :null => false
t.column :mode, :string, :null => false, :default => "park"
end
end

def self.down
drop_table :car_transmission
end
end



class CarTransmission < ActiveRecord::Base
include StateTransition::Observable
state_observable CarTransmissionNotifier, :state_name => :mode
end


So then for my notifier I have:


class CarTransmissionNotifier < StateTransition::Observer
def mode_from_drive_to_reverse(transmission)
# send out mail and flash lights about how this is bad.
end
end


And that's it. Whenever in the controller, I change the state from "reverse" to "drive", lights will flash and emails will be sent out condemning the action, and my controllers stay small and lean.

class CarController < ApplicationController
def dismantle
@car = Car.find(params[:id])
@car.update_attribute :mode, "reverse"
@car.update_attribute :mode, "drive"
end
end


So where's the magic? It took a bit of digging around. There were two major things I had to do. I had to insert observers during initialization and I had to override setting of attributes to include an update to notify observers.

ActiveRecord doesn't exactly allow you to override the constructor. I don't think I tried too hard to mess around with it. Looking on the web, I happened upon has_many :through again, where he has some good tips that helped me through Rail's rough edges. While I didn't exactly follow his advice, I did find out about the call back, :after_initialize. It must be something new, because I don't see it in the 2nd edition of the Rails book, and the current official API doesn't list it. Other Rails API manuals seem to be more comprehensive, like RailsBrain and Rails Manual.

Then overridding attributes has always been a bit of a mystery. I found a listing of the attribute update semantics, which was helpful to figure out what I was looking for, but it was false, in that you can't use the first one (article.attributes[:attr_name]=value) to set an attribute. Looking in the Rails code for 1.2.3, it shows that attributes is a read_only hash. But it's right that you should override the second one (article.attr_name=value), since update_attribute() and update_attributes() depends on it.

Again, it ends up that the function I was looking for wasn't found in the official API as a method, other than a short mention in the description of ActiveRecord under Overriding Attributes, which makes it harder to find. Ends up that we can use write_attribute().

So that's pretty much it. Using some standard meta-programming like how plugins do it, you wrap it up, and it's pretty simple:

require 'observer'

module StateTransition
module Observable
class StateNameNotFoundError < RuntimeError
def message
"option :state_name needs to be set to the name of an attribute"
end
end

def self.included(mod)
mod.extend(ClassMethods)
end

module ClassMethods

def state_observable(observer_class, options)
raise StateNameNotFoundError.new if options[:state_name].nil?
state_name = options[:state_name].to_s

include Object::Observable

define_method(:after_initialize) do
add_observer(observer_class.new)
end

define_method("#{state_name}=") do |new_state|
old_state = read_attribute(state_name)
if old_state != new_state
write_attribute(state_name, new_state) # TODO yield the update method
changed
notify_observers(self, state_name, old_state, new_state)
end
end
end

end

end

class Observer
def update(observable, state_name, old_state, new_state)
send("#{state_name}_from_#{old_state}_to_#{new_state}", observable)
rescue NoMethodError => e
# ignore any methods not found here
end
end

end


I had a difficult time figuring out how to define methods for an instance of a class. The only thing I came up with was to use define_method, or to include a module with instance methods in them. instance_eval() didn't work. The meta programming for ruby gets rather confusing when you're doing it inside a method--it seems hard to keep track of which context you're in.

So if you can make a use of this, great. If you think it's worth moving it into a plugin, let me know that too. If you know of a better way, by all means, let me know. tip!

Monday, October 22, 2007

Where do you put the rules of Monopoly?

It's apparently a favorite interview question. I have to admit, the first response in my head wasn't a great one, which was "everywhere".

What are game rules? When browsing the rules of popular games like Monopoly and Scrabble, they seem to follow a similar format:

  • The initial conditions of the game (the setup)
  • Then given a condition,
    • the set of allowable actions for the player to do
    • the effects of the condition
I embarked on somewhat of the same problem, though on a much smaller scale. I wanted to implement a point system that gave points to those that participated in a Rails app. My first reaction was to make a Rule abstract class, and have different rule classes that subclass it. Something like this (variable names have been changed to protect the innocent):
class SceneRules
def initialize(model)
@scene = model
@user = @scene.submitting_user
end

def on_submit
@user.points += 1
end
end

class SceneshotRules
def initialize(model)
@sceneshot = model
@user = @sceneshot.sceneshot_uploader
end

def on_submit
@user.points += 10
@scene.submitting_user.points += 5
end

end
Then I'd be able to call it from the controllers. However, on second thought, it's rather ugly, since I'd be updating the karma everywhere in the controllers. If I understand cross-cutting concerns correctly, scoring karma would be a good example of one. I suppose it's a good candidate for aspect orientated programming, so I scrapped the code above.

Logging is often cited as the poster-child problem to solve with AOP. Logging needs to be done everywhere in the code, but it really has nothing to do with the responsibilities of the class that it's performed in. So you have the same code doing the same thing, duplicated everywhere because there's no one place to put it to make things easy to change.

By the same token, game rules and scoring are of the same nature. And because game rules involve lots of different objects at once, and scoring is interspersed throughout, I think that makes it a good candidate for AOP. However, Ruby has no such direct support for AOP. Instead, the closest thing we have are observers, before/after/around filters (in Rails), and some meta-programming.

I wanted something that allowed me to list out rules like games like Monopoly and Scrabble. I'd have a setup, and some conditions and their effects. Scoring is simplified here because the only time you can score is when one of the models is created or changes state. This is a good fit to the observers and the filters available in Rails.

class ScoringRules < ActiveRecord::Observer
observe Sceneshot, Scene
include Rules

setup { :scene => Proc.new { |sceneshot| sceneshot.scene } },
{ :sceneshot_uploader => Proc.new { |sceneshot| sceneshot.sceneshot_uploader },
:scene_submitting_user => Proc.new { |sceneshot| sceneshot.scene.submitting_user } }

rule :after_create_sceneshot do |board, players|
players[:scene_submitting_user].score += 5
end

# put more rules here

def after_create(model)
rule_dispatch(:after_create, model)
end

end
Here, the Rules module is what encapsulates the setup, rule, and rule_dispatch calls. I needed setup so that I can access different "game elements" (the board and the players) to update the scoring. It basically stores the setup as a list of lambdas that it can execute at a later time when the rule needs to be executed. Now, when a model is created, we ask the rule dispatcher to figure out which rules execute based on the rules we've named, and then execute the attached block. The block is passed a hash of different game pieces that it needs to update the score and the game conditions. That's it.

I thought it was an interesting way about it and probably warranted some criticism. Is there any particular disadvantage of doing it this way? And if you can think of a way to not have to explicitly state the model relationships in the setup, that'd be nice. half-tip!