RailsCasts Pro episodes are now free!

Learn more or hide this

Recent Comments

Avatar

Same problem as Rob, it's not logging any errors.

Avatar

Ryan, as always great videos. Loved the 2.1 updates. I've recently been using config.gem and I think I found a problem using it with BlueCloth: http://railsforum.com/viewtopic.php?id=18850

Any idea whats going on here?

Avatar

@Bharat: you could just keep a window with ``tail -f log/development.log'' open, that should show the queries. I prefer to have them in the same window though, and have explained how to achieve this here:
http://skionrails.wordpress.com/2008/05/22/loading-additional-files-when-starting-scriptconsole/

Hope that helps. Great work as always Ryan :)

Avatar

Hey Ryan, great screencasts. I've learnt 99% of my Rails from them :)

I have a question though...looking at my logs, it looks like the SQL generated uses 'like' everytime since the :conditions is used. Doesn't this take a very small performance hit?

What would be the best way to exclude the 'like' search except when a search term is passed? Use a condition to check if the 'search' parameter exists and then append it to the paginate code?

Thanks.
Keep up the great work.

Avatar

An imagine uploading tutorial would be great. In fact, it would be really nice if Ryan could suggest something that would combine attachment_fu's S3 capabilities and fleximage plugin's on-the-fly imaging capabilities.

Looking forward to each and every episode as always :)

Avatar

As always: nice screencast Ryan :)

A suggestion for future screencast(s): Tests. I think this is a very interesting topic, because i think there are a lot of programmers out there not testing at all... There are also a lot of testing frameworks, and it all can be a bit confusing at first...

Just a suggestion ;)

Ben

Avatar

Any idea how this could be combined with will_paginate?

Avatar

@Bjarki - I agree about an image uploading tutorial. Very necessary and I think one of the last things to make this site complete. :-)

Avatar

Ryan, i am getting an weird error when i combine the use of "fields_for" and "collection_select" at the partial code.

There's someone having the same issue, any tip?

http://railsforum.com/viewtopic.php?id=18598

Avatar

Why not:

def render_starts(rating)
  content_tag :div, (0...5).map do |position|
    image_tag begin
      if rating >= position + 1
        "/images/full_star.gif"
      elsif rating <= position
        "/images/empty_star.gif"
      else
        "/images/half_star.gif"
      end
    end
  end.join, :class => 'stars'
end

It has only 11 lines and seems to be simpler then separate object.
Rearange of if's (full, half, empty) can increase the simplicyty.

Avatar

@James, interesting idea. I hadn't thought of using inject here.

The problem with just starting with Product instead of Product.scoped is that if no further scopes are applied to it then it will simply return Product, not a scope. This means you can't iterate through the result or treat it like an array as you can with a scope.

@Jim, what kind of object is being passed to the block here? It can't be a normal named scope because calling further named scopes upon it returns a new named scope, it doesn't change the existing scope.

This means we would have to set up a new object which gathers up the called methods and then reapplies them to the scope. That solution seems a bit too complicated.

Avatar

Whenever I see code like this I think blocks to clean it up.

I'd look at doing something along the lines of:

Product.scoped({}) do |scope|
  scope.conditions "products.name LIKE ?", "%#{keywords}%" unless keywords.blank?
  scope.conditions "products.price >= ?", minimum_price unless minimum_price.blank?
end

def scoped(conditions, &block)
   ....
end

I'll leave it up to everyone else to do the hard work. :)

Avatar

I've been thinking about your cleaning up the `scope = scope.scoped …` code, so I'll throw out some ideas.

We can definitely use inject() to remove all of the assignments. I also like the idea of staring with the model class itself, instead of an empty scope. Using just that much, we can build something like:

    ….inject(Product) do |scope, …|
      scope.scoped …
    end

