RailsCasts Pro episodes are now free!

Learn more or hide this

Recent Comments

Avatar

Hey Ryan, quick question, how do you get your project folder to be part of the textmate window rather than the usual drawer style (like this; http://blogallalong.com/wp-content/uploads/2009/04/textmate-project-drawer.png) ?

Thanks for the all superb videos over the years! :)

Avatar

@hounddog @jowls

The mass_assignment_authorizer method now takes a role parameter in Rails 3.1.

You can see for yourself here.

Avatar

I forgot to add that with the above changes, you can remove the "password_salt" column.

Avatar

I can't believe no one has taken to calling you Dr. Bates yet. Not just for your coding examples, but also because of your ESP in delivering these episodes exactly when others are in need of them. Thanks again!

Avatar

Hi,

when I try

ruby
 puts "hello world"

I get

<code>ruby<br> print "hello world" <br></code>

but not get
<pre lang="ruby">
Thanks for the podcast.

Avatar

Ryan,
As usual, relevant info presented succinctly with style.

How does Guard compare with Autotest (and Spork)?

I've been using autotest/spork for a while now, and it works well, but if you change a controller or routes the proper specs are run, but fail because spork is running the old version. Does Guard do this better?

Avatar

Would be really helpful if searchlogic would be ported to rails 3. I want to upgrade a rails 2.3 project to rails 3, would hate to have to remove searchlogic.

Oh well.. that's a problem with most rails plugins/gems - they stop being upgraded after a while and when you have an older project that uses them then you are out of luck.

Avatar

In case anyone else is having problems getting this to work with gmail apps, there is a little error in Ryan's demo code. In mail_setup.rb, user_name must be fully qualified, as in user@domain.tld, not just user. In the example, Ryan has
:user_name => "railscasts"
...where it should be...
:user_name => "railscasts@railscasts.com".

Even I have the same doubt

Avatar

Hi Ryan,

thanks for the great episode. After watching it it was keen trying it myself and downloaded the complete source code. After extraction I installed the bundle, did a "rake db:migrate" and tested the app in the browser, all worked fine.

When following the coding using the auth-before tree as a start I soon got this error:

Failure/Error: let(:user) { Factory(:user) }
     ActiveRecord::StatementInvalid:
       Could not find table 'users'

I checked in the auth-after (bundle, rake db:migrate, guard) and I do get the same error. So there must be something wrong with my testing environment as the regular development environment find the user table in the browser. I am on Ubuntu Linux, I installed/updated libnotify, rb-inotify, and childprocess as guard did complain about not finding them or them being out-dated...

Any help would be appreciated.

Cheers Juergen

SOLVED:

rake db:test:prepare

Should have guessed... sigh

Avatar

You're right. The Timecop version is more deterministic and that is what our tests should be.

But there maybe situations where you can't use Timecop and you don't need to test on milliseconds (with an increased delta to get a more robust test), then it might be a good solution too.

Avatar

I cannot get capybara to work on rails 3.1.0.rc5.
I wonder if somebody knows how to make it work.

Avatar

This railscast extends work done in the Authentication from Scratch railscast. You'll find the missing code in there.

Avatar

I have a few small simplifications that I'll share. I'm new to Rails (but not programming in general) so I apologize if anything is bad practice.

ruby
# In the User model. This is now an instance method.
def authenticate(password)
  self if Password.new(password_hash) == password
end

def encrypt_password
  self.password_hash = Password.create(password)
end
ruby
# In the users controller. 
def create
  user = User.find_by_email(params[:email]).authenticate(params[:password])
  ...etc...
end
Avatar

It can have unpredictable behaviour. What if send_password_reset first sets attribute value and then does something longer than a second due to high system load? What if send_password_reset doesn't really set attribute value but some previous test does and tests are not fully isolated? You'll have test that breaks from time to time in random manner.

Avatar

Maxsy and airyym,

Regarding the "uninitialized constant User::BCrypt" problem, you need to run "bundle install" in the terminal and then restart the rails server.

Avatar

If somebody gets stuck on the part when form doesn't generate nested fields
<% f.fields_for :questions do |builder| %>
then in Rails 3.1 you have to change the tags to <%= %>

I've wasted hours on that...

