RailsCasts Pro episodes are now free!

Learn more or hide this

Recent Comments

Avatar

I second was Eric has said above.

We need deeper nuts and bolts level advice on integrating Rails with Coffeescript/backbones/Twitter Bootstrap/datatables (or a grid/table display widget) in a javascript (jQuery really) centric environment. There is a nice article published on Backbone/Twitter Bootstrap which Mike Gunderloy linked in his "A fresh cup" column today:

http://coenraets.org/blog/2012/02/sample-app-with-backbone-js-and-twitter-bootstrap/

If something like this can be done in a Rails environment, it gives us enough of a framework to create a nice look and feel.

Avatar

Awesome job, Ryan!

I found as I started integrating this into existing applications that if I have a large number of datasets, it tries to load all of the data at the initial load. This is because each router is loaded in the base window.App class. Is this how it is supposed to work? I don't expect you to answer this, but if someone can respond, I would appreciate it.

Also, I would love to see a screencast that covers pagination with Backbone.js.. It seems that there is very little documentation on this and it is very complicated to understand. If you could dumb that down for us, I would really appreciate it!

Avatar

What a great episode - thank you !!

I'd like to see more episodes on Backbone - like:
- handling associations between models in a Backbone app
- caching data using localStorage
- using multiple view objects and multiple routers
- appCache and Backbone
- testing with Jasmine and Sinon

Avatar

How to implement with more than one word? I have problems when i use to autocomplete for example "java javascript" and load a table below in ajax. The value is "java" and not "java javascript".

I read that is a limitation of the plugin and I need other one, like bassistance. Anyone knows how to replace in rails with bassistance?

Avatar

Really happy to see Gon+RABL covered in this screencast. That has been my favored approach to passing data to javascript lately. Thanks Alexey for making the Gon gem (and integrating it with RABL) and thanks to Ryan for another great screencast.

Avatar

For the routes, I use the js-routes gem quite extensively, it has always worked well for me.

Avatar

I never worked with backbone.js, but it seems to me that rails is a bit heavy when you skip most of the rails functionality. Would it not be better to use sinatra or even not use ruby at all? I guess you could use node.js?

testing backbone.js tutorial

Thanks Ryan for all the work on these screencasts.

Avatar

You'll probably want to add a rel="nofollow" to those admin links so Googlebot doesn't try to follow them.
You should of course protect your controller actions with a before_filter, but even then your application error log is not going to be pretty if the bot starts crawling those links :)

Avatar

Does 304 show up as a page view and work with say, google analytics? Since it's a local javascript, one would think it would get called again, but I'm not sure how the browser handles a 304.

Avatar

