RSS
 

Archive for the ‘ruby’ Category

Don’t Use Rails’ Scaffolded Controllers

12 Nov

Fellow Rails Developers, the state of the art has moved on, and you should no longer be using the controllers generated by Rails’ scaffold command (or ‘rails g resource foo’).

These controllers are all the same. Repetition like that can and should be eliminated.

Instead, you should use something like Inherited Resources.

Here’s what a controller generated by Rails looks like:

class UsersController < ApplicationController
  # GET /users
  # GET /users.xml
  def index
    @users = User.all

    respond_to do |format|
      format.html # index.html.erb
      format.xml  { render :xml => @users }
    end
  end

  # GET /users/1
  # GET /users/1.xml
  def show
    @user = User.find(params[:id])

    respond_to do |format|
      format.html # show.html.erb
      format.xml  { render :xml => @user }
    end
  end

  # GET /users/new
  # GET /users/new.xml
  def new
    @user = User.new

    respond_to do |format|
      format.html # new.html.erb
      format.xml  { render :xml => @user }
    end
  end

  # GET /users/1/edit
  def edit
    @user = User.find(params[:id])
  end

  # POST /users
  # POST /users.xml
  def create
    @user = User.new(params[:user])

    respond_to do |format|
      if @user.save
        format.html { redirect_to(@user, :notice => 'User was successfully created.') }
        format.xml  { render :xml => @user, :status => :created, :location => @user }
      else
        format.html { render :action => "new" }
        format.xml  { render :xml => @user.errors, :status => :unprocessable_entity }
      end
    end
  end

  # PUT /users/1
  # PUT /users/1.xml
  def update
    @user = User.find(params[:id])

    respond_to do |format|
      if @user.update_attributes(params[:user])
        format.html { redirect_to(@user, :notice => 'User was successfully updated.') }
        format.xml  { head :ok }
      else
        format.html { render :action => "edit" }
        format.xml  { render :xml => @user.errors, :status => :unprocessable_entity }
      end
    end
  end

  # DELETE /users/1
  # DELETE /users/1.xml
  def destroy
    @user = User.find(params[:id])
    @user.destroy

    respond_to do |format|
      format.html { redirect_to(users_url) }
      format.xml  { head :ok }
    end
  end
end

Here’s that SAME controller using Inherited Resources:

class UsersController < InheritedResources::Base
end

That’s right, just by inheriting from InheritedResources::Base you all the standard REST actions for free.

If you need to, you can override any of the default actions:

class UsersController < InheritedResources::Base
  def new
    # do different stuff for new
  end
end

It even has a nice DSL for customizations you’re likely to need. Here’s how to change just the redirect for the destroy action:

class UsersController < InheritedResources::Base
  def destroy
    destroy!{ root_url }
  end
end

The best thing is, once you’ve got that duplicated code out of there, you don’t need to test it! Inherited Resources already has its own tests for the standard actions, so you only need test the things you explicitly change.

A few months ago, I refactored an app to use Inherited Resources instead of the generated controllers. And by ‘refactored’, I mean ‘deleted pages and pages of controller and test code’. I ‘git rm’d almost all our functional tests and damn that felt good.

You gotta get in on this! The README is solid, so you should have little trouble getting started.

 
2 Comments

Posted in coding, rails, ruby

 

Ruby Best Practices: A Review

06 Jul

One of my favorite simple pleasures is reading a technical or instructional book where the level of complexity perfectly matches my expertise.  I’ve been enjoying this exact experience while reading Greg Brown‘s new book, Ruby Best Practices.

I have been programming professionally for over three years, with the last five months doing full time Ruby on Rails development.  I would label myself an intermediate Ruby user: comfortable with the basics, but with limited exposure to its more advanced topics.  Lately, I have been reading more and more open source Ruby projects, and have been looking for ways to contribute back to our teriffic community.

Given my experience and goals, Ruby Best Practices was a perfect read.  The book is a collection of general strategies for solving problems in Ruby, with a focus on real-world code examples. Its author is an experienced Ruby developer who also happens to be an excellent writer.

Ruby Best Practices has a number of notable strengths. First, Brown is highly pragmatic. When discussing closures, he writes “I could show some abstract examples or academically exciting functionality such as Proc#curry, but instead, I decided that I wanted to show you something I use fairly frequently.”  This attitude has lead to a book that is full of ideas you can actually use.  It feels like the experienced guy down the hall showing you all his best stuff.

Secondly, RBP’s examples are almost uniformly excellent.  As contributor or creator of several popular Ruby projects (Prawn and Ruport) Brown has no lack of real-word code examples to choose from, and he does so with skill.  In addition, he’s not shy about trimming down the examples to leave behind just the most relevant code elements.  These two factors combine to produce code listings which are indicative of real open-source programs while remaining quite comprehensible.  Not only are Brown’s examples excellent, but they are plentiful.  Nearly every new idea he introduces is demonstrated through a case study of real (or plausibly real) code.  Working through this book will definitely sharpen your code-reading skills.

Beyond simply being clear, Brown’s writing is also fun to read.  His enthusiasm for the subject matter is obvious: “I could stop here and move on to the next topic, but similar to when we looked into the belly of lazy.rb earlier in this chapter, I can’t resist walking through and explaining some cool code.”  This sort enthusiasm continues throughout, and leads to a technical book that I’m tempted to call a page-turner. Making my way through the book really excited me to read and work on open-source projects.

If you’re still on the fence, take a read through the sample chapter, Mastering the Dynamic Toolkit.  Or, if you’d prefer a quicker read, check out this post on the book’s blog to get a feel for Brown’s writing style.  If you like what you see, don’t hesitate to pick up a copy of this excellent book.

Chapter Titles:
1.  Driving Code Through Tests
2.  Designing Beautiful APIs
3.  Mastering the Dynamic Toolkit
4.  Text Processing and File Management
5.  Functional Programming Techniques
6.  When Things Go Wrong
7.  Reducing Cultural Barriers
8.  Skillful Project Maintenance
A.  Writing Backwards Compatible Code
B.  Leveraging Ruby’s Standard Library
C.  Ruby Worst Practices

 
11 Comments

Posted in ruby