The tricky part here is knowing what to iterate over. Obviously, the find() parameters are needed, but you also only conditionally apply them. That made me want to try something like:

    [ minimum_price.blank?, {:conditions => ["products.price >= ?", minimum_price],
      … ].inject(Product) do |scope, (cond, params)|
      scope.scoped params unless cond
    end

Of course, that's just way too ugly. I haven't come up with the best way to improve that yet though.

Avatar

Ryan, your screencasts get better as your skill increases. It's a lovely thing to watch.

Avatar

Hie

I am using WAMP
I have rails 2.0 installed
I installed gems debugger
but the require 'ruby-debug'
is giving problems
The moment I start my server I get these on the command prompt

=> Booting WEBrick...
c:/ruby/lib/ruby/gems/1.8/gems/rails-2.0.2/lib/commands/servers/webrick.rb:13: w
arning: already initialized constant OPTIONS
=> Booting WEBrick...
c:/ruby/lib/ruby/gems/1.8/gems/rails-2.0.2/lib/commands/servers/webrick.rb:13: w
arning: already initialized constant OPTIONS
c:/ruby/lib/ruby/site_ruby/1.8/rubygems/custom_require.rb:27:in `gem_original_re
quire': no such file to load -- c:/ruby/lib/ruby/gems/1.8/gems/linecache-0.42-ms
win32/lib/../ext/trace_nums (MissingSourceFile)
        from c:/ruby/lib/ruby/site_ruby/1.8/rubygems/custom_require.rb:27:in `re
quire'
        from c:/ruby/lib/ruby/gems/1.8/gems/activesupport-2.0.2/lib/active_suppo
rt/dependencies.rb:496:in `require'
        from c:/ruby/lib/ruby/gems/1.8/gems/activesupport-2.0.2/lib/active_suppo
rt/dependencies.rb:342:in `new_constants_in'
        from c:/ruby/lib/ruby/gems/1.8/gems/activesupport-2.0.2/lib/active_suppo
rt/dependencies.rb:496:in `require'
        from c:/ruby/lib/ruby/gems/1.8/gems/linecache-0.42-mswin32/lib/traceline
s.rb:8
        from c:/ruby/lib/ruby/site_ruby/1.8/rubygems/custom_require.rb:32:in `ge
m_original_require'
        from c:/ruby/lib/ruby/site_ruby/1.8/rubygems/custom_require.rb:32:in `re
quire'
        from c:/ruby/lib/ruby/gems/1.8/gems/activesupport-2.0.2/lib/active_suppo
rt/dependencies.rb:496:in `require'
         ... 39 levels...
        from c:/ruby/lib/ruby/gems/1.8/gems/rails-2.0.2/lib/commands/server.rb:3
9
        from c:/ruby/lib/ruby/site_ruby/1.8/rubygems/custom_require.rb:32:in `ge
m_original_require'
        from c:/ruby/lib/ruby/site_ruby/1.8/rubygems/custom_require.rb:32:in `re
quire'
        from script/server:3

Please help.

regards
Yukti

Avatar

Nice new features. I upgraded to Rails 2.1.0 earlier. Really easy. Looking forward to using named scopes. Just need to find a nice bit to use it for.

Would you consider giving feedback on some code I've written if you have 5 mins? I'm new to Rails (3-4 weeks) and I've gotten to the point where I have some untidy spots I can't optimize with my current knowledge. Email sent with this comment. Understand if you're too busy.

Keep up the great work.

Avatar

This is a valuable resource!
Love it. thanks

Avatar

Apologies for the incorrect code. It should be fixed now.

@Devin, planning to make a new intro soon. Sorry about that. ;)

@Tomek, since the search id is in the URL, it's still possible to share the searches with anyone.

Avatar

If you change the condition_parts method to read:

private_methods(false).grep(...

It will work just fine.

Avatar

nice screen cast alwasy. :)

Avatar

I've found one pitfall with your approach though: if you want to exchange searches between users ? If somebody does a search in Google they can easily pass that url to me and I can enjoy the same results. That's why I think that having complete query strings in the url is not that bad idea.

Avatar

Hey Ryan,

As always, your webcasts are exceptional. They've helped me out tremendously in all the Rails applications I've been working on.

Quick question... have you ever done any role-based access control? If so, maybe this could be a topic for one of your future webcasts?!

--
Thanks!

Avatar

I used rfpdf since pdf-writer did not go together with activescaffold (+activescaffoldlocalize +calendar_date_select). Be sure to pick the right plugin (http://code.google.com/p/rfpdf/source/checkout), since there are two.

Avatar

I've found the acts_as_ferret plugin very good for plaintext searching.

Avatar

Helo Ryan, can you tell me what is what you do to show the SQL statements executed by Rails at the bottom of the screen?

Thanks.

Avatar

@Andrew : thanks RailsWhere looks interesting

Avatar

Ryan, I love your screecasts. You do a wonderful job, but I have one gripe. The intro makes me want to commit suicide. The clickety click of a keyboard, the big BLAHMMMMM noise, etc. Consider changing it? Please?

Love,
d

Avatar

Example rewrite of the Search class using RailsWhere.

class Search < ActiveRecord::Base

  def products
    @products ||= find_products
  end

  def find_products
    Product.find(:all, :conditions => to_conditions)
  end

  private

  def to_conditions
    w = Where.new
    w.and "products.name LIKE ?", "%#{keywords}%" unless keywords.blank?
    w.and "products.price >= ?", minimum_price unless minimum_price.blank?
    w.and "products.price <= ?", maximum_price unless maximum_price.blank?
    w.and "products.category_id = ?", category_id unless category_id.blank?
    w.to_s
  end

end

Avatar

Another great plugin to make writing complex conditions easy:

RailsWhere (http://code.google.com/p/railswhere/)

I think that using this plugin makes the code a lot more readable that writing seperate functions for each condition and then using metaprogramming fu to join them all together.

Avatar

I think the _conditions methods need to be public because the the 'methods' method doesn't return private methods. Which means you can't run grep on them.

Avatar

Thanks for this screencast!
It's going to be so usefull! I'm going to use it with sphinx search engine!

Avatar

@Lauren & mike,
euhm after I posted this, continued to watch the railscast. And Ryan included it in the application.rhtml and even says again that you should not forget to include it !

So instead of flaming, you should have watched the cast more carefully I guess :)

Avatar

Thanx, great tutorial, loved it :)
Anyway ruby got me loving programming again and to all people complaining it does not work, had same thing.

And solution is simple, you are using the Insert method from the rjs library but forgot to include the javascript lib files.

To make the long story short you get rid of the Reference errors by adding this line to your view html template (mine is project.rhtml):

<%= javascript_include_tag :defaults %>

here is my full project.rhtml:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
       "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head>
  <meta http-equiv="content-type" content="text/html;charset=UTF-8" />
  <title>Project: <%= controller.action_name %></title>
  <%= stylesheet_link_tag 'scaffold' %>
  <%= javascript_include_tag :defaults %>
</head>
<body>

<p style="color: green"><%= flash[:notice] %></p>

<%= yield %>

</body>
</html>

Avatar

It's still me
I have noticed that in the code you post here as a resource you have made all the methods (unless find_products") private. However, in the railscast all are public. With private methods it looks like the search doesn't work. Am I missing something on my app or they must be public?

Thanks again

Avatar

@Ryan
Why on keyword_conditions do you use the variable keywords twice? Is once not enough?

Thanks

Avatar

@Bizzy, yep! planning to add searching to Railscasts, just haven't gotten to it yet. :)

Avatar

As of this moment GiT users face the same problem that every earlier adopter does, a lack of compatibility and support in most ancillary tools. This, however will change over time and the decision of when to move to GiT may well be heavily influenced by what tool is considered most important.

In our case we recently moved from Trac to Redmine because we decided that the VCS was a more vital technology to our future efforts than the Project Administration System. As Trac support for GiT is very minimal and has not, to my recent knowledge, been slated for core implementation we decided to move PAS as well as VCS. Others will decide to stay on Subversion until their desired tools provide better support for GiT.

I have found GiT's UI, for the most part, simple and straight forward to use. I have zero experience with the the GUI's available but the command line instructions could ahrdly be simpler.

The whole structure of GiT is a marvel to consider. The insight of the designer is, for me, dumbfounding. One must consider that this entire project is really nothing more than an innovative combination of tools that have been present on most Linux distributions for years.

GiT's innovations have tremendous possibilities for OS fs security and data compaction in future Linux distributions. I believe that GiT is going to radically change computing. Consider the value of knowing simply by looking at the SHA1 value of the system whether or not any file in /etc or /var/share or /usr/local has been changed or needs to be updated!

The SVN folks themselves have conceded that the OOS community mind-share has committed to DVCS and that SVN will likely be the end of the line for centralized repository systems in OSS. Whether this means that GiT will be "THE" OSS DVCS is another issue.

Avatar

Dave,

You might need to associate the email you want to display with the email account you're using to authenticate.

Gmail is probably not allowing you to change your "from" because it doesn't recognize the specified email as yours.

Avatar

Excellent as always. I'm using timezones though, and for the longest time I thought there was something with my code. Remember to convert you hide_time to UTC when doing the find!

<code>
all(:conditions => ["updated_at >= ?", hide_time.getutc])
</code>

Avatar

the codes didn't work for me well (updated version or no) and i guess i can blame the complexity or disorderliness of my project code. with the help of a friend, i was able to find a way around my predicament with these complex forms. i use collection_select instead of text_fields too. anyway, while my friend was a genius being able to figure out how to do the updating (edit or adding a new record) of multiple forms on the spot, he wasn't able to figure out how to delete records (plus he had somewhere to go to).

but wow, i still can't believe how i managed to figure out a very simple way to do it. it's a bit of simple common sense, actually.

i used the javascripty "remove" in conjunction with the server side's "destroy".

<% if task.new_record? %>
<%= link_to_function "Remove field", "$(this).up('.task').remove()" %>
<% else %>
<%= link_to 'Cancel task', task, :confirm => 'Are you sure?', :method => :delete %>
<% end %>

hope that will help anyone...

Avatar

Thanks Ryan, Today I started working on a search engine for my application and this railscast is exactly what I need.

PS Does someone have a paginated version of the form to let me see? ;)

Avatar

good tutorial, i had exactly that problem, with that instance variables it can improve the performance

Avatar

I find it ironic how easily you can implement a search as complex as this, but there is no search implemented on this site!

D'oh!!

Avatar

He Ryan,

Great article..i am going to used it for sure in my new rails project.

You talked about storing the search results of the user in the database. I looked arround the net, but with no result. Do you have some links where i can find information about this kind functionality?

Grtz..remco

Avatar

I've also thought about the off-database model.
In current solution:
- You can easly run out of the free id (it is not so uncommon as it may appear to be, hard to solve and detect) - the deleted ids are not reused
- Also easy DOS attac (run out of ids).

Run out of id can be solved but it requires in fact stop of service.

Avatar

I recently implemented time zone support using Rails 2.0.2 and TzInfo and I think it uses different time zone names or am I incorrect? If so, is there then a way of converting my existing user accounts to use the other, default time zone names?

Avatar

Hi all.

I fixed the code to work with SQLite and Rails 2.1, plus added a few improvements like extracting the announcements div into a partial, implementing named_scope, and a feature for a plural hide message if more than one announcement is active.

See it here:

http://railsforum.com/viewtopic.php?pid=63353

Avatar

I have tried everything in the tutorial and the comments including May 22 08 comment by "pi_p master" for respond_to do format etc. and here is my predicament; my application works on my development machine just fine; when I transport it to my production environment it does not call the javascripts controller; I have the following error : <script type="text/javascript" src="/javascripts/dynamic_units.js">
1<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML 2.0//EN">
2<html><head>
3<title>404 Not Found</title>
4</head><body>
5<h1>Not Found</h1>
6<p>The requested URL /javascripts/dynamic_units.js was not found on this server.</p>
7</body></html>

Now I have even tried putting in explicitly map.connect ':controller/:action.:format'

as well as :

  map.js '/javascripts/dynamic_units.js' , :controller=>'javascripts', :action =>'dynamic_units'

and whatever permutation I could fathom but to no avail. Help please.