RailsCasts Pro episodes are now free!

Learn more or hide this

Austin Schneider's Profile

GitHub User: austinthecoder

Site: http://austinschneider.com

Comments by Austin Schneider

Avatar

I recently created a gem to aid in building and rendering a monthly calendar. The API is much less magical than the table_builder gem, with all the same features. Check it out at https://github.com/austinthecoder/cal. I hope it helps.

Avatar

Well, turns out the rackup file was tampered with! :-/

Avatar

Ryan,

I followed these directions exactly but when I visit http://[ip] I get "Not Found: /". However, when I visit http://[ip]/[appname] it hits the app. Is it possible one of the paths in one of the configs is wrong?

Avatar

While it's fresh in my brain, here's an example for using the session.

Controller:

ruby
def new
  @search = SessionSearch.new(session)
end

def create
  @search = SessionSearch.create!(session, params[:search])
  redirect_to @search
end

def show
  @search = SearchSession.last
end

Model:

ruby
class SessionSearch
  class << self
    def create!(session, attrs = {})
      new(session, attrs).save!
    end
    
    def last(session)
      attrs = YAML.load(session['search_payload'])
      new(session, attrs)
    end
  end
  
  def initialize(session, attrs = {})
    @session = session
    @attrs = attrs
  end
  
  def save!
    @session['search_payload'] = YAML.dump(@attrs)
  end
end

There's probably ways to make this cleaner, but I think the idea is there.

Avatar

I agree with @Dom. Nothing wrong, just different use cases.

For the non-db backed, basic approach I'd make my route a singular resource

ruby
resource :search

The controller could just about stay the same, except for the show action:

ruby
def show
  @search = Search.last
end

And then the model could be something like:

ruby
class Search
  class << self
    def create!(attrs = {})
      new(attrs).save!
    end

    def last
      # retrieve the attrs from storage
      new(attrs)
    end
  end

  def initialize(attrs = {})
    @attrs = attrs
  end
  
  def keywords
    @attrs[:keywords]
  end

  def save!
    # store the attrs somewhere
    # maybe serialized in the session, or in mongo or memcached
  end
end

By "non-db backed" I mean you don't have to store every search, but you'd still need some type of storage. It's possible not to use storage by showing the search from the create action, but I think it's good practice to only display pages from a GET request.

Avatar

I've been doing:

ruby
presenter.h.should_receive(:render).with('blah/_blah', :arg => 'value')

I like your way better, although I wish this was possible:

ruby
presenter.method.should render_template('blah/_blah').with_locals(:arg => 'value')
Avatar

It is much cleaner, but we can take it a little further. If we change the present method to:

ruby
def present(object, klass = nil, &block)
  klass ||= "#{object.class}Presenter".constantize
  presenter = klass.new(object, self)
  if block_given?
    block.arity > 0 ? yield(presenter) : presenter.instance_eval(&block)
  end
  presenter
end

We can slim our view down to:

html
<% present @user do %>
  <div id="profile">
    <%= avatar %>
    <h1><%= linked_name %></h1>
    <dl>
      <dt>Username:</dt>
      <dd><%= username %></dd>
      ...
<% end %>

We'll still have access to the template via h, just need to make it a public method.

Avatar

What's the best way to test a decorator? More specifically, how would you test the following method (in rspec):

ruby
def amount
  h.number_to_currency(model.amount)
end

When I try the following, I get undefined method 'number_to_currency' for nil:NilClass:

ruby
it "returns the formatted amount" do
  item = Item.create!(:amount => 5.5)
  decorator = ItemDecorator.new(item)
  decorator.amount.should == "$5.50"
end

There's must be some magic going on that sets the view context somewhere. Anyone write decorator helpers for rspec yet?