RailsCasts Pro episodes are now free!

Learn more or hide this

Recent Comments

Avatar

Great Episode!
I'm using modest model. It's very similar and an alternative if someone is looking for.

Avatar

Has anyone got capybara xpath assertions working?

Example:
page.should have_xpath("//title")

Gives me the error:
NoMethodError: undefined method `have_xpath'

Avatar

What advantages does MiniTest have over other existing testing frameworks? Other than having "Mini" in the name.

Avatar

Does the final setup here use transactions in the db for isolation? If so, which part of the setup loads that support? I couldn't see it.

Avatar

why backbone submit with double params?

ruby
Parameters: {"name"=>"test", "entry"=>{"name"=>"test"}}
Avatar

Was asked today to implement a simple application that lets people submit tickets without persisting them to the database. This is going to work perfectly. Thanks Ryan!

Avatar

I'm running into a strange problem with cucumber. When I run my feature that tests that a user can create an account, the feature fails with the error No route matches [POST] "/auth/identity/register" (ActionController::RoutingError) It does, however, work just fine if I test it in my browser. Running rake routes dos not show that route, but I assume that's because it's provided by omniauth-identity through rack middleware. Does anyone have any ideas? Any Google searches I've done just bring me back here. Thanks for the great screencast!

Avatar

I thought to this article as soon as the episode started! =)

Avatar

Well, there's also the fact that server rendering is holding up a blocking request. Time/throughput is more expensive than memory.

Avatar

Thanks for the hint -- exactly what I needed for my "legacy" app.

Avatar

When I save the data and want to edit them again, only the first select is shown.
The second select is on "style="display: none" regardless the right values is "option selected="selected".

Any suggestions?

Thanks ahead!

Avatar

Thanks Ryan! Private_pub really is a Gem. May I suggest a tiny, tiny, three character tweak would make it even more fun:

In app/views/messages/create.js.erb,
Change ".append" to ".prepend", like this:

<% publish_to "/messages/new" do %>
$("#chat").prepend("<%= j render(@message) %>");
<% end %>
$("#new_message")[0].reset();

Restart Mongrel (or your WebServer).

Now, each new micropost will be on top, and you won't have to scroll using the side bar to view it at the bottom.

Avatar

Yes. I also have this issue. Rails 3.2.1 with rabl.

Avatar

For anyone still referencing this, current ActiveRecord versions now have a reset_counters convenience class method that will automatically execute a count query for you. Also, please do use find_each instead of find(:all).each :-)

I'm not wild about using migrations to modify data personally, but if you insist:

ruby
def self.up
  add_column :projects, :tasks_count, :integer, :default => 0

  Project.reset_column_information
  Project.select(:id).find_each do |p|
    Project.reset_counters p.id, :tasks
  end
end

def self.down
  remove_column :projects, :tasks_count
end
Avatar

Hi Ryan,
i see that there are some hooks you can define using delayed job.
i want to do some task after the job is done and, as the docs suggest i add the method

ruby
def after(job)
  # do something
end

in my class but it never been called.
What is the right way to use the hooks or maybe there is some other way to define callbacks instead?

Avatar

And the problem was: The browser. Works in Firefox 9.0.1. Cheers.

Avatar

Hello Ryan and All,

I have modified the 'before' app according to the section in the example titled 'Using Private Pub in Our Applications' but private pub is failing. I am looking for troubleshooting help.

I am running Rails 3.2.

I do not see a new message appear in the browser until I refresh the screen. The development log looks good. Index.html is being rendered, just not to the browser. Here is the log:

Started GET "/" for 135.209.108.81 at 2012-02-20 15:46:37 -0800
Processing by MessagesController#index as /
Message Load (8.2ms) SELECT messages.* FROM messages
Rendered messages/_message.html.erb (90.4ms)
Rendered messages/index.html.erb within layouts/application (94.5ms)
Completed 200 OK in 132ms (Views: 109.4ms | ActiveRecord: 8.9ms)

Only after I refresh either broswer do I see the chat list. In the log, after the refresh, we see:

Started GET "/assets/application.css?body=1" for 135.209.108.81 at 2012-02-20 15:46:38 -0800
Served asset /application.css - 304 Not Modified (0ms)

Started GET "/assets/messages.css?body=1" for 135.209.108.81 at 2012-02-20 15:46:38 -0800
Served asset /messages.css - 304 Not Modified (0ms)

Beofre I modified the chatter-before app as per the tutorial, the browser submitting the update was updated by ajax. Now, after the modification to use private_pub, the submitting browser must be refreshed to see a new message.

When pointing the browser at the http://myserver:9292, the server responds with the following message:

Sure you're not looking for /faye ?

Thanks. I will post the solution when I know what it is.

Avatar

Looks good but seems to have a conflict with cancan (both current release and 2.0 alpha). Would post a bug report but not really sure which gem is the culprit.

On a brand new rails 3.2.1 app with only cancan and rabl added to Gemfile:

/usr/local/rvm/gems/ruby-1.9.3-p125@***/gems/rabl-0.2.8/lib/rabl/template.rb:66:in `<top (required)>': uninitialized constant ActionView::TemplateHandlers (NameError)
        from /usr/local/rvm/gems/ruby-1.9.3-p125@***/gems/rabl-0.2.8/lib/rabl.rb:12:in `register!'
        from /usr/local/rvm/gems/ruby-1.9.3-p125@***/gems/rabl-0.2.8/lib/rabl/railtie.rb:6:in `block (2 levels) in <class:Railtie>