Avatar

That's what I've been doing as well. I'm giving Timecop a try now and it's pretty good, not much changed except a few tests so far.

Avatar

It should be cookies.delete(:auth_token), not cookies.delete[:auth_token].

Avatar

Signing cookie adds overhead to the size (http://yuiblog.com/blog/2007/03/01/performance-research-part-3/). So that depends on the security you need.

For better security you want to save also a expiry time inside the cookie and sign it. Then you can check e.g. that the cookie isn't more than year old so that info in old computers cannot be abused. But in most cases the way described in this screencast is enough.

Avatar

I can confirm that this method works. Thanks for the example.

Avatar

hey guys please what tmbundle or snippet allows you to type in 2 place at the same time...for instance when you open a p tag, if you change the opening tag to strong, the closing ta automatically changes too. He used something like that around 2:45 - 2:50

Avatar

Testing with times involved is mostly no fun, particularly because I never heard of Timecop before :) But I found a way to manage it with RSpec matchers:

ruby
it "saves the time the password reset was sent" do
  user.send_password_reset
  user.reload.password_reset_sent_at.should be_within(1.second).of(Time.zone.now)
end
Avatar

(newbie alert)

I'm having a hard time understanding how the successful "signed up!" message appears as shown in the video, esp when comparing it to the downloadable episode code. There doesn't seem to be anything in a View or Layout to output flash[:notice]

Avatar

Your just too awesome !! I am blind with true awesomeness :)

Avatar

I thought exactly the same. I always just mock Time.zone.now (or Time.now) to test if the time gets set.

I really would like to hear what the benefits of using timecop are if you only want to test if the time gets set to Time.zone.now

Avatar

Hi Ryan,

I have a small question about this testing approach. Since I'm not testing a "controller", I don't have the session/params/cookies variables to work with.

My authentication depends on storing session[:user_id] but I can't set it from the integration test since I get that session is not defined.

How can I get around that?

Thanks!

Avatar

whoops, had those geocoded_by calls reversed

Avatar

Is it possible to make the method of geocoding conditional? i want to geocode by ip_address by default but if the user updates there current address, I want to then geocode by that.Anyone have ideas on how to do that? something like

ruby
class Patron < ActiveRecord::Base
  attr_accessible :ip_address, :address, :latitude, :longitude
  
  unless self.address.nil?
    geocoded_by :ip_address
  else
    geocoded_by :address
  end  
  
  after_validation :geocode 
end
Avatar

Hey, if anyone if having the same problem, you need to use preserve before sending the data.

[source]
http://stackoverflow.com/questions/6325416/maruku-incorrectly-parsing-second-line-of-code-blocks

Avatar

Hi Ryan, fantastic episode as alwais.

Do You know a way to test file uploads? e.g size, timeout, type of files (mime), image dimensions,.. ?

And where to put this stub files?

Avatar

My first impulse when watching the first part of the episode was "just mock the Time.zone method so that Time.zone.now returns a fixed date"

Wouldn't that have been enough?

Avatar

Does anyone have a problem with Internet Explorer? I couldn't get the session store accross subdomains working well...

It works fine most of the times, but sometimes it seems the session is different between subdomains... example: if I log out from subdomain1.domain.com and after that I visit subdomain2.domain.com for some reason I am still log in!

The behavior is strange, but it just happen in Internet Explorer =/ and, as I said before, it only occure sometimes...

Any ideas?

Avatar

I've been trying to get the user_id of whoever created the new items to be put into the column on the authors table. Been trying like this Author.create!(:name => $1, :user_id => self.user_id) but I keep getting NULL entries into the database. Any ideas?

Avatar

Using this gist you can also add custom entries.
https://gist.github.com/952240

Any idea how to get the user_id from the user who posted the entry? been trying Author.create!(:name => $1, :user_id => self.user_id) but I keep getting NULL entries into the db.

Avatar

For some reason cookies.delete[:auth_token] does not work in Rails 3.1.
I had to use cookies.delete :auth_token to get it to destroy the session.

Avatar

I just installed the Rails 3.1.0.rc5 version and I found that the line:

ruby
config.active_record.identify_map = true

on application.rb has been removed, this must be cause that intruction was not working at all

Avatar

Since Rails 3.1 comes with CoffeeScript installed we get the gem ExecJs Execj that "lets you run JavaScript code from Ruby" but you need to have a Javascript Runtime installed. ExecJs chooses the best runtime that we have.

You can install any of these runtimes:

  • therubyracer - Google V8 embedded within Ruby
  • therubyrhino - Mozilla Rhino embedded within JRuby
  • Johnson - Mozilla SpiderMonkey embedded within Ruby
  • Mustang - Mustang V8 embedded within Ruby
  • Node.js
  • Apple JavaScriptCore - Included with Mac OS X
  • Mozilla SpiderMonkey
  • Microsoft Windows Script Host (JScript)

I recommend to install TheRubyRacer or Johnson because are easy to install, You can install them with gems.

Avatar

Ok interesting to know. I was trying to stick with that as well, but I really ran into trouble when I wanted to test redirects and urls. Maybe there's a way to do this (cleanly), but I couldn't figure it out. Say you wanted to test a very simple create action that redirects to the show page. In the integration test you have something like:

ruby
visit new_user_path
fill_in :name, :with => "Ken"
click_button "Submit"

at this point, how can you access the controller variables to ensure that you redirect to user_path(@user). assigns(:user) wasn't working, and after days of searching, came to the conclusion this sort of test is best served in the controller specs. I supposed you could do something like:

current_page.should eq(user_path(User.last))

but that didn't seem right at all.

Avatar

I don't do controller or view tests because I feel they overlap too much with integration tests. Usually if something is too complex to go in an integration test then it should be moved into a model or helper and tested there in isolation. This makes it easier to handle a lot of branching paths and such as well.

I'm not very strict on refactoring test code, I feel it's better to be more direct there to reduce the possibility of bugs and odd dependencies. But when I do see a lot of duplication I like to move it into a module in the spec/support directory and do config.include in the spec_helper.rb

Avatar

If your users use internet explorer, the buttons and functionality doesn't even work! Is there a way to progressively enhance your usability by using pushState?

Avatar

I think it's still good to have a Timecop.return statement in spec_helper.rb in case something slips through, but I do think the block syntax is great for larger test cases where you want to isolate where it is frozen.

Avatar

Excellent cast as always, and I really like the testing angle. I've got a question though and I was hoping you or anyone else could help me out. I fairly experienced in the app folder, but not quite as much in spec. But alas, I have taken on Ryan's challenge last week and haven't opened the browser since. It's been going great, and I have tons of test coverage, but I'm worried I may have too much - or at least redundant tests. Specifically, I see a lot of overlay between my integration tests and my controller tests. I find that whichever one I write first, it covers about 75% of the other one. That really bugs me. So a few things:

  1. Is this normal? I get the feeling it isn't because there really wouldn't be 2 seperate areas to test the same thing.
  2. What's some good practices to make sure that there's little overlap between the 2 sections.
  3. Do you always start with integration tests, then more to controller, or what are the common coding flows that people use.
  4. I'm very good at refactoring app code, but test code, not so much, any suggestions on how to really learn good test code refactoring?

Thanks so much everyone.

Ken

Avatar

I can't get the password_validation to work properly. Whatever I enter in password_confirmation (even if it's not the same value as password), it'll save the user regardless :(

Avatar

Great screencast as always, thanks!

One possible improvement (at least for me) is the block usage of Timecop#freeze.

Instead of having to call #return explicitly, I prefer to put the frozen code in a block, like:

ruby
Timecop.freeze do
  user.send_password_reset
  # ...
end

That way it automatically returns from the frozen time and also makes explicit which code is frozen via indentation.

Avatar

Hi Ryan.

Have you thought about doing an episode about testing ajax functionalities?

Cheers, Kai

Avatar

I'm using nested forms to which I add fields dynamically with ryans gem nested_form. How could these fields be validated?

Avatar

How can change the default from "id" and "name" to something other than name (in my case its "account_number").

In the video he just says if you dont have "name", youll need further customization and i couldnt find anything anywhere.

Any help?

Avatar

I can't remember now why I chose FakeWeb over WebMock when I used it in railscasts.com, but it definitely does look more full featured. Thanks for bringing this up. Time to research it.