Feb 3

I’ve been running with the Rails MySQL adapter for a while now after failing to build the native MySQL gem under Leopard. The problem, I thought, was that I’m using the Macports MySQL, and it turns out I was right. If you attempt to build the MySQL gem and you get an error like this:

Building native extensions.  This could take a while...
ERROR:  While executing gem ...
(Gem::Installer::ExtensionBuildError)
    ERROR: Failed to build gem native extension.

ruby extconf.rb install mysql
checking for mysql_query() in -lmysqlclient... no
checking for main() in -lm... yes
checking for mysql_query() in -lmysqlclient... no
checking for main() in -lz... yes
checking for mysql_query() in -lmysqlclient... no
checking for main() in -lsocket... no
checking for mysql_query() in -lmysqlclient... no
checking for main() in -lnsl... no
checking for mysql_query() in -lmysqlclient... no

Gem files will remain installed in
/opt/local/lib/ruby/gems/1.8/gems/mysql-2.7 for inspection.
Results logged to /opt/local/lib/ruby/gems/1.8/gems/mysql-2.7/gem_make.out

Then you’ll need to add a couple of things to your Gem command line to get it building:

If you’re just installing or updating the gem, try this:

sudo gem install mysql -- --with-mysql=/opt/local/lib/mysql5 --with-mysql-lib=/opt/local/lib/mysql5/mysql --with-mysql-include=/opt/local/include/mysql5/mysql

If you’re updating all your gems (this one caught me out), then try this:

sudo gem update -- --with-mysql=/opt/local/lib/mysql5 --with-mysql-lib=/opt/local/lib/mysql5/mysql --with-mysql-include=/opt/local/include/mysql5/mysql
Dec 12

Note: read the notes at the end of this article first!

Ok, so we’re using RubyAMF trunk on a brand spanking new project, and all in all it’s pretty darn cool. I love AMF anwyay, irrespective of the crimes against standards, it’s efficient - and I like efficient. But I do care about standards, and for that reason I can’t bear the thought of producing a service that can only talk AMF, but I don’t want to go through extra hoops to achieve it.That’s one of the nice things about Edge (Oops, just remembered it’s now a release) Rails. Using respond_to, a controller can dynamically serve content based on the client. Meaning this is possible:

def ProjectsController
  def create
    @project = Project.create_with_company!(
      params[:project],
      params[:company]
    )
    respond_to do |format|
      format.xml do { render :xml => @project.to_xml }
      format.html do { render :action => “some_action” }
      # etc..
    end
  rescue
    # Blah blah
  end
end

This is nice. It means that the only time we need to care about what the client is, is when we need to send something back. As long as we receive a standard params hash.I may well be wrong, but there doesn’t appear to be a way to configure RubyAMF to map an incoming Value Object straight to a hash. Instead RubyAMF wants to instantiate the appropriate ActiveRecord model for you, which means that the controller will ultimately need to behave differently when an AMF client makes a request. This is no good.So, after much experimentation with ParameterMappings, ValueObjects mappings and RubyAMF configuration settings, I came up with this little gem (why are these things never obvious until you’ve been around the houses a few times?). To map your incoming Value Objects directly to the params hash, declare your ParameterMappings like this example:

ParameterMappings.register(
  :controller => :ProjectsController,
  :action     => :create,
  :params     => {
    :company => "[0].attributes”,
    :project => “[1].attributes”
  }
)

Notice the call to .attributes. Now this controller will receive a hash containing two other hashes, one containing the company attributes and the other containing the project attributes; in other words, a regular params hash. Our controller can now simply return the results as AMF the same as any other request:

def ProjectsController
  def create
    @project = Project.create_with_company!(
      params[:project],
      params[:company]
    )
    respond_to do |format|
      format.xml do { render :xml => @project.to_xml }
      format.html do { render :action => “some_action” }
      format.amf do { render :amf => @project }
      # etc..
    end
  rescue
    # Blah blah
  end
end

It’s a bit of a hack. RubyAMF spends pointless time and effort gift wrapping an ActiveRecord model for us and we tear it to shreds and throw it away. But hey, it works, and us kids still get our toys.

Update: It appears I may have been hasty in my assumptions. Setting ParameterMappings.scaffolding to true will achieve the same effect. I know I’ve tried this, and I had an issue with it, I just don’t remember what it was. In fact I think I’ve possibly tried every single possible permutation of configuration settings..

Update: Indeed ParameterMappings.scaffolding does achieve the same effect, so this whole article is actually redundant. Ho hum :-)

Nov 12

TextMate Rails Cheat Sheet

Posted by Cliff

This is actually a duplication of this, but when I already have a million tabs open during the course of development, I’d rather not open another with a big fat Flash applet in it. So I created myself the following text only version. The characters I’ve used aren’t perfect, I’ll fix them when I get a chance..