<snip>'

Anyone else seeing this?

Avatar

Post is by DHH, the name you mention is from a comment. ;-)

Avatar

Here's how I did it for a blog project using Rails 3.2 and Redcarpet 2.1 (minus the syntax highlighting). Some of the configuration options have been moved into the HTML renderer, while the more generic ones are still at the markdown layer:

ruby
module ApplicationHelper 
  def markdown(text)
    markdown = Redcarpet::Markdown.new(Redcarpet::Render::HTML.new(
        :hard_wrap => true, :filter_html => true, :safe_links_only => true),
        :no_intraemphasis => true, :autolink => true)
    return markdown.render(text).html_safe
  end
end
Avatar

RABL crashes for me on rails 3.2.1 on ruby 1.9.2

/Users/rackom/.rvm/gems/ruby-1.9.2-p290/gems/rabl-0.2.8/lib/rabl/template.rb:66:in <top (required)>: uninitialized constant ActionView::TemplateHandlers (NameError)

jbuilder on same configuration throws this error
Illegal instruction: 4

Any help?

Avatar

Thanks for the railscast, Gon looks very promising!

My only fear is that google won't index anything more then 'Loading products...', making this technique unusable for certain projects. Are there any solutions known for this problem?

Avatar

Also - can anyone explain how hook_for is supposed to work?

Avatar

No need now. I'm using the Haml_Coffee_Assets gem referenced above. Textmate treats the hamlc files just like haml

Avatar

Thanks from me also. The templates look allot cleaner now.

Avatar

I saw that - great read! Makes sense.

Avatar

What Textmate bundle do you use for .eco files ? I notice the bottom of your textmate window says javascript template. Where can I get it?

Avatar

Good point. (This will most likely result in a different SQL query due to lazy/last-minute evaluation in AR, probably for the better...)

Avatar

Apparently the DB queries is not the bottleneck for most cases, if you can avoid complex joints, etc... This came as a surprise to me too. (See the linked 37Signals article and the comments)

Avatar

@Ryan in HTTP caching you can only fix expiration once.

So, if you set a TTL of 30 minutes for a page, you're done. No way to tell the users and intermediate proxy caches that fetched that one they need to revalidate right now because it is stale. They won't do it after 30 minutes have passed.

So, the key of this approach vs HTTP headers is that you have total control over the expiration of the cache.

Avatar

