RailsCasts Pro episodes are now free!

Learn more or hide this

Recent Comments

Avatar

Great episode as always!

If I'm not mistaken, you've used this kind of a named route ('resources') behind the scenes in episode 21 as well....(REST).

Gr,

- J.

Avatar

Is there any reason Rails shouldn't just escape the "params" and "cookies" hashes, no matter where you put them in your code?

That would mean "escaping" the conditions hash as a whole, which might be harder than escaping each value one by one.

Seems like a good idea to me, just because stuff is easier to understand when written the insecure way - to me at least.

Avatar

Awesome tip! I didn't know this already existed, so I implemented it all by myself ;)
Thanks for this video and your great blog.
Keep it up it's great stuff!

Avatar

Okay, nothing else worked for me except this explanation. Even the Rails wiki was confusing. Thanks!!

Avatar

Excellent point Nicolás! Doing "send" is better because of the point that you mentioned. Thanks for bringing that up.

Avatar

Great screencast! :)
Making plugins is actually easier than I thought :D (which doesn't surprise me all that much, considering the whole philosophy of rails).

One question though, why use write_attribute(name) and read_attribute(name) instead of send(name.to_sym) and send("#{name}=".to_sym)? That way if the user is further rewriting due_at and due_at= for some preprocessing they wouldn't loose there changes :)

(Maybe I'm missing on something about why it's not useful to do so, though)

Again, congrats on the great screencast :)

Avatar

Right, module_eval would require a string evaluation for this case, so if you're uncomfortable with that, define_method is indeed the way to go.

For comparison, here's a module_eval version:

      module_eval <<-EOV
        def #{name}_string
          #{name}.to_s(:db)
        end
      EOV

The Rails source code uses module_eval/class_eval to define macros like acts_as_list, for whatever that's worth...

Avatar

@Ryan, your screencasts are as great as ruby/rails language and framework! Keep Your good work :). Greetings from Poland.

Avatar

@Geoff, good point. I don't like putting code into a string and I didn't realize you could pass a block to class_eval and module_eval. You're right, that would be cleaner. Thanks for the suggestion. :)

Update: actually I need to define the name of the method, so I don't think it's possible to do this with module_eval without passing a string. I avoid that whenever possible so I guess define_method is the right way to go for me.

@Ross, thanks for the encouraging comments. Creating a validates_* method is a great idea. I'll try it out and consider creating an episode on it.

Avatar

This was by far the best episode so far. This is a topic I was going to delve into very soon but you gave me a huge head start. One thing that might be neat to cover would be taking this a step further and adding a validates_X method to ActiveRecord::Base as well to validate the date string (validates_date_string or something like that). I would think of this as a more elegant solution than simply using the validate hook (though I guess this is a fairly straightforward process given the information already presented so maybe this isn't really necessary).

Avatar

Great stuff!

You could use module_eval/class_eval instead of define_method, right? Might make the code a little more readable (i.e., no calls to instance_variable_set, write_attribute, etc.)

Avatar

Thanks for another great one Ryan, I'm really impressed how quickly and regularly you release these at such high quality. I always get excited when I see the little (1) next to railscasts in my RSS reader.

Avatar

Ryan,

Brilliant as usual. Thank you for putting this great resource out there. Your commitment to the RoR community and learning/teaching in general is to be highly commended.

Off topic, how are creating 'railscasts' while at RailsConf? Your ability to crank out high quality content at such a rapid pace never ceases to amaze me.

Keep up the great work.

Avatar

@Trueke, you can probably do this by overriding method_missing on NilClass, but I don't recommend it. This may break some things and changes the behavior of Ruby that other programs rely on. Instead, just do a nil check anytime you need to call a method on an object that could be nil.

@infrid, glad you enjoy the screencasts and thanks for the encouraging comments! I enjoy doing them. :)

Avatar

found these today and am so overwhelmed that I put down tools and gave myself an afternoon of training matrix style.

WOW - almost every single one has been a gem (no pun intended).

great length, great topics, really elegant solutions. I'd happily pay to view longer screencasts, if you do them!

Thanks so much. Really really appreciate your work.

Avatar

Hi!

Watching that webcast I got a question;

It's possible to extend nil object to make nil.anything returns nil?

I mean,

a = nil
b = a.anything
result: nil, not an error.

Did I explain myself?

Avatar

Great screencast - I always wanted to know about plugins but couldn't find much information on them. This helped.

Avatar

BrianC, I think you can have plugins auto-reload by adding this line to your plugin's init.rb file:

Dependencies.load_once_paths.delete(lib_path)

See the post by technoweenie for details:

http://weblog.techno-weenie.net/2007/1/26/understanding-the-rails-plugin-initialization-process

Avatar

Great episode.

Is there any way around having to restart the server to get it to reload the plugin? Any special "i'm writing a plugin now, please reload it's files" mode you can run in?

We're all spoiled by the magic reloading that rails does for us :)

Avatar

Module#define_method and Object#instance_variable_set are advanced for me, your screencast show a good example how to use them,now I think I underground them,thanks !~

Avatar

I like this episode and hope you make screencast about plugin because it hard for me.

Avatar

Great screencast , I love this site!!!
Question:
Why not just verify that the metod is post like this?

verify :method => :post, :only =>[ :destroy, :create, :update ], :redirect_to => { :action => :list }

This seems more simple and this way you can not create new users using curl (or the browser address field)
Or I'm I just not getting it?? :)
Cheers

Avatar

This is the best website on the entire planet.

Question:
Why is it that the percentage signs can not be arround the qustionmark in this statement but need to be in the second argument with the params[:query]?

Task.find(:all, :conditions=>["name LIKE ?", '%' + params[:query] + '%' ])

Thanks

Avatar

Just heard (at RailsConf up here) that the "require" statement isn't necessary in the init.rb file, so you can probably remove it.

Avatar

Very good question. AFAIK the limit clause in SQL is very limiting, and I don't think it's possible to do this with an SQL LIMIT (find :limit parameter). See if fetching all of the projects gives you decent performance. If not you could try not fetching the projects and doing a separate SQL query for each category, fetching the limited projects. This is a good way to go if you don't have many category models.

If you want to do this all in one query, I'm sorry I don't know how. I'm sure it's possible with a custom SQL query, but I'm not proficient enough with SQL to know.

Avatar

Just wanted to say that your Railscasts have been helping me tremendously while trying to learn rails. I've worked my way out of several tough spots to grasp using them, thanks!

I had one question about this episode though. I am working on a gallery type page for my portfolio, and I am using eager loading to call up categories, projects, and images all at once. I am wondering if there is a way to limit just one of the models returned? For example I only want to retrieve 5 projects per page. Where would I put the limit condition? This is what I have in my category model right now:

def self.portfolio
  find_all_by_parent_id(2, :include => { :projects => :images }, :conditions => 'images.default = true' )
end

Thanks!

Avatar

@Zubin, cool, didn't know about %e.

Regarding your question, you could extend the String class to add your own method which does this. Place this in a file in your lib directory and require it in environment.rb

--
class String
  def to_webname
    #...
  end
end
--

sorry there's no indentations

Avatar

Thanks Ryan, another great screencast!

If anyone's wondering, %e = Day of the month with no leading zeros (0-31). This is missing in "ri strftime" for both Time and Date ("ri Date.strftime" returned no info for me).

Does anyone know how to add a more generic string formatting function to the environment file (or elsewhere), which is available to models, controllers and views? (eg str_to_webname?)

Avatar

Virtual attributes are also covered on episode 16:

http://railscasts.com/episodes/16

It just so happens that Rails uses getter and setter methods for setting and retreiving attributes (columns) so you can create your own attributes by making your own getter and setter methods.

Avatar

YAGR (Yet another great Railscast) Ryan. Thanks a lot. It's improved my coding quite a bit.

Is there another episode where you cover getter and setter methods? I'm a little confused on why you would use them in the first place and how rails knows how to access them. I've got most of the Rails books so if anyone knows references from those, that could help too.

Avatar

@Simon, good comments!

Overriding "validate" still allows all other validations to get through, think of it as just a place to define your own custom validations. The main thing you need to watch out for is if you are subclassing another model (STI) and overriding it there.

True about using the text field without the virtual attribute pretty much works. I realized this after I recorded the episode, otherwise I would have mentioned it. But the technique is still useful if you want to customize the behavior (add Chronic for example).

Also, I should have added a "nil?" check on the getter method so it doesn't cause any errors while creating a new task.

Another thing I should probably have done is to store the entered string in an instance variable so, if there is a validation error, the time doesn't revert back to the original one.

Avatar

Thanks for these RailsCasts, they're very well done. Just a couple of points/questions on this one:

- should you be redefining the "validate" method, or just calling it? It was my understanding that if you redefine it, that basically cuts out all other validation.

- you can actually get the same effect just by using a text field (without doing the virtual attributes) if you just want the basic parsing behaviour.

Avatar

Thanks again. I love these screencasts because they're short (so I don't fall asleep) and tackle 'real-life' problems.

Avatar

This one is one of the best Railscasts.

Congratulations!

Avatar

Hmm, it should work fine with a RESTful design because you're just editing a model's attributes like normal. Unless you have a has_many :through association instead of has_and_belongs_to_many, in that case you would have to create your own "*_ids" method.

Can you be more specific on what isn't working?

Avatar

Hi Ryan ! Thanks for the great site. I loved this tutorial and found it helpful but couldn't make it work when I generate the scaffold using "scaffold resource" as for making it work RESTfuly (as accepting requests in various formats)

Avatar

Very nice show.

Thanks !

Avatar

Hmm, I'm not sure if it's valid XHTML or not. If not, you could do a nil check inside the td element like this:

<% for task in tasks_row %>
  <td>
    <% unless task.nil? %>
      ...
    <% end %>
  </td>
<% end %>

Thanks for bringing that up, good question.

Avatar

i've got the same question Wincent. I'm wondering if there isn't a way to conditionally act upon the nil objects.
I'm really interested in learning more about this technique.
Here's what I want to do:

http://www.scubadorag.com/coco/links/USAlinks.asp

We will be moving to a rails host. I've thought about doing it with modulo, but I haven't been able to wrap my head around it yet.

Avatar

@Rebort, hmm, how did you install Ruby? Did you compile it from the source? If so, you needed to do "make install-doc" command after "make install".

@eskim, yep, you can move this into a file in the "lib" directory. Then just "require" the file in your environment.rb.

Avatar

Hi, thanks for the hint with Time::DATE_FORMATS, I've been looking for quite a while for something like this :)

You can push this even further be adding a alias_method for to_s in Time class like this:
class Time
  alias_method :[], :to_s
end

Now you can do something like Time.now[:custom_format] etc.

There is no []-instance method for the time-class, so this does not destroy some other behaviour in your existing app.

Greetings, Christoph

Avatar

Is there any way to put the format string things in the file other than environment.rb?

Thanks for the great screencasts.
I'm big fan :)

Avatar

Great tips.

Uhm .. how did you get that command line "ri" documentation to work? The command exists on my system but it looks like the actual docs are missing, eg:

$ ri Time.strftime
Nothing known about Time.strftime

Avatar

Thank you! This really what i'm looking for!

I appreciate your greak work! Thanks again!

Avatar

It's the 13th! Do you know what that means?!?! Time for a new screencast! Whereisit whereisit whereisit....

Great screencast as always Ryan, I actually find myself enjoying yours more then peepcode, so be sure that I'm going to convert the money I would have spent on their screencasts into donation money for yourself, great work!

Avatar

I used to use breakpointer a lot, but the recent Ruby releases broke it, so I'm currently getting by with just echoing variables to the log/view. I really need to learn ruby-debug, and once I do you can expect there to be an episode on it. Thanks for the suggestion.

Avatar

Hi Ryan,
I would have a suggestion for a screencast.
How do you debug? With ruby-debug or breakpointer?
What is the better choice? There are topics, that breakpointer is deprecated, isn't it?
May this would be a topic for a Railscast

greetinx

Avatar

@james, good question about pagination. It's not too tricky, you just have to make sure you order them properly so the grouped items are close together. For example, in this case I would need to group them by due_at so the month names stick together. Then you would treat it like normal. The only problem is a page my split up a group, but I can't think of an easy way to resolve this problem.

If you need to group items already, pagination may not be the best solution. Instead consider creating some sort of index of groups where clicking one will take you to the items in that group. In this case I would make a list of months, and clicking one would reveal the tasks for that month. This way the person doesn't have to deal with guessing which page has a certain month on it.

Avatar

I'm displaying the key commands with a little utility called KeyCastr.

http://stephendeken.net/software/keycastr/

Avatar

filter_parameter_logging "password"
good tip