Rails 3.2, getting an odd error where it closes the div class nested-messages then prints the content, then echoes the div again, like this (i'm using folders instead of messages)

html
<div class="nested-folders"></div>  
<a href="/clients/2/folders/2">Child of Test Folder</a> (x files)<br>
<a href="/folders/new?client_id=2&amp;parent_id=2">Add child folder</a>
<div class="nested-folders"></div>
Avatar

What a great tutorial! This makes me want to use backbone to improve the responsiveness of my more complex pages. My biggest concern is how to test all this javascript. It leaves me feeling exposed to brokenness.

Avatar

@Elliot Larson, I think you've nailed it.

Avatar

Is there a way to get a pdf file with 300dpi using PDFKit?

Avatar

I get the following error when calling create_project:

undefined method 'create_project' for #<Project:0x104eb03c0>

shouldn't i get the create_association(attributes = {}) method for free in a belongs_to relationship?

thanks in advance, cole

Avatar

Have you considered doing an episode on the rest of Stripe Integration? Things like:
upgrades, downgrades, cancellations, receiving webhooks, updating cc info, handling failed payments, etc.? I've built several subscription sites with authorize.net and these things are always such a pain. I would love find out if there are any best practices and see how other Rails developers handle such things.

Avatar

Unless your code is open source, I wouldn't bother with that. I prefer to store those setting in environment files.

production.rb: STRIPE_SECREY_KEY = "XXXX"
development.rb: STRIPE_SECREY_KEY = "YYYY"
initializers/stripe.rb: Stripe.api_key = STRIPE_SECRET_KEY

Now if your code is open source... yes.
http://stackoverflow.com/questions/6113042/where-to-store-sensitive-data-in-public-rails-app

Avatar

Agreed Dan, I've been through hell trying to get controller tests with this stuff.

Avatar

Just a comment about the call to rm_rf.

Doing a recursive rm is not atomic and weird things may happen if at the same time you get requests that are generating files again in the same tree.

In order to safely expire an entire directory it is better to move it. Moving a directory is atomic. After moving you can rm_rf safely.

Avatar

ionas,

I came across this problem in Chrome (doesn't happen in Firefox). Apparently, its because the page and ajax request urls are the same (since Ryan showed pagination with only the requested format differentiating between returning the html and the javascript responses).

See:
http://stackoverflow.com/questions/6309477/moving-back-to-a-pushstate-entry-that-used-ajax

I think a more elegant solution than given in the stackoverflow answer, is to remove any page extension, and append the .js extension to change the url.

Avatar

Thanks for covering this, Ryan. It's a bit of a divergence from the beaten path with Rails, but I think this is the future of web application development.

I've spent quite a bit of time coming up to speed with BB lately, including a 2 day training course with the Gaslight Software guys (I'm not affiliated with them: I highly recommend their course).

Initially I struggled with the fact that using BB (or any of the other similar libraries) means writing a lot more code. It's simply more complicated, especially when dealing with data persistence. Writing basic CRUD operations in plain Rails is pretty straight forward. Involving BB in CRUD is a lot of additional work.

My "ah-ha" moment came when I deployed my first BB/ Rails app to a development server. The performance was amazing. Making JSON requests via AJAX in the background (especially if you're caching) is so much more performant that doing page requests. And, pushing a lot of the application logic to the client is a big win in terms of server load.

I've come to the conclusion that BB is really amazing for client facing front end stuff where performance is a concern. It's less useful for backend admin stuff where simple Rails based page requests provide adequate performance.

Avatar

Working with the code from github I learned:
* copy the folder best to a new path
* had to upgrade my rvm with iconv - http://beginrescueend.com/packages/iconv/
* run migrations
* realize there is no new for plans, thus open interactive console like this: rails console
* insert new plan p = Plan.new
* assign to p values, p.kisses =10 etc
* p.save!
* rails s

Avatar

I figured. I have absolutely no idea what the purpose of backbone.js is; it's what I'm looking into at the moment.

Avatar

I was just thinking: "It would be nice if Safari could render JSON in a more readable way... www.goo... oops" You beat Google! Great tip!

Avatar

Python is very similar Ruby. Yes, Backbone and Rails a very different. As they should be, Rails and Backbone are for two different purposes.

Avatar

Can someone help me understand how to make this screencast work with monodb as my database while using mongoid. This is what I am seeing.

When I create a new entry via the console, similar to how Ryan did it in the video 'entry.create' , rails adds that entry just fine. Below are is my Ruby Log and my javascript headers log from Chrome Inspector.

Ruby Log

Started POST "/api/entries" for 127.0.0.1 at 2012-02-12 17:31:24 -0600
Processing by EntriesController#create as JSON
Parameters: {"name"=>"Heather", "entry"=>{"name"=>"Heather", "action"=>"create", "controller"=>"entries"}}
MONGODB w_market_development['system.namespaces'].find({})
MONGODB w_market_development['entries'].insert([{"_id"=>BSON::ObjectId('4f384bcc504b9348be000003'), "name"=>"Heather"}])
Completed 201 Created in 11ms (Views: 2.4ms)

Headers Log

Request URL:http://0.0.0.0:3000/api/entries
Request Method:POST
Status Code:201 Created
Request Headers (14)
Request Payload
{"name":"Heather"}

As you can see it posted fine. Now let me show you an update via the 'entry.save()' example Ryan showed us.

Ruby Log

Started POST "/api/entries" for 127.0.0.1 at 2012-02-12 17:34:25 -0600
Processing by EntriesController#create as JSON
Parameters: {"_id"=>"4f38152c504b9345dc000005", "name"=>"Bloip", "winner"=>true, "entry"=>{"_id"=>"4f38152c504b9345dc000005", "name"=>"Bloip", "winner"=>true, "action"=>"create", "controller"=>"entries"}}
MONGODB w_market_development['system.namespaces'].find({})
MONGODB w_market_development['entries'].insert([{"_id"=>BSON::ObjectId('4f38152c504b9345dc000005'), "name"=>"Bloip", "winner"=>true}])
Completed 201 Created in 12ms (Views: 2.7ms)

Headers Log

Request URL:http://0.0.0.0:3000/api/entries
Request Method:POST
Status Code:201 Created
Request Headers (14)
Request Payload
{"_id":"4f38152c504b9345dc000005","name":"Bloip","winner":true}


As you can see when I complete the 'entry.save()' on a current entry, which should be an update, the json is showing a POST instead of a PUT which mongoid is doing nothing with and the DB shows no changes. After googleing I found the following articles but nothing really helped.

link
link

I hope someone can help.

Avatar

What about Knockback http://kmalakoff.github.com/knockback ? It is a hybrid of Backbone and Knockout, seems to take the best parts from both.

Avatar

+1 for testing and +1 for future episodes on PayPal recurring subscriptions!

Avatar

As a web developer, I know some clients love cutting corners and don't secure things like they should. I mean, look at Sony and their recent PSN issues. So I only checkout from PayPal except on sites like Amazon. I've never heard of PayPal servers getting hacked.

Avatar

doesn't work when multiple paginates on the same page , even using different :param_name .... there is only one 'current_page' checked
need to be improved ...
I'll be back to will_paginate ....

Avatar

Thanks! I was going nuts because of this :)

Avatar

From what I can tell, sometimes, if you do a massive update over all records in a table, you may not want to run the sweeper on every record save. So you only activate the sweeper when you know you need it, for example during a certain controller.

However, if your more typical use is CRUD in ActiveAdmin, well then... perhaps doing a model observer would work (never tried).

Avatar

I don't know if anyone else ran into this problem but I had to put

ruby
def destroy
    #does stuff
    cookies.delete(:auth_token)
    #does stuff
  end

otherwise it would blow up when redirected back to the homepage after deleting a user account.

Avatar

you didnt need to roll back you probably were trying to use/login with a user-account that was already in your database. After doing the tutorial, create a new user so the auth_token column is populated and it will fix your error. @fritzsche created a rake tasks that will fix all your current users in your database incase you dont want to do a rake db:migrate:reset.

in short you cannot login with a old user after doing this.

Avatar

When writing a presenter from scratch, what is the best way to access the rails helpers? Inside the class I'd have a @context variable which would be used to call the view helpers,

e.g. @context.link_to "help"...

Avatar

Maybe good to mention that with the getScript function the cache is disabled by default (http://api.jquery.com/jQuery.getScript/)
For non user specific content you may consider to enable this to get even a better performance due to http caching

Avatar

If I am not mistaken Grupon uses a similar technique to this, probably not this exact technique, but a similar concept, show a static cached page, then fill in any user info with ajax calls.

Avatar

Well actually, BackboneJS serves a different purpose than jQuery. With jQuery - your large web application can get really messy and difficult to maintain. Frameworks like Backbone, Ember, Spine, Batman etc provide architecture, organization and convention to your client side code as well. Just like Rails provides all these things to your server side code.

Avatar

Best thing I learnt in this screencast - Rails doesn't scale if you have sleep calls in your controllers. :) lol

That was a good one Ryan. :)

Avatar

Thanks Ryan, this is perfect for me. My pages are very complex involving multiple models and they only change once per day. I only have a couple user-specific elements to load via JS. Time to get to work implementing this.

Avatar

Nice, I am satisfied, but yes I would like to see more on this topic, especially on error handlings like insufficient funds as well as tests and what is needed to be set in place in rails 3.2

Avatar

I can't imagine this to be a feasible solutions for more complex applications or pages.

It's difficult to maintain. Just imagine you are using the same method on tens or hundreds of pages in your application. The javascript will get convoluted. You'd probably use different JS files for each page but that would force you to put all your user-specific code into partials, meaning you'd have hundreds of partial files lying around. It will be a mess.

Performance. Sure, as long as you are on localhost everything will be blazingly fast. However, once you are on a remote server and the pages are a bit more complex the user will inevitably experience delays before the elements pop up. One should also consider the extra times it takes to render the partials, especially when rendering collections.

I am sure that there exist some scenarios where this approach is appropriate. For example, if you have a very large page with mainly static content. Still, for most cases, I think the drawbacks of this approach by far outweigh the benefits and that action or fragement caching would probably a better solution.

Avatar

Yeah, I was thinking about the delay in loading different elements. So I am guessing the benefit of caching outweighs the milisecond-ugliness for mostly the admin, like the edit/destroy buttons, headers or anything else, I suppose admins can tolerate that. But if it does happen on the client facing elements, I guess a one can do a complete $('#container').show() preceded by #container{display:none} css with an "Loading" HTML message. That way, it looks a bit more professional and certainly is going to be lighter for the server still (just serving HTML files like the 90's)

Avatar

i'm having the exact same issue as @zafriedman; so should we be working where tabs are as spaces when using coffeescript? rather frustrating as i've always had everything of mine setup where tabs are tabs and not interpreted as spaces.

Avatar

Thanks Mike ang Nik for your responses...

Nik's first interpretation was what I was reffering to, but I didn't consider the security of the controller (that I actually do in my projects). Feeling such a fool now! haha

Thanks

Avatar

I'm really confused with the idea to send partial HTML each time trough AJAX. The partial itself may become heavy to load, and every time the page loads, header may appear with the unpleasant delay.

Avatar

Hi Federico, I am interpreting your concern in two different ways. One, in plain words, is that you are concerned people can do admin stuff simply by turning off CSS. Correct me if I am ignorant that you actually already know that's not possible IF you do something like before_filter authorize_user! with Devise in your controllers. - Which brings me to a second possible interpretation of your concern: you simply are talking about that there is one more scenario where people might SEE the Edit/Destroy links, a purely interface concern, not one of security. I mean, MOST people don't disable their CSS, so the small bunch that happen to, you can NOT render the Edit links and send a javascript request to check for Admin, then return a evaluated template to each place needing these links and grab the proper ID as you loop along doing template inserting. That way, it's definitely not a problem if they do $('*:hidden').toggle(). But then again, if you don't have CSS turned on, you might also have Javascript turned off as well. And in that case, I guess you might have to resort to some trickier routing conditions and serve two different html files?