I think the main problem with this approach is that you have to load and use all the recent article models, even when you read from the cache.

If you already have the article models loaded just to build the name of the cache, you might as well just print the link_to entries and skip the cache altogether. I would think the main benefit of caching this section of the page would be to avoid the SQL call that loads the recent article models in the first place.

Avatar

You could use something like Article.maximum(:updated_at) as a cache key to make it shorter.

Avatar

Does it make sense to nest cache resources this way? Is it Rails so slow to render a template that you should waste more cache memory?

Avatar

A quick test in the console suggests that this should work (although you probably won't want to do this when you have a lot of objects in you array?)

>> ActiveSupport::Cache::expand_cache_key(["key_test"] + Model.limit(5))
  Model Load (0.3ms) ...
=> "key_test/model/1-20110606182109/model/2-20110606174200/model/3-20110606170234/model/4-20110606170854/model/5-20110604144748"
Avatar

What's a good way to auto-expire the "recent_articles" fragment you have there? Would something like this work?

ruby
<% cache ["recent_articles"] + @recent_articles do %>
<div id="recent_articles">
  <h3>Recent Articles</h3>
  <ul>
  <% @recent_articles.each do |article| %>
    <% cache ["recent", article] do %>
      <li><%= link_to article.name, article %></li>
    <% end %>
  <% end %>
  </ul>
</div>
<% end %>
Avatar

When I was going through the RailsCast as described above. I was using the entries controller that Ryan put together. After much searching, copying, pasting, and retrying I found that I need a completely new Controller set up. Below is what I originally had.

class EntriesController < ApplicationController
  respond_to :json

  def index
    respond_with Entry.all
  end

  def show
    respond_with Entry.find(params[:id])
  end

  def create
    respond_with Entry.create(params[:entry])
  end

  def update
    respond_with Entry.update(params[:id], params[:entry])
  end

  def destroy
    respond_with Entry.destroy(params[:id])
  end
end

This is the Controller code the fixed the issue for me.

class EntriesController < ApplicationController
def index
    render :json => Entry.all
  end

def show
  render :json => Entry.find(params[:id])
end

def create
  entry = Entry.create! params
  render :json => entry
end

def update
  entry = Entry.find(params[:id])
  entry.update_attributes!(params[:entry])
  render :json => entry
end

def destroy
  render :json => Entry.destroy(params[:id])
end
end

Thanks All!

Travis

Avatar

I'm doing ExtJs for some time and bumped to similar problem, at beginning, cause I was lazy to rewrite validation to client side. Then I realized that VALIDATION is not same as BUSINESS RULES in your app.

There is nothing wrong having same validation in UI. It will just prevent UI to make unnecessary round trips to backend. So add that validation in UI. Also, you can pass exceptions for Business rules back to ui by packing exception as nice messages which you can send with HTTP 4xx or 5xx status codes. Or you can add special JSON/XML node which your javascript code will handle before response reaches your UI model.

After all, UI validation is always more restrictive than one which is in service ;)

Avatar

This worked awesome, thanks. It turns out oh-my-zsh added a ton of stuff to my path!

Avatar

I agree, it was the first screencast that made me easily understand BB. Great job Ryan! Would be great to see a Ember screencast too!

Avatar

verify that you can access the category_id column via mass assignment.
Add category_id to the attr_accessible declaration in your model

Avatar

Hi,

I did a variant of the above Raffler in Spine JS to find out the differences between Spine JS and Backbone. For those of you that are interested, the result can be found here: https://github.com/ygor/spine-raffler

The only thing that I have not been able to figure out yet is how to do the remote validation. Let me know what you think!

Avatar

In my controller I have to add "@product.category_ids = params[:product][:category_ids]" to the create and update actions, otherwise nothing gets stored in the database. I don't see this in the source code of this episode. Am I forgetting something?

Avatar

There's this one, but it's over 4 years old:
http://railscasts.com/episodes/90-fragment-caching

Would love to see a 'revised' version of that one. I'm guessing it's coming up though.