RailsCasts Pro episodes are now free!

Learn more or hide this

Recent Comments

Avatar

Have you tried the new kid in the block for image handling: dragonfly? I find it excellent, well done and very flexible. I update my RJCROP project to work with dragonfly: http://github.com/jschwindt/dragonfly_crop

Avatar

@Aaron, I plan to do an episode on upgrading a Rails 2 app to Rails 3 later. It will also act as a nice summary of the past Rails 3 episodes.

@Steve, thanks for the detailed responses here and your work on UJS in Rails.

@Yuval, The "js.erb" file acts as a view file, so it would not have access to controller methods. However you can move the methods into a Helper and it will be available in the view.

Avatar

I really need to complete my thoughts before I post these comments. :)

In the case of an action with more than one outcome (i.e. all of them, if you're doing error handling) would I essentially just move my entire block of RJS logic (posted above) to a correspondingly named js.erb file? Would it still have access to private methods within the controller?

Avatar

Thanks Ryan and Steve for your feedback. Ultimately, I will most likely use the legacy plugin for any production projects that I update from Rails 2.x to 3. There are just too many variables. Down the road, as I work on new projects, I'll definitely have a look at a full UJS implementation. Cheers.

Avatar

ak, i figured out my problem. maybe this will help you. i was trying to incorporate nested model form into an existing project and passed a wrong association to the link_to_add_fields method. hope that helps.

Avatar

Aaron, this might help. http://blog.peepcode.com/tutorials/2010/live-coding-rails-3-upgrade

Avatar

@Romain, its possible it could bite you, returning false is basically just like calling e.preventDefault() and e.stopPropogation() meaning it will stop the browsers from handling it (example clicking a link will no longer follow it), and it also will prevent the event from bubbling up the DOM.

@Jamie, what your referring to is graceful degradation and not UJS, due to limited time constraints only the later was tackled, its possible it could be addressed in the future.

@Yuval, not sure how UJS further complicated your project, however you mention programmatic generation of JS, which is precisely what the UJS project has changed.

The helpers only generate the data-* attributes and nothing more, the jQuery and Prototype drivers are meant as an easy way of performing common functionality.

It's completely possible, to not include the rails.js file at all and write your own custom behaviors . Also if you dont like the js.erb approach each of the drivers have implemented custom callbacks ( ajax:before, ajax:complete, etc..) that you can hook into along the way $("#myform").live('ajax:complete', function() { ... }); where you could handle the response data in anyway you want (also allowing all your JS to be merged in one file and prevent continuously returning / evaling it from the server.

UJS allows more flexibility if you fall in the 20% of the 80/20 rule there are many ways to accomplish the same goals and the defaults may not always be be best for you but the important thing is that it is now very easy to step away from the golden path when it comes to JS.

Avatar

me, to. i'm having the same issue with undefined method `klass' for nil:NilClass. if anyone could shed some light, i'd appreciate it. thanks!

dl

Avatar

I'll have to watch this later. Ryan if you are able to do an episode on converting a simple 2.3.5 app to work in 3.0.0beta, that would be awesome. I've been having trouble trying to do that myself.

Thanks.

Avatar

@Yuval, I don't have much experience with large JavaScript code bases so I hesitate to say much here, but the convoluted code might be resolved through better organizing/structuring of the files and functions.

I don't think this is a problem specific to UJS. Any large code base has a high potential to turn into spaghetti code and JavaScript is no exception.

On the other hand, the event driven programming style is somewhat unique with UJS so that may play a part here. I hope others with more experience than I will chime in here.

Regarding your second question. The :update option is RJS and does still exist in Rails 3. See my earlier comment for my opinions on this.

Avatar

Was also wondering if render :update still exists unaltered on the controller side. This is what most of my xhr controller actions look like. There are usually two possible outcomes to any action as well as processing other than simple view generation:

def whatever
   render :update do |page|
      if condition
         some processing
         page.replace_html... or some other rjs action
      else
         show_errors
      end
   end
end

This is vital functionality. Cheers.

Avatar

@Santiago, thanks for pointing this out. I took a look at the rails_xss plugin a while back but it was lacking much of the Rails 3 functionality. It looks like that has been resolved so I've updated the show notes for this episode to point this out.

@Jeff, I haven't tested the performance hit of the "h" method, but even with Rails 3 the escaping is happening when rendering the view so the performance may still be an issue in some situations

Caching the sanitized output in the database can get messy and I recommend holding off until you know the HTML escaping is the bottleneck. Also consider other forms of caching such as fragment caching which will likely offer more performance improvements over a database cache.

@Tobias, html_safe returns a new string (actually SafeBuffer) and html_safe! makes the current one safe. If you try "html_safe!" on a string it will not work because only a SafeBuffer can be marked safe.

This was done for performance reasons. See this blog post by Yehuda for details.
http://yehudakatz.com/2010/02/01/safebuffers-and-rails-3-0/

Avatar

Thanks for the cast Ryan. I know this comment won't be popular, but I have very mixed feelings about UJS.

I've worked on big ajax-heavy production projects with both prototype helpers and UJS JQuery, and the UJS projects inevitably ended up more obtrusive and convoluted. Mostly because of the sheer quantity of javascript files needed, as well as programatically generating javascript in rails or C# (gross) once you get into more complex tasks.

I'll still give this a try but remain somewhat skeptical.

Avatar

@Nico, Yes, you can render a js.erb partial if you need to generate JavaScript in a helper.

I rarely find the need to use RJS anymore. It worked well back when I could not stand JavaScript, but jQuery and other frameworks make JavaScript much nicer to work with.

Simple things like JavaScript "if" conditions are very ugly to do with RJS. I encourage you to learn to use JavaScript directly and it will be more flexible.

@Romain, in what way is "return false" dangerous? It basically tells the browser to not follow the "href" part of the link.

@Jamie, I can understand both sides here. In some ways I would like to see a "delete" action be there by default, but the implementation of the confirmation page would be a lot of duplication across controllers.

Certainly Rails could handle the confirmation page behind the scenes but I think that kind of implementation fits better in a plugin. I hope with Rails 3's approach to plugins it will be much nicer to write a plugin which extends "resources" in routes and adds a delete action and view.

I'll post this on your blog post as well which is probably the best place to continue the discussion.

Avatar

@Laser Lemon
same problem, solution was just to type this in linux console:
sudo ldconfig

Avatar

I still maintain that there should be a "delete" GET action by default similar to how we have "edit" for update. This would allow everything to work without javascript, is this not the whole point in unobtrusive javascript.

I wrote an article back in 2006 outlining why this is a good idea http://thelucid.com/2006/07/26/simply-restful-the-missing-action/

Avatar

This is a great screen-cast, but how do you display a nested attribute in the index view.

I keep getting nil?
error.

Avatar

undefined method `klass' for nil:NilClass

I am also seeing this error - im obviously doing something stupid here - and I see some other ppl have had(and resolved) the same issue.

could someone kindly explain to me what im missing here.

Thanks in advance!
ak

Avatar

@Steve : Ok i see. So in a "real" application it's quite dangerous to use "return false;", no ?

Avatar

@Steve: So to have a rails helper that outputs js I could e.g. render a js.erb partial in a helper? Is that what you mean? Anyway rjs had some nice functionality. Abstracting away from the actual js using ruby is nice. I liked that...

Avatar

@Nico, @Willem - rails 3 still contains RJS via http://github.com/rails/prototype_legacy_helper and only available for prototype, however nothing prevents you from creating a js.erb view containing the javascript you would like executed

@Romain - event.preventDefault only prevents the browsers default action, returning false stops the event from propogating (including other handlers)

@Martin - the data-* attributes function in all major browsers, however it will not validate as custom attributes are not part of the HTML spec until HTML5

Avatar

What happens if the user is not using a HTML 5 capable browser? I imagine it will be quite a few years until you can assume that all your users have HTML 5.

Great screencast though!

Martin

Avatar

Thanks for another great screencast...

I still use Rails 2.3 in Windows OS, and actually not much satisfied...
Does it still functional in older Rails version?

Avatar

How do you do it? You always seem to come up with Railscasts that hit exactly what I'm looking for... anyways, thanks for another great tutorial!

Avatar

I've made a simple init generator which will download the latest rails.js (jquery) and doing some other stuff: http://github.com/mendelbenjamin/rhj_init

Thanks again Ryan

Avatar

Thanks, this screencast is much appreciated. I am also wondering about RJS and Rails 3? I have used RJS with much joy in that past and I am hoping that it would still be supported in Rails 3.

Avatar

Hello Ryan, like usually, thanks for your work. :)

In the javascript code, why do you use "return false;" instead of "event.preventDefault();" ?

And i have a suggestion for a unobstrusive links with actions methods : the idea is to use the noscript tag to provide a button_to if scripts are disabled and link_to in normal cases.

Of course, the other way is to use only buttons for actions, with nice styles. :)

Sephi-Chan

Avatar

Nice screencast, thanks. I wonder if the rjs stuff is still in rails 3? I'm using it a lot, it simplifies working with javascript quite a bit. For example by making helpers that output js via the update_page function. Is that still supported in rails 3?

Avatar

how can I use nested_attributes with this approch? e.g. http://stackoverflow.com/questions/2445097/accepts-nested-attributes-with-model-update-for-multiple-models

Avatar

For those of you wondering about aligning the table, it's a feature that comes with the textmate bundle. The most recent version does not support CMD+OPT+\ - instead hit CMD+S to save and align your tables.

Avatar

For those of you wondering about aligning the table, it's a feature that comes with the textmate bundle. The most recent version does not support CMD+OPT+\ - instead hit CMD+S to save and align your tables.

Avatar

I dont understand how it gets to the create action

for example I changed my root as follows

map.root :controller => "users", :action => "new"

so it goes straight to the page where a new user can be entered. once the user hits submit, it goes back to the controller, but how does the controller know that it should go to the create action next?

The reason I ask is because instead of going to create action directly, I want it to go to another form with more parameters (city, country etc)

Avatar

Be careful. Auto-conversion to UTC does not happen in time fields in the database, only datetime, and timestamp.

Avatar

Thanks a lot!
We started using this method a while back when the XSS-Plugin for the current rails became avaliable so we wont have to switch to much code.

I have a view more notes:

1. HAML:
I have to use = "some #{code}" from time to time in my template. Since all "" are considert unsave, the easy way to make them safe in HAML is to write != "some #{code}". Unfortunatelly the code-highlighting doesnt support this but it works fine.

2. Helper:
I use the safe_helper-Helpermethod in my helpers to mark them safe globally.
More: http://github.com/nzkoz/rails_xss

3. HTML-Tag-Helper: I am not shure about that but I had problems using html-tag-helper since they mark your html safe without much thinking. Thats not so nice since the whole new escaping makes you feel save and I forgot to look at the html-helper-tags for a while...
(See comment http://rvdh.de/blog/2009/12/14/rails-3-xss-protection-in-erb/#comment-27963694 in german)

4. Btw, where is the difference between .html_safe and .html_safe!
?

Avatar

Nice one ryan,

It's great that you would help out everyone like this.

Avatar

Hi Ryan,

great screencast, as usual!

I have a question: how would I lazy-load #all?

In the controller you did:
@articles = Article.order(...)

What if I wanted to lazy-load all articles? I mean something like:

@articles = Article # would need to implement Enumerable

or some other way to turn Article into an empty Relation.

Technically, I could just create a dummy Relation object as in:

@articles = Article.where('1 = 1')

but that doesn't seem to Railish...

Avatar

Very efficient presenrtation; gawds you are getting extremely good at this! I especially like how you gently identify mainline command differences w/ Rails 2. Your appeal for give-back is well done.

Avatar

Got it!

  desc "Raise an error unless the RAILS_ENV is development"
  task :development_environment_only do
    raise "Hey, development only you monkey!" unless RAILS_ENV == 'development'
  end

task :test_data => [:environment, :development_environment_only] do
    #file = Dir["db/migrate/#{ENV["VERSION"]}_*.rb"].first
    file = Dir["db/migrate/*load_test_data.rb"].first
    require(file)
    migration_class = file.scan(/([0-9]+)_([_a-z0-9]*).rb/)[0][1].camelize.constantize
    migration_class.migrate(:down) unless ENV["DIRECTION"] == 'up'
    migration_class.migrate(:up) unless ENV["DIRECTION"] == 'down'
  end

References:
1. Justin French for dev env only
http://justinfrench.com/notebook/a-custom-rake-task-to-reset-and-seed-your-database

2. bmihelac Blog http://source.mihelac.org/2007/02/21/running-database-migration-individually/

Avatar

How we we migrate only one migration file using rake. Meaning i have a migration file named 20100628999998_load_moduls_data.rb
It has various factories which create data. I want to run only that migration/ruby file everytime, how do it do that ?

Avatar

Hi Ryan,

I have a query for you with regards to this episode. I am referencing my pages with a "slug" column. and want to be able to do pages/slug/comments

I have tried saying for it to use the slug as a variable to pass everything through but it seems not to want to work. any thoughts?

Avatar

FYI: http://errtheblog.com/post/43 link is dead.

Avatar

Thanks so much for your good job, Ryan. I really enjoy your railscasts, and I'm learning them one by one from the beginning these two days. I hope to learn all of them soon.

A suggestion just FYI: it'll be great (especially for newbies) to put Rails versions there for some railscasts which might use deprecated APIs or ways (if any).

Avatar

I installed RedCloth 4.2.3 but when i put <%= textilize h(@interview.body) %> I get this error:

NameError in Interviews#show

uninitialized constant ActionView::Helpers::TextHelper::RedCloth

Does anyone have solution? When I put gem list it shows me that RedCloth is installed.

environment.rb file includes this line:
config.gem "RedCloth", :version => "4.2.3"

Avatar

Hi Ryan,
First,thanks for all your great videos.

I have get an error on the video tutorial, I have the ActiveRecord::ReadOnlyRecord error when I try to edit a project, and I can't figure out how to correct it :/

Best,
Greg

Avatar

Hey Ryan, thanks for the great screencast. Where can one find the source for #94 and #95.

Thanks a bunch,

-Vance

Avatar

Many ppl do something to help other developers or newcomers, but three years of constant "duty" are outstanding, to say the least.

Avatar

its so far so be good!

Avatar

Congratulations on three years of excellent screencasts. It's hard to believe that you haven't missed a single week! I can't describe how much help you've been to my career. You've really helped to iron out the wrinkles in Rails. Thank You!, Thank You!, Thank You!, Ryan.

Avatar

I just want to say "thank you". I'm new to rails and I like it. Your screencasts are great. I don't understand each of them fully, but from day to day I understand more.