Legend:

Apple / Command
Shift
Option
Control
Tab
Enter

File navigation

Go to file ⌘T
Go to line ⌘L
Go to method ⇑⌘T
Go to file ⇑⌘F
Go to file ∧⌘R

Editing

Code completion Escape
Fold / Unfold F1
Comment selection ⌘/
Indent / Unindent selection ⌘[ and ⌘]
Move selection ∧⌘(arrow)
Edit selection ⌥⌘A
Column selection ⌥(drag)
Insert tag ∧⇑<
Wrap selection in tag ∧⇑W
Close tag ⌥⌘.
Wrap selection as link ∧⇑L
Subversion menu ∧⇑A
New method name∧↵

Commands (⇑⌥⌘C)

Run file as Ruby ⌘R
Start IRB ∧⇑I

Snippets (⇑⌥⌘S)

class class_name class➾
def method_name def➾
each { |method_name| } each➾
for element in collection forin➾
if condition if➾ or elsif➾
unless condition unless➾
:key => :value :➾
flash[:notice] = "…" flash➾
logger.info "…" logi➾
assert_equal value, @o.attr ac➾
redirect_to options rec[ai]➾
render :action => "action" ra➾
render :partial => "item" rp[loc]➾
create_table "table" mct➾
table.column :,: mcc➾
<%= link_to options lic[ai]➾
<% for item in @items eforin➾
<%= form_tag options ft➾
has_many :objects hm➾
belongs_to :object bt➾
validates_presence_of :attr vpif➾
=> ∧L
params[:id] ∧P
session[:user] ∧J
<% %> ∧X
<%= %> ∧Z
Nov 8

I just had a problem with my svn repository after a couple of plugins I had installed as svn:externals (./script/plugin install -x http://blahblah) were no longer required and I wanted to remove them. Not something I’ve done before, but I found a handy article here, and all you have to do is this:

cd vendor/plugins
svn propedit svn:externals . --editor-cmd vi

Remove the lines that reference the plugins you wish to remove, then save and quit vi (shift-ZZ if you didn’t already know).

Then svn commit and you’re done :)

Sep 20

Dates and times in fixtures

Posted by Cliff

Just a micro tip. If you’re inserting dates and/or times into your database via fixtures whether for testing or to load initial data, it’s not enough just to specify the date. This won’t work:

some_fixture:
  id: 1
  created_at: <%= 2.days.ago %>

You need to coorce the data into the appropriate format like so:

some_fixture:
  id: 1
  created_at: <%= 2.days.ago.to_s :db %>
Jun 8

A question regarding the embedding of SWF content came up on the Ruby on Rails mailing list. In this instance, the problem was related to the tags used to embed a SWF in Internet Explorer and Mozilla browsers. Internet Explorer requires an <object> tag, while Mozilla (and most other) browsers require an <embed> tag.

Further to that, the ridiculous EOLAS patent requires changes in the way that objects are embedded in web browsers. One of the effects of this is that Internet Explorer users must now click a plugin in order to activate it (which is a problem for SWF files, especially if they are used in navigation, since two clicks are required to navigate).

There is a workaround, however, in the form of the extremely lightweight SWFObject javascript library. It is very easy to use, and actually I prefer this method of embedding SWF files since:

  • There is no need to deal with <embed> or <object> tags at all. It’s all handled for you behind the scenes.
  • Cross browser embedding is implied; the exact same code embeds a SWF in any browser automagically.
  • Passing parameters to a SWF is trivial.
  • Supplying alternative content for browsers without the Flash Player is trivial.
  • Embedding with SWFObject bypasses issues caused by the ridiculous EOLAS patent.

Because of these issues, SWFObject has quickly become the de-facto standard for embedding SWF files.

I was in the process of replying to the mailing list, but I figured it would be more useful to write up a blog post for everyone. So here is a short tutorial on embedding SWF content in Ruby on Rails using the SWFObject library.

  • Download the zip file from the SWFObject homepage ( direct link here)
  • Extract the contents of the zip file anywhere on your machine, and copy swfobject.js to #{RAILS_ROOT}/public/javascripts
  • Include swfobject.js in the head of your layout file using:
<%= javascript_include_tag 'swfobject' %>
  • Copy your SWF file(s) to #{RAILS_ROOT}/public/swf
  • Include the following code in the body of the template file in which you wish to embed the SWF content:
You need to upgrade your Flash Player This is replaced by the Flash content. Place your alternate content here and users without the Flash plugin or with Javascript turned off will see this. Content here allows you to leave out noscript tags.

And that’s all there is to it. More information is available on the SWFObject homepage :-)

UPDATE: Meekish kindly posted a comment pointing out a plugin for Ruby on Rails that provides a flashobject_tag to use directly in your views. More info here. Thanks Meekish!