RailsCasts Pro episodes are now free!

Learn more or hide this

Recent Comments

Avatar

new Railscast suggestion,

how about something on Model Observer classes?

I recently discovered these in restful_auth and find them very nice for extracting all the filters and grouping them in a small file.

Although I'm not finding much discussion/documentation on their usage.

Avatar

thanks, how would I trick collection_select into working this way (If I can figure this out, the rest will work:

<%= collection_select "project[task_attributes][]", :resource_id, entities, :id, :nickname } %>

when I try this, I get "ActionView::TemplateError (`@project[task_attributes]' is not allowed as an instance variable name)"

I tried similar thing on check_box_tag and it works correctly (I think)

Avatar

@Joel, I'm not familiar with the plugin so I don't know. Basically you just need to be concerned about the resulting HTML. Make sure it has that same "project[task_attributes][]" prefix in the name of the fields and it should work. If you can't prefix the name of the fields then you'll have to either hack it or look for a different solution.

Avatar

Hi Ryan, great video, one question, I use a date widget called "datetime toolbocks", they dont provide a method on the formbuilder, so I have to use the normal helpers, for example I use: "toolbocks_date_select object method" syntax on it. Given this, is there a way to use fields_for to make this work?

Avatar

@DAZ, the difference is that .create will save the model to the database right there, but .build will only build the model in memory and not try to save it.

So, you could say ".build" is like ".new".

Avatar

Could somebody explain the .build method? It looks similar to .create ... are there any differences and/or reasons for using it? thanks.

Avatar

Awesome!

I've been waiting a long time for you to post this one.

Very much looking forward to the next one and even hoping it will turn into a 3-part series ;)

Avatar

@HappyCoder, the presenter pattern is interesting, but I'm skeptical. Adding another layer of abstraction and delegation is a big cost, and I have yet to see a good example of it which justifies this cost. Instead I prefer the more direct approach like the virtual attributes you see here.

However, I do think there are many patterns around this concept of presenter pattern which are useful. But, I would only apply it through refactoring to make sure it's exactly what your app needs. Otherwise, you risk adding unnecessary complexity.

I guess you could say every presenter pattern is different depending on the needs of the app.

Avatar

Ryan:

Thanks so much for this episode!!! I've been waiting for it for so long!!! Can't wait for the next one.

Alek

Avatar

Ryan, Thanks, I love this idea of creating and updating children in the parent model rather than the controller. So today I made fields_for person[mugshot] and person[address], even though Person only has_one of each of these. Then I made setter methods in the Person model: def address= (address_hash) and the same for mugshot. Works a treat and so much cleaner!!

Avatar

Ryan, you always make screencasts on topics that puzzle me exactly when I really need a solution :-)

My friend told me about another one interesting solution http://blog.jayfields.com/2007/03/rails-presenter-pattern.html

You should make a screencast about it.

Avatar

Thanks for the topic, my controllers can be more slim now.
Do you use not official way to share controllers and view among different applications? (e.g plugems, engines, gems,..)

Avatar

Ok for the rest so do you advise to not use anymore the postback actions style of coding?

For Rayan:
We would love some episodes on complete deployment with capistrano 2.0 and maybe a subversion only one that explain the basics of subversion.
I am also waiting for the longer episodes on how to write basic apps

Avatar

After seeing this screencast last week I created a simple plugin to search your Rails projects for this exploit and I thought some of you may find it useful. I called it audit_mass_assignment:

http://code.google.com/p/audit-mass-assignment/

rake audit:mass_assignment

The audit goes through your models and checks for attr_accessible. If the model doesn’t use it, the model fails the audit. The plugin is obviously only for people that use the whitelist approach.

I could see a whole family of “audit” plugins that could check certain aspects of Rails projects for bad/insecure patterns. You could include (or omit) any kinds of audits that you want and run them before you deploy your app with “rake audit”. Obviously not every exploit or bad pattern can be audited this way but many can be.

Avatar

Hi Ryan,
thank you so much, great episode.
Again, I can't wait the next episode!
Unfortunatelly have to wait another week ;-)

greetinx

Rafael

Avatar

@Zargony, interesting. Perhaps a better solution would be to store the contents in an instance variable and handle the association creating in a callback instead of directly in the accessor method.

@Jermaine, yes, the technique I'll show in the upcoming episodes is better then what I wrote about. I'm planning to update these articles soon.

Avatar

Ryan,

I remember that you've written a nice tutorial about this on the railsforum website a year ago.

http://www.railsforum.com/viewtopic.php?id=717

Hopefully in the next part there will be some RJS goodness.

- Jermaine

Avatar

@Skyblaze:
This is the RESTful way of doing stuff.
A resource expects to have a 'new' action for entering a new object. This even extended to new.xml in edge rails.

Basically if you share controller actions for 2(or more) purposes, it can get ugly really fast. Splitting an action by using if/then/else (request.post? ) just to share a few basic lines isn't worth the cluttering. If you want to DRY up the code, use a before_filter for setting up the basic @instance variable.

Avatar

Thanks Ryan, this episode is a great summary on how to create multiple models in one action. However, a while ago I had trouble building associated models from a custom setter method that is called during initialization (like in your case). Under some circumstances, the associated models (tasks in your example) were vanishing. The full story: http://zargony.com/2007/09/17/vanishing-records-on-creating-multiple-models-in-one-action/

@Skyblaze: Using separate actions might look unnecessary, but in fact, it makes life easier if it comes to error handling, restful routes and/or ActiveResource.

Avatar

I wonder why you use two separate methods for new and create actions. Why don't you use postbacks?

Avatar

Ok...one more. Here's a sample of an RSpec method to mock the OpenID request. Some work is needed, but it covers the basics.

http://pastie.textmate.org/102377

Avatar

Very useful!

This screencast and code makes the OpenID part easy. It's the integration with an existing system, and writing specs that takes a bit more work.

The article by Ben Curtis was helpful. I also ended up stuffing a bunch of the code into the User model: authenticate_by_openid(identity_url, registration). This takes care of the logic in the model so it can be reused from a signup form as well as the login form.

Avatar

Thanks so much! I've been looking all over for a tutorial on custom rake tasks. This was a god-send.

Avatar

Ryan, Very nice work, been helping me a great deal with setting up a blog. but I run into a huge hurdle where the rjs is not rendering after the respond_to call. I've checked the rjs with a link_to_remote and its working fine. code done just like in your notes. Any reason that this would happen

Avatar

@Lucky, I believe I answered this on railsforum.com, but I'll answer it here for completeness. You need to remove the index.html file from the public directory so the home page will work.

Avatar

@Andy, I think you'll need to keep track of this manually instead of using the counter_cache option. You'll have to set up an observer or callback to update the counter cache every time you change a task. You may want to ask this on railsforum.com where I can go into more detail.

Avatar

@Roland, thanks. Fixed. :)

Avatar

You'll have to specify the rails environment when you call your rake task. Like this:

rake pick:winner RAILS_ENV=production

It defaults to development.

Avatar

@Michael

The following will make sure the plugin gets installed in a directory named markaby. I believe script/plugin in this case is just wrapping svn co since this is exactly how svn works as well.

script/plugin install http://code.whytheluckystiff.net/svn/markaby/trunk markaby

Notice the last parameter. Hope that helps.

Avatar

Im just starting my research on this but does anyone know of a way to change the DB configs that :environment calls? It works fine locally but when i try to run this on my stage server its trying to use root @ localhost which is is the development block of our database.yml account. I need to it to use one of the others. Ill post if I find the solution. Thanks in advance!

Avatar

Hi,

one quick note: the css should probably be
input#openid_url { ... } since it's an id not a class name.

thanks for your great screencasts!
Roland

Avatar

Is it possible to maintain counters of complete and incomplete tasks?

Basically I need counters for each state in my child model, and this approach works for counting # of children right?

Thanks

Avatar

I installed this plugin but encountered the following problems. Thanks in advance, to anyone who help enlighten me.

1. For my case, MVC for HOME (home/index) is not generated automatically. Do I have to create it myself? Anyway, I created Home controller and view.

2. When I entered the wrong password, I do see error message "Authentication failed".

But, when I entered the correct password, I was re-directed to "http://localhost:3000/", but it does not display the Welcome page (/home/index.rhtml). I did change routes.rb to enter the first line - "map.home '', :controller => 'home', :action => 'index'".

Avatar

I wanted user records in my app to have various statuses. Here's how I modified restful_authentication with acts_as_state_machine to accomplish this. I'll call it stateful_authentication

Avatar

I don't know about Capistrano but, I do have a solution for staging environments using Vlad on my blog.

Avatar

very cool~
Add This:
  ActiveSupport::CoreExtensions::Time::Conversions::DATE_FORMATS.update(:my_format => '%y-%m-%d %H:%M')

Avatar

Great cast!
It would be great to see how to setup capistrano to use staging environment may be the next screencasts :)

Avatar

I found an answer to something that has been confounding me about the self. thing. I am learning about OO programming, so I admit that this may seem obvious to a lot of people. Please excuse my ignorance.

Here is a link regarding how this works.
http://wiki.rubyonrails.org/rails/pages/RubyHeadScratching

Thank you Ryan for all the excellent work in your railscasts. I really appreciate the patience and clear mindedness that you demonstrate in your screencasts. You express yourself as a joyful and brilliant person.

Avatar

oops, sorry for the formating.repost here:
http://pastie.caboo.se/99835

btw: suggest add a "remember me" option for the comment for auto refill the form options.

Avatar

I don't think we need to install a new plugin, the XmlMarkup is a good enough as a markup builter :

 xml = Builder::XmlMarkup.new
 xml.div("id" => "error_message") do
    xml.h2 "#{pluralize(object.errors.count, 'error')} occurred"
    xml.p "There were problems with the following fields:"
    xml.ul do
        object.errors.each_full do |msg|
          xml.li msg
        end
      end
 end

though it is not so "sexy" as markaby,but it's good enough for this situation.

Avatar

I am curious about the self.find...

Why is it that this method requires "self." ?

Avatar

Nice screencasts, helped a lot! BTW, what software have you made it with?

Avatar

On top of restricting mass assignment with attr_accessible and attr_protected, why not do something like below, restricting access to fields on a method by method basis?

params[:user].delete_if { |key, value|
!([:company_name,:profile].include?(key))
}
user.update_attributes(params[:user])

This could be done as an application helper method that takes an array and a hash.

After typing the above though, I kind of realize filtering out attributes by method might be pointless, when really the goal is to filter by user or role. A user with access to a method might have no business running it on a particular row,. The need to check permissions for the requested row will often be there, but if your doing that, why not just create a function that checks for permissions by row and field, and filters the params hash to suit?

One could pass this params filter method an ActiveRecord object, login credentials, and the params hash - to get back a sanitized params hash without the attributes the user has no access to.

Another method might identify if a particular user has access to an array attributes for a given ActiveRecord object/row, returning true or false. AJAX apps could use this to dynamically add edit links for row/attributes where the user has permission.

Does something like this exist already? Perhaps it is just overkill, usually there are just admins and simple users, where simple users are restricted the same fields but different subsets of rows. But sometimes you do end up with with a third "power user" tier that requires less than complete access to all the fields and rows.

Getting back to the original subject of mass assignment, preceding mass assignment with this params filter would make it safe to use wherever, keeping things a litte simpler on the code end by pushing permissions related stuff into the database.

Avatar

It might be more efficient, I haven't done any benchmarking. It probably depends on where the session is stored. The default in edge rails is to store it in the users cookie which is limited on space - another reason not to store large objects there.

Either way, sessions are not designed to be caches. If you need a performance boost, look into a memcache solution (such as cache_fu).

Avatar

OK, don't store an object in session because it can get out of sync with DB but what if you make sure to keep it in sync? Wouldn't that be more efficient than hitting the DB so often?

If you hit the DB every time the user wants to look at anything that's going to slow things down.

OK, let's see. If the user updates the object then you're going to have to save it regardless. But if you're just flipping from one page to another, seems pretty important for performance to hang onto the object.

I'd say that's particularly true of a users User obj, which in many apps changes very infrequently and is read often. Every page in the app might need the logged in username, or could need their role if your app uses roles.

Avatar

@Frank, I've had issues with stubbing class methods. Sometimes the stub didn't get reset between tests which caused very difficult to find problems. So far I haven't had any problems with mocha and it feels much more solid to me.

Avatar

Why do you prefer mocha? What problems do you have with stubbing and mocking in Rspec itself.

Avatar

off topic : wish for screencast topic.
maybe you could show in one of the following screencasts:
helper_method :whatever
versus
helper :whatever include WhateverHelper
... this was quite confusing for me in the beginning and i still have always to think instead of doing the appropriate one automatically

Avatar

@Kristen: TextMate is a weird editor. You need to have at least one file open for the Subversion bundle to be active. Otherwise, the Subversion bundle will appear greyed out. That makes it confusing, because to checkout a repository to get a working copy, you need to open at least one new file. Hope that helps.

Avatar

@Joshua, looks like a good solution. I've done something similar in the past. It is relying on the fixture data, but as long as it's not relying on the relationship of other fixture records then I think it's perfectly acceptable.