Skip to content

Instantly share code, notes, and snippets.

@rohitarondekar
Created September 15, 2011 05:45
Show Gist options
  • Save rohitarondekar/1218625 to your computer and use it in GitHub Desktop.
Save rohitarondekar/1218625 to your computer and use it in GitHub Desktop.
class Post < ActiveRecord::Base
  belongs_to :author, :class_name => 'User'
end

class User < ActiveRecord::Base
  has_many :posts, :foreign_key => 'author_id'
end

So to build a post for current_user we can do the following:

@post = current_user.posts.build(params[:post])

But what if the @post has to be built using multiple steps like:

@post.author = author
@post.editor = editor
@post.category = category

There are two problems I see with the above:

  1. It's possible to forget one of the objects and you can have inconsistent data. You can of course use validations to get rid of this problem.
  2. You need to repeat those steps every time you want to build and save a @post. It also looks brittle in a controller imho.

So would the following make sense

@post = Post.build(params[:post], current_user, editor, category)

i.e define a .build method as follows

class Post < ActiveRecord::Base
  def self.build(params, author, editor, category)
    post = Post.new(params[:post])
    post.author = author
    post.editor = editor
    post.category = category

    post
  end
end

This isolates the steps required to build a @post and thus changes can be done in one place (but also update the callers but that's a smaller less error prone change compared to prev case). Also you can write unit tests for .build method.

What do you think?

@zerothabhishek
Copy link

I've found putting all that assignment logic together in a build like method is been good for my code, and for the same reason you mention. I've heard people say that class methods are a code-smell, but I'm yet to see good arguments against this one.

@neerajsingh0101
Copy link

I prefer not to much with methods coming from ruby or rails. I would do exactly the way Rohit illustrated in two/three steps and add validations. And write tests.

@rohitarondekar
Copy link
Author

@neerajdotname Actually ActiveRecord doesn't define a build method on the model itself AFAIK. So there is no Post.build or User.build. In that case what is the harm in writing one?

Ideally you would pass the dependencies via the constructor but I would rather not override it for AR model classes.

@neerajsingh0101
Copy link

Yes I missed that. There is no build method on the klass itself.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment