RailsCasts Pro episodes are now free!

Learn more or hide this

Recent Comments

Avatar

Thanks Andy, I will try that. I still am wondering if 10.04 LTS is better than 11.10. because I have this extra box lying around. The plan is to set it up and put it in my routers DMZ and then access my test sites from outside my home office. Can't do this with a VirtualBox setup

Avatar

I noticed that I get the same error trace even at 3:45. When I look at the html file being generated, I see that raffler.js is placed before backbone.js. So the raffler script is being loaded before backbone?

html
<!DOCTYPE html>
<html>
<head>
  <title>Raffler</title>
  <link href="/assets/application.css?body=1" media="screen" rel="stylesheet" type="text/css" />
<link href="/assets/main.css?body=1" media="screen" rel="stylesheet" type="text/css" />
  <script src="/assets/jquery.js?body=1" type="text/javascript"></script>
<script src="/assets/jquery_ujs.js?body=1" type="text/javascript"></script>
<script src="/assets/collections/entries.js?body=1" type="text/javascript"></script>
<script src="/assets/models/entry.js?body=1" type="text/javascript"></script>
<script src="/assets/raffler.js?body=1" type="text/javascript"></script>
<script src="/assets/routers/entries.js?body=1" type="text/javascript"></script>
<script src="/assets/views/entries/index.js?body=1" type="text/javascript"></script>
<script src="/assets/underscore.js?body=1" type="text/javascript"></script>
<script src="/assets/backbone.js?body=1" type="text/javascript"></script>
<script src="/assets/entries/index.js?body=1" type="text/javascript"></script>
<script src="/assets/application.js?body=1" type="text/javascript"></script>
  <meta content="authenticity_token" name="csrf-param" />
<meta content="D17d/z61caff+D96DLjvNyLEKTSuvazXlegAu+DZAGs=" name="csrf-token" />
</head>
<body>

<div id="controller">Loading...</div>

My application.js file is as follows

js
// This is a manifest file that'll be compiled into including all the files listed below.
// Add new JavaScript/Coffee code in separate files in this directory and they'll automatically
// be included in the compiled file accessible from http://example.com/assets/application.js
// It's not advisable to add code directly here, but if you do, it'll appear at the bottom of the
// the compiled file.
//
//= require jquery
//= require jquery_ujs
//= require_tree .
//= require underscore
//= require backbone
//
//= require .//raffler
//
//= require_tree ../templates/
//= require_tree .//models
//= require_tree .//collections
//= require_tree .//views
//= require_tree .//routers
//= require_tree .

Sunil

Avatar

Hey Alan,
Thanks for the post. I added the line, but it is still giving the same error trace. I restarted the server and everything. I even started from fresh in another computer (running Ubuntu 11.04). Same problem (I tried both Chrome and Firefox browsers). I am following Ryan's instructions step by step.

Before I spend time digging deep into this, any other help/suggestions will be really appreciated.

Sunil

Avatar

Hi Ryan. I was wondering how you test validations. Do you always do it through integration tests (like in the example below) or do you use something else?

ruby
visit new_employee_path
click_button "Save"

page.should have_content "Name can't be blank"
page.should have_content "Age can't be blank"

fill_in "Name", :with => "John Doe"
fill_in "Age", :with => "something"
click_button "Save"

page.should have_content "Age must be a number"
# ...

If you do use integration tests, what's your advice to make the code cleaner/less repetitive?

Thanks for the great screencast!

Avatar

Chris you could set up Vagrant / Virtual box, which would give you the flexibility to test different OS versions.

Avatar

Thanks Chris, now things look clear to me:)

Avatar

centaure, I had the same problem and figured it out.

Your application.js file must be like this:

javascript
// This is a manifest file that'll be compiled into application.js, which will include all the files
// listed below.
//
// Any JavaScript/Coffee file within this directory, lib/assets/javascripts, vendor/assets/javascripts,
// or vendor/assets/javascripts of plugins, if any, can be referenced here using a relative path.
//
// It's not advisable to add code directly here, but if you do, it'll appear at the bottom of the
// the compiled file.
//
// WARNING: THE FIRST BLANK LINE MARKS THE END OF WHAT'S TO BE PROCESSED, ANY BLANK LINE SHOULD
// GO AFTER THE REQUIRES BELOW.
//
//= require jquery
//= require jquery_ujs
//= require_tree .
//= require underscore
//= require backbone
//
//= require .//raffler
//
//= require_tree ../templates/
//= require_tree .//models
//= require_tree .//collections
//= require_tree .//views
//= require_tree .//routers

And it should be like this:

javascript
// This is a manifest file that'll be compiled into application.js, which will include all the files
// listed below.
//
// Any JavaScript/Coffee file within this directory, lib/assets/javascripts, vendor/assets/javascripts,
// or vendor/assets/javascripts of plugins, if any, can be referenced here using a relative path.
//
// It's not advisable to add code directly here, but if you do, it'll appear at the bottom of the
// the compiled file.
//
// WARNING: THE FIRST BLANK LINE MARKS THE END OF WHAT'S TO BE PROCESSED, ANY BLANK LINE SHOULD
// GO AFTER THE REQUIRES BELOW.
//
//= require jquery
//= require jquery_ujs
//= require underscore
//= require backbone
//
//= require .//raffler
//
//= require_tree ../templates/
//= require_tree .//models
//= require_tree .//collections
//= require_tree .//views
//= require_tree .//routers
//= require_tree .

Notice the //= require_tree . statement, it must be the last one.

By the way Ryan, I'm the newest "pro" member (just registered) and your job is awesome, keep up the great work. And as a suggestion, warn people about this issue, it may save a couple hours.

Hope it helps!

Avatar

You can limit what servers will execute a task by passing a HOSTS environment variable like this:

cap HOSTS=new.server.com deploy:setup
Avatar

Ryan, Great show. One question though. Why Ubuntu 10.04 LTS and not Ubuntu 11.10? Is there any issues with Ruby or Rails on Ubuntu 11.10? The reason I'm asking is that I was going to try this with a spare machine I have lying around and it currently has 11.10 installed (nothing else). If there are issues then I will just re-roll it with 10.04 LTS

Avatar

Awesome episode!

I would love to see how to use recurring payments with IPN callback messages :)

Avatar

I'm having trouble using Jbuilder with Rails 3.1.0, specifically my Jbuilder view (index.json.builder) is rendering empty, and throwing no errors. I've placed the issue on Stack hoping to get some help:

http://stackoverflow.com/questions/9999395/rails-3-1-jbuilder-rendering-empty-views

Has anyone else seen this behavior?

Avatar

you may want to update

ruby
match '*path', to: redirect("/#{I18n.default_locale}/%{path}")

to be something along the lines of

ruby
match '*path', to: redirect({|params, request| "/#{I18n.default_locale}#{request.fullpath}"})

If you want to maintain the request format sent in /posts.json, also it should be noted that a 302 redirect will not resubmit post data, possibly a 307. This method of redirection you need to pay close attention that any urls placed in ajax calls have the locale otherwise there may be some unforeseen bugs, especially with POST requests

Avatar

I don't get the "home page" alert dialogue at 5:35. Note that I did get the "Hello from Backbone" alert at 3:45.

Any help will really be appreciated. I am running rails 3.1.2 in Ubuntu 10.04.

Also note that I had to include the gem "therubyracer" to get the server running at the start (I was facing the issue similar to https://github.com/rails/rails/issues/2963)

Below are the relevant parts of the code and the error trace I get in the console.

app/assets/javascripts/routers/entries.js.coffee

ruby
class Raffler.Routers.Entries extends Backbone.Router
  routes:
    '': 'index'

  index: ->
    alert "home page"

app/assets/javascripts/raffler.js.coffee

ruby
window.Raffler =
  Models: {}
  Collections: {}
  Views: {}
  Routers: {}
  init: ->
           new Raffler.Routers.Entries()
           Backbone.history.start()

$(document).ready ->
  Raffler.init()

The error trace I get in the console is:

In entries.js(5): Uncaught ReferenceError: Raffler is not defined

ruby
(function() {
  var __hasProp = Object.prototype.hasOwnProperty,
    __extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor; child.__super__ = parent.prototype; return child; };

  Raffler.Collections.Entries = (function(_super) {
entries.js:5Uncaught ReferenceError: Raffler is not defined

    __extends(Entries, _super);

    function Entries() {
      Entries.__super__.constructor.apply(this, arguments);
    }

    Entries.prototype.model = Raffler.Models.Entry;

    return Entries;

  })(Backbone.Collection);

}).call(this);

In entry.js(5): Uncaught ReferenceError: Raffler is not defined

ruby
(function() {
  var __hasProp = Object.prototype.hasOwnProperty,
    __extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor; child.__super__ = parent.prototype; return child; };

  Raffler.Models.Entry = (function(_super) {
entry.js:5Uncaught ReferenceError: Raffler is not defined

    __extends(Entry, _super);

    function Entry() {
      Entry.__super__.constructor.apply(this, arguments);
    }

    return Entry;

  })(Backbone.Model);

}).call(this);

In entries.js(23): Uncaught ReferenceError: Backbone is not defined

ruby
(function() {
  var __hasProp = Object.prototype.hasOwnProperty,
    __extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor; child.__super__ = parent.prototype; return child; };

  Raffler.Routers.Entries = (function(_super) {

    __extends(Entries, _super);

    function Entries() {
      Entries.__super__.constructor.apply(this, arguments);
    }

    Entries.prototype.routes = {
      '': 'index'
    };

    Entries.prototype.index = function() {
      return alert("home page");
    };

    return Entries;

  })(Backbone.Router);
entries.js:23Uncaught ReferenceError: Backbone is not defined

}).call(this);

In index.js(17): Uncaught ReferenceError: Backbone is not defined

ruby
(function() {
  var __hasProp = Object.prototype.hasOwnProperty,
    __extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor; child.__super__ = parent.prototype; return child; };

  Raffler.Views.EntriesIndex = (function(_super) {

    __extends(EntriesIndex, _super);

    function EntriesIndex() {
      EntriesIndex.__super__.constructor.apply(this, arguments);
    }

    EntriesIndex.prototype.template = JST['entries/index'];

    return EntriesIndex;

  })(Backbone.View);
index.js:17Uncaught ReferenceError: Backbone is not defined

}).call(this);

In raffler.js(9): Uncaught TypeError: Undefined is not a function

ruby
(function() {

  window.Raffler = {
    Models: {},
    Collections: {},
    Views: {},
    Routers: {},
    init: function() {
      new Raffler.Routers.Entries();
raffler.js:9Uncaught TypeError: undefined is not a function
      return Backbone.history.start();
    }
  };

  $(document).ready(function() {
    return Raffler.init();
  });

}).call(this);
Avatar

I would love to see a Chef + Vagrant episode.

Avatar

Nice one, for dealing with locales in the URLs Routing Filter Unless API might be useful.

Avatar

We think that the very basic i18n approach of rails needs some improvement.
That is why we built a product to handle translations much more easily: phrase

If you have a rails/ruby project that uses the i18n gem, this could be the right thing for you to use.

Avatar

Maybe phrase would be a good replacement for the shut down copycopter.
We are currently in beta for our i18n service application: phrase

If you have a rails/ruby project that uses the i18n gem, this could be the right thing for you to use.

And since we are on Railscasts, we have a screencast, too ;-)

Avatar

Managing i18n and l10n can be very painful, especially in large projects with multiple persons working on translations.

That is why we built a product to make things a lot easier: phrase

If you have a rails/ruby project that uses the i18n gem, this could be the right thing for you to use.

And since we are on Railscasts, we have a screencast, too ;-)

Avatar

Great episode, thanks Ryan.

One thing, maybe because I'm not familier with Capistrano, I'm curious about what will happen if I run "deploy:install" task twice, for example, in order to add a new server.
I assume Capistrano will try to install everything both to the new one and which has had those already.

If so, will it be OK(no problems as its consequence)? or otherwise is there anyway to avoid it, such like running a task on a specific server?

Avatar

to get the value for each entry he used this:

<% for entry in @entries.models: %>
<%= entry.get('name') %>
<% end %>

that didn't work for me, I modified it to this one:

<% for entry in @entries.models: %>
<%= entry.get('entry').name %>
<% end %>

and it works,
Any Idea?, I want the sipler code rather than the code I came up

Thanks

Avatar

GitHub stopped building gems in October of 2009. They suggest RubyGems.org.

See RubyGems' docs on Distributing Gems

bash
-bash> gem push mygem-1.2.3.gem 
Enter your RubyGems.org credentials.
Don't have an account yet? Create one at http://rubygems.org/sign_up
   Email:   ^CERROR:  Interrupted

Create an account: http://rubygems.org/sign_up

If you want to use gem commands from the command line, you'll need a ~/.gem/credentials file, which you can generate using the following command:

bash
-bash> curl -u bart https://rubygems.org/api/v1/api_key.yaml > ~/.gem/credentials
Enter host password for user 'bart':
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
  0    56    0    56    0     0     53      0 --:--:--  0:00:01 --:--:--   495

Try again:

bash
-bash> gem push mygem-1.2.3.gem 
Pushing gem to https://rubygems.org...
Successfully registered gem: mygem (1.2.3)

Note that you can only push a single gem version once; if you update your gem in any way, and want to update rubygems.org, you'll have to increment the version number, build the gem again, git add new/changed files, remove the old version from git tracking, and then push the new version.

Avatar

Ryan allowed me to Gemify these recipes. Check it out here.

I added a few of my own changes such as setting up a firewall, setting the timezone to UTC and a task for tailing the logs. I plan on adding the Apache, Passenger and MySQL recipes from episode 335 as well.

Avatar

Well I'll answer my own question. :-) I dug into Puppet last week - the tools it has for creating users, installing packages configuring systems etc would take a lot of time to rebuild from scratch in Capistrano. So I've become a Puppet user & believe its worth the time to learn. But this is a complicated tool, and it still seems like there is a need for a simpler deploy tool than Chef or Puppet.

Avatar

Is anyone else having issues viewing this episode?

It either won't start streaming or will stop streaming about a minute in. Wouldn't let me download the MP4 version either.

Avatar

Hi, do you use something like globalize3 for content translation?

I curious about your approach to this problem (e.g. do you build something from scratch or use something almost-ready? How do make the translators work? etc...)

Avatar

+1 (x10^99999)

I've just seen the old I18n episode and discovered on of the globalize3 authors (svenfuchs) is even an rails-i18n author. It would be cool an episode about globalize3 (I wonder if some way to build translation interface on it exists...)

Avatar

You have to install the python-software-properties package ;)

Avatar

It seems that Copycopter is officially shutting down on 15th April and the service will not live on in any way.

https://copycopter.com/pages/shut-down

Sad.

Avatar

Just tried working through this exercise - the User.save does NOT save the encrypted passwords to the table, although it does save all the other user info. No error messages are generated, but the save is obviously incomplete as it strays on the sign-in page!
Any ideas? I am running on Windows XP, using SQlite3 and Rails 3.2.1.

Avatar

Is there a referral code for Linode we can use when we sign up, so Railscasts can receive a referral fee?

Avatar

thanks Nicolai Seerup.. was facing this problem and you pulled me out.

Avatar

For anyone who is still having problems with the syntax for the inserted crop_command in cropper.rb, what worked for me (rails 2.3.5, ruby 1.8.7) was

"-crop #{target.crop_w.to_i}x#{target.crop_h.to_i}+#{target.crop_x.to_i}+#{target.crop_y.to_i} "

No additional quote marks

Avatar

The screencasts are so perfectly made, I am trying to do the same at my http://happycasts.net (One Linux Tip per Week), to make sth useful and beautiful at the same time.

Railscasts Rocks!!!

Avatar

Has anyone been able to get the nginx :install recipe to work on Debian Linux? There is no add-apt-repository command available.

Avatar

Has anyone checked out the offering from ZURB? I use it with Bourbon to do pretty much everything I do with Compass.

It even has a gem

Avatar

This fixes encoding issue, thanks!

Avatar

A little note: Instead of using the set_default method here (or Capistrano's own _cset), a similar effect can be achieved by using the second parameter to the fetch method like so:

ruby
directories_to_create = fetch(:directories_to_create, [])

If I now use set(:directories_to_create, Dir[...]) that gets used, otherwise it uses the second parameter as the default (in this case just an empty array).

Avatar

Heroku is good in a lot of situations. However, what disappoints me a little is the lack of JRuby and Rubinius support. This is where EngineYard shines a little more. A lot of Ruby developers probably aren't aware how much more concurrency you can gain using a VPS running JRuby/Rubinius with Puma/Trinidad/TorqueBox rather than running Thin or Unicorn.

For example, TorqueBox (a JRuby-specific App Server) is a "real" application server that runs independently (it's practically a whole infrastructure, not something that just binds to a port), and you deploy your application to this app server. This one single instance uses threads (JVM, not MRI) for everything you would normally have to spin up processes for with MRI (which translates to Dynos on Heroku).

There have been people that took their worker farm (120 worker processes) from around 60gb in memory usage (yes, 60 gigabyte) spread across like 10 dedicated servers, down to about 1gb memory usage on a single server by switching from process-based scaling to thread-based with JRuby or Rubinius. That is huge. Not only does it scale well, you reduce a lot of costs, the infrastructure becomes more simple and imagine running 120 workers on Heroku, the bill goes through the roof. It really makes me wonder why there aren't more people supporting JRuby and Rubinius. (Note that this also applies to concurrent web requests of course, not just workers).

However, I definitely agree you when it comes to being more at ease when deploying to Heroku, simply because you cannot do any administrative tasks. When something breaks, needs updating, and what not, Heroku is the one taking care of it all while you sleep. It mainly depends on your application's requirements. If you have a basic app that doesn't really need a lot of concurrency (be it in the web process, or worker process) then it's all good. However, once you have use cases where you run large worker farms or tremendous amounts of traffic, it might change your game completely.

These are all interesting discussions, I guess basically it comes down to picking the right tools for the job and dealing with certain tradeoffs on each side. But it'd be good to let everyone know it's not just MRI, Thin and Unicorn out there.

What'd I'd love to see from Heroku is (real) support for JRuby (now) and Rubinius (once RBX hits 2.0), perhaps 1GB of ram per Dyno (at a higher price) and the ability to use TorqueBox flawlessly. I think this would be a total game changer for deployments and power per Dyno.

tl;dr:

  • Check out Ruby Implementations:
    • JRuby
    • Rubinius
  • Check out thread-enabled app servers:
    • Puma
    • Trinidad
    • TorqueBox (this is pretty much one-of-a-kind, a beast, not comparable to any other Ruby app server to date)
  • @Heroku: Please add real support for JRuby and TorqueBox.
Avatar

I like Twitter Bootstrap because it has same nice CCS features and javascript features like pophover, drop down menus, etc. I suppose one can use jQuery to achieve that but Twitter Bootstrap makes it really nice. My only compliant is that it uses LESS instead of SASS.

Back to Compass, can one have BOTH Compass and Twitter Bootstrap? I would like to have the dynamic nature scaling for mobile devices while having the mixing of Compass.

Avatar

Depends on the problem. But in general yeah you should be looking at the logs. There is the server log and also production logs. I don't think you want to be looking at the development log when in a production environment.

Avatar

Hi! Please help!
I am stuck on this error:

ActiveRecord::UnknownAttributeError in SurveysController#new
unknown attribute: survey_id

Rails 3.2.2

models/survey.rb
class Survey < ActiveRecord::Base
  has_many :questions, :dependent => :destroy
  accepts_nested_attributes_for :questions, :reject_if => lambda { |a| a[:content].blank? }, :allow_destroy => true
end
models/question.rb
class Question < ActiveRecord::Base
  belongs_to :survey
  has_many :answers, :dependent => :destroy
  accepts_nested_attributes_for :answers, :reject_if => lambda { |a| a[:content].blank? }, :allow_destroy => true
end
models/answer.rb
class Answer < ActiveRecord::Base
  belongs_to :question
end
```surveys_controller.rb
...
def new
  @survey = Survey.new
  3.times do
    question = @survey.questions.build
    4.times { question.answers.build }
  end
end
...
_form.html.erb
<%= form_for @survey do |f| %>
  <%= f.error_messages %>
  <p>
    <%= f.label :name %><br />
    <%= f.text_field :name %>
  </p>
  <%= f.fields_for :questions do |builder| %>
    <%= render "question_fields", :f => builder %>
  <% end %>
  <p><%= f.submit "Submit" %></p>
<% end %>
Avatar

Hi Carl, gummybears - thx for help.

In the end I found the solution for installing mysql by sending the password via capistrano when the blue screen appears- its quite simple. Here is the solution:

ruby
# capistrano task for installing mysql
run "#{sudo} apt-get -y install mysql-server" do |channel, stream, data|
  # prompts for mysql root password (when blue screen appears)
  channel.send_data("#{mysql_root_password}\n\r") if data =~ /password/
end

Also, for those that are interested - user creation can also be automated via capistrano (that is the only thing Ryan did manually in this episode). You can check that at this link.
It's a bit complicated, but in the end you don't even have to ssh to machine prior to running capistrano recipes.

I hope this is useful to someone :)

Avatar

Edit: Executing the command on the server without Capistrano seems to work. :/

Avatar

Great screencast :)

But I ran into a problem when Capistrano tries to build my assets. I have no idea what's going on, if I start rails locally, everything works fine!

log
  * executing `deploy:assets:precompile'
  * executing "cd /home/deployer/apps/app/releases/20120331112826 && bundle exec rake RAILS_ENV=production RAILS_GROUPS=assets assets:precompile"
    servers: ["example.com"]
    [example.com] executing command
    [example.com] sh -c 'cd /home/deployer/apps/app/releases/20120331112826 && bundle exec rake RAILS_ENV=production RAILS_GROUPS=assets assets:precompile'
 ** [out :: example.com] rake aborted!
 ** [out :: example.com]
 ** [out :: example.com] cannot load such file -- bcrypt
 ** [out :: example.com]
 ** [out :: example.com]
 ** [out :: example.com] (See full trace by running task with --trace)
 ** [out :: example.com]
    command finished in 5227ms
*** [deploy:update_code] rolling back

But in my Gemfile I have bccrypt-ruby set up.

Gemfile
gem 'bcrypt-ruby', :require => "bcrypt"
Avatar

I have the same issue, couldn't resolve it.
So I ran the command manually and commented it out.

Avatar

I can't seem to figure this out at this moment in time. I created a new application from scratch, added a view, copied a template for the application.html.erb to contain a navbar. When you make your window smaller than 800px so the menu merges into a pulldown, you are unable to open the navbar. I uploaded the application if someone can look at it.

https://github.com/koldrid/testapp

Avatar

Hi,

I got some problem about my app.
And Have no idea about where to look the development.log?