@austin_web_developer You can fix this by using flash.now[:notice] instead of flash[:notice]. I wrote a blog post explaining how the flash hash works: http://travisonrails.com/2008/08/17/Working-with-the-flash-hash"
This is cool I even created a Textmate command to help when localizing an existing app. Just select some text, and run it, it will ask for a desired translation name, and insert the appropriate <%=t 'name' %> for you. The translation line that you can insert into a yaml file is copied to the clipboard, ready for pasting ;) That makes it so much faster.
You can find it here if you're interested:
http://gist.github.com/31133
Ryan,
I have been using Nested Routes for a while now in dev and they ARE quite long and painful. Shallow routes DO help in that sense.
I am also trying to implement user based subdomains into the app with subdomain_fu. Right now, my routes are of the format http://localhost:3000/accounts/1/etc.
Meaning most of the resources are nested under the accounts resource. Instead, id like to just use the 'subdomain' attribute of the Account model as a subdomain and get rid of the '/accounts/1' part of the URL for good, like http://subdomain.localhost:3000/etc.
Ive actually been looking for write-ups on nested resources, routing and subdomain_fu but havent found any of real use. Could you give me a few pointers on how to get started on this?
This feature was much needed. I liked the "@something ||=" idiom, but it didn't work well in situations that would set the instance variable to null. In those cases, it was kind of ugly to have to write "return @something if defined?(@something)" at the top of the method.
The resources_controller plugin simplifies nested controllers A LOT. In many cases I just need one collection and member finder in my app controller. individual resource controllers are remain almost empty.
def find_resources
resource_service.paginate(:page => params[:page])
end
in the posts / comments example, resource_service is either Comment or @post.comments.
Great show!
I already have implemented nested resources and shallow resources will be a great addition.
Thx a lot!
Question to the community:
On top of nested resources I uses activeresource to exchange data (XML) between 2 web applications. Everyhing is working, but it's super slow as I loop trough all the singe URL's. As far as I see it, it should be possible to transfer just one XML containing all the nested information. What is the best practice here. Is there a good documentation out?
Thanks very much for this tutorial. I was just starting to use migrations to load a bunch of development data, and it was getting very frustrating.
I've been using Populator and Faker for a few weeks now and have noticed an issue with modifying tables in the schema. Populator seems to work fine on tables after their creation, but not after they are modified in future migrations.
For example, I have a `distributors` table I later added a `country` column to. I updated my populator to set the country value, but on running my drop/migrate/populate command, it kept failing saying "country" was not a method.
I fixed this problem by adding a new line after your "delete_all" line that clears out all your data, to call "reset_column_information" before running all of my populator loops.
I think from a newbies perspective it makes more sense going the long way and seeing articles_comment_edit_path just because that's the standard way you would accomplish it or recognize it within a rails application, unless of course they are using the shallow method.
I'm still wrapping my head around these routes in general and learning though so I have yet to fully grasp it all or when it's best to use one method or the other.
I for one have been waiting for this. My very first project had complex associations with resources quite comfortably nesting under a variety of models.
I was stuck with only one set of path names I could use in my controller when I really wanted to be far more dynamic.
I am looking forward to seeing if this truly brings the flexibility I hoped for.
@David: yeah. As with Ryan - I get your point and it makes sense. It's just a difference in philosophy.
As for seeing where you are by looking at other hints - works fine for a human. But if your app does a lot of self-reflecting, the full nested urls come very handy. At least that's been my experience.
@Ryan: I see your point. I guess it comes down to personal taste and your line of thinking definitely makes sense.
That said, I see no reason why nesting comments in both articles and users would be a bad thing. It's very descriptive actually - you look at the url and immidiately understand what you're looking at. It makes sense for the app, when *it* looks at the url as well.
Also, I try not to think about SEO too much on that level. SEO should be a tweak on an overall great setup, not a fundamental issue when creating the design in the first place. That's IMHO anyway.
@EppO and AC, this may be more of a personal opinion, but from a user standpoint I much prefer concise URLs. However, this is not the sole reason I avoid nested routes.
I find most web sites difficult to fit in a pure hierarchical structure. Certainly we have one-to-many associations in our implementation, but these often collide with one another and can become deep. A URL is often not capable of handling complex associations, so attempting to mirror them blindly can get messy.
Another reason is due to the point of entry. Nested resources seem to make sense when we're only editing comments through the article. But what if User has_many comments as well, and on the user profile page we list his comments? Well this is another point of entry, and nesting comments under user also makes sense. A comment in itself is just a resource, and the URL should not be dependent on the point of entry.
That said, it ultimately comes down to your app requirements. I think nested routes definitely have their place if there's a strong one-to-many association which will always apply. Look at how github.com nests user/project in their URL. That is a great example of when to use nested resources.
@Martin, the controller could have an if condition like this: http://pastie.org/333938
@Olli, good point!
@Laszlo, you could do that. But then you'd have multiple URLs leading to the same resource (/comments/2 and /articles/1/comments/2). That can cause confusion and lead to poor search ranking.
Does anyone have the problem where the flash message stays on the page one reload more than it is supposed to?
So if you reload the page, the flash message is still there, but it goes away after a second reload.
Its a problem because if you carry out an action and you get an error, then do it again and get a success message, the previous message is displayed on the page at the same time as the current one.
I was having a heck of a time getting Paperclip to generate thumnails, even though I have working copies of ImageMagick and RMagick installed. My IM was built from source and installed to /usr/local/bin. The solution was to add a line to my development.rb:
Maybe "map.root :articles" isn't such a good idea if some wants to make a seo optimised website. Thats because the content of articles is reachable under / and under /articles .
I did avoid this with a 301 redirect method which is called "map.root :controller => 'articles',:action => 'redirect'"
Thanks for this cast :)
Olli
@David: but when do short/long urls really matter ? Only when pasting urls in irc, forums, emails, etc. In that case shallow routes don't help anyway, because people rarely paste links to edit, or destroy actions. It's mainly index and show in these situations.
On the other hand a full nested routing is descriptive - both for the developer and for the user. It presents a clear hierarchy. I personally, as a user, very often look at the link/form destination url to determine what it really does and how it relates to where I am. It's very helpful.
You keep telling us to avoid nested resources, without giving any reasons other, than "it can get messy".
If that's the sole reason, then I'd rather suggest using the resource_fu plugin along with a little model query abstraction layer.
I added an entity_set method to my controllers, which I use instead of directly calling Model.find. It parses the current route to see what instance variables need to be set - so in case of /articles/1/comments/2 it would set @article = Article.find(1) and @comment = Comment.find(2). And all this I get from one call (e.g. entity_set(:find_one, params[:id])). This deals with the model queries. And resource_fu deals with the urls.
This is part of a larger DRYing layer, that generates the whole controller, model and view for me (allowing for changes where necessary), based on the database layout.
And here's why I think nested routes are better, than what you describe in this episode - they're easy and fast to abstract away. And that's what we should be doing.
Either way, it's been informative, so thanks again for your screencasts!
So, what would be the best way to change CommentsController#index having on the one hand comments nested to a specific Article, and all the comments alone on the other?
Josh: I think Ryan uses iShowU for his screencasts, but I expect he has a decent-ish microphone and setup because it sounds very clear and is well edited.
I don't see why shallow routes is a good idea. Nested resources define and detail a lot scoped resources. That describes dependencies between parents and children resources.
When a comment (of an article) is edited, anybody changing the ID of the comment in the URL can access to a children of another parent resource. You can of course handle this by an authorization mechanism but the error would be wrong ! It would raise non-authorized error although it is a non-existing error (no comment for this article match).
So I disagree that using Comment.find instead of @article.articles.find is a better idea...
Off topic, but after installing Selenium 1.0b2 from the link you provided into Firefox 3.04, I am now getting endless "spam popups". Even with Firefox's "block popups" turned on.
I'll ask around in the Firefox / Selenium/ google, but if anyone else has encountered this, or has any info I'd greatly appreciate finding out how to kill this malware.
Like a bunch of other people on here, I'm setting up a model with multiple attachments.
I've followed this Railscast and Ryan's article on multiple models in one form in Advanced Rails Recipes (#13).
Here's the code I have so far:
http://gist.github.com/33011
As you can see I'm receiving an 'unknown attribute' error. I think this has to do with the way I'm using a new attribute writer method for in the model, and I don't think paperclip has run at that point. So, there is no attachment attribute yet, and thus the error.
Any advice is appreciated.
P.S. I've looked at the other articles mentioned above on polymorphic associations with paperclip, but none of them worked for me.
I can't use ActiveRecord in rsel files...
Without any ActRec's like
product = Product.first
everything works fine, if I insert anything (like "Product.new()" or "Product.find(1)" or whatever (doesn't matter what class I use) I always get a
/opt/local/lib/ruby/gems/1.8/gems/activesupport-2.2.2/lib/active_support/core_ext/module/introspection.rb:9:in `parent_name': can't modify frozen object
vendor/plugins/selenium-on-rails/lib/selenium_on_rails/rselenese.rb:29:in `render'
/opt/local/lib/ruby/gems/1.8/gems/activesupport-2.2.2/lib/active_support/core_ext/module/introspection.rb:31:in `parent'
/opt/local/lib/ruby/gems/1.8/gems/activesupport-2.2.2/lib/active_support/dependencies.rb:88:in `const_missing'
(eval):9:in `render'
...
Thanks!!!! Your screencast is good and easy.
Hello,
I have to following problem when I start workling :
ruby script/workling_client start -t
/Library/Ruby/Site/1.8/rubygems/custom_require.rb:36:in `gem_original_require': no such file to load -- rubyeventmachine (MissingSourceFile)
But gem list --local gives :
eventmachine (0.12.2)
Is there any thing to do ?
Thanks,
Pierre
These screencasts always seem to fit in with what I am doing.
I was working through the jQuery in action book and wanted to use Rails rather than the jsp example. Your screencast was invaluable.
Thanks as ever.
I am looking to get into merb and I hope that the community starts to produce something as valuable as this.
Hurray! My voice has been heard!
Thank you so much Ryan for this screencast!!
Any ideas why I'm getting "Missing layout layouts/application.erb in view path /myapp/app/views"?
For some reason when rendering the .js template my app is trying to use the wrong (non-existant) layout mentioned above.
@austin_web_developer You can fix this by using flash.now[:notice] instead of flash[:notice]. I wrote a blog post explaining how the flash hash works: http://travisonrails.com/2008/08/17/Working-with-the-flash-hash"
My site is very language centric, and recently i used some fragment caching to speed up page loads. Has anyone tried I18n with fragment caching?
If you're getting a bunch of unnecessary instance variables such as
@_cookies or @url
Then you can filter out the responses you don't want like this:
http://pastie.org/336813
This is cool I even created a Textmate command to help when localizing an existing app. Just select some text, and run it, it will ask for a desired translation name, and insert the appropriate <%=t 'name' %> for you. The translation line that you can insert into a yaml file is copied to the clipboard, ready for pasting ;) That makes it so much faster.
You can find it here if you're interested:
http://gist.github.com/31133
Ryan,
I have been using Nested Routes for a while now in dev and they ARE quite long and painful. Shallow routes DO help in that sense.
I am also trying to implement user based subdomains into the app with subdomain_fu. Right now, my routes are of the format http://localhost:3000/accounts/1/etc.
Meaning most of the resources are nested under the accounts resource. Instead, id like to just use the 'subdomain' attribute of the Account model as a subdomain and get rid of the '/accounts/1' part of the URL for good, like http://subdomain.localhost:3000/etc.
Ive actually been looking for write-ups on nested resources, routing and subdomain_fu but havent found any of real use. Could you give me a few pointers on how to get started on this?
@Javan, you want #{previous_release}.
def find_resources
resource_service.paginate(:page => params[:page])
end
in the posts / comments example, resource_service is either Comment or @post.comments.
This feature was much needed. I liked the "@something ||=" idiom, but it didn't work well in situations that would set the instance variable to null. In those cases, it was kind of ugly to have to write "return @something if defined?(@something)" at the top of the method.
The resources_controller plugin simplifies nested controllers A LOT. In many cases I just need one collection and member finder in my app controller. individual resource controllers are remain almost empty.
def find_resources
resource_service.paginate(:page => params[:page])
end
in the posts / comments example, resource_service is either Comment or @post.comments.
The first time I tried this I was using Rails 1.2.3 so I skipped the js.erb file and implemented the javascript directly in the html page.
Now I'm working on another project using Rails 2.2.2 and was able to implement the way you show. It works great.
Thanks to Peer Allan for sharing how he fixed the edit form issue.
I think I'd use the XSS plugin if you're going to do this. I'd worry about security since you're giving users direct access to an sql query.
You can find more about this here: http://api.rubyonrails.org/classes/ActiveRecord/Base.html
Under "Dynamic attribute-based finders"
Great show!
I already have implemented nested resources and shallow resources will be a great addition.
Thx a lot!
Question to the community:
On top of nested resources I uses activeresource to exchange data (XML) between 2 web applications. Everyhing is working, but it's super slow as I loop trough all the singe URL's. As far as I see it, it should be possible to transfer just one XML containing all the nested information. What is the best practice here. Is there a good documentation out?
Thanks very much for this tutorial. I was just starting to use migrations to load a bunch of development data, and it was getting very frustrating.
I've been using Populator and Faker for a few weeks now and have noticed an issue with modifying tables in the schema. Populator seems to work fine on tables after their creation, but not after they are modified in future migrations.
For example, I have a `distributors` table I later added a `country` column to. I updated my populator to set the country value, but on running my drop/migrate/populate command, it kept failing saying "country" was not a method.
I fixed this problem by adding a new line after your "delete_all" line that clears out all your data, to call "reset_column_information" before running all of my populator loops.
populator_models = [Posts, Distributors, ...]
populator_models.each(&:delete_all)
populator_models.each(&:reset_column_information)
On another note, I find it very useful to give certain data a chance to be nil. For example, when populating data for a `contacts` table:
contact.name = [Faker::Name.name, nil]
Or, for when I want it to be more rare a company has a fax number:
contact.fax = Faker::PhoneNumber.phone_number unless rand(5) == 0
Cheers!
@ryan:
Any chance you can do a screencast repeating #17 with the has_many :through and incorporating some additional field storage?
Wonderful episode, wasn't aware of this shallow routes addition until now!
Thanks Ryan!
i have a problem related with this, i can insert data for the many-to-many relationship but it's no deleting anything, what could be the problem?
@Mark Wilden
'Locale is pronounced "loh-CAL".'
It's not in my "loh-cAIL". ;-)
I think from a newbies perspective it makes more sense going the long way and seeing articles_comment_edit_path just because that's the standard way you would accomplish it or recognize it within a rails application, unless of course they are using the shallow method.
I'm still wrapping my head around these routes in general and learning though so I have yet to fully grasp it all or when it's best to use one method or the other.
I for one have been waiting for this. My very first project had complex associations with resources quite comfortably nesting under a variety of models.
I was stuck with only one set of path names I could use in my controller when I really wanted to be far more dynamic.
I am looking forward to seeing if this truly brings the flexibility I hoped for.
Hey Ryan, how do you nest self referencing routes such as a model that uses acts_as_tree ?
For anyone who's interested I've updated a gist with a working example of multiple file attachments using Paperclip.
http://gist.github.com/33011
Notes about the gist:
1. Page has many Assets
2. Asset has Paperclip attachment
3. Paperclip attachment is called 'file'
@Gavin: Thanks for the tip!
I'll check out iShowU...
@David: yeah. As with Ryan - I get your point and it makes sense. It's just a difference in philosophy.
As for seeing where you are by looking at other hints - works fine for a human. But if your app does a lot of self-reflecting, the full nested urls come very handy. At least that's been my experience.
Cheers.
@Ryan: I see your point. I guess it comes down to personal taste and your line of thinking definitely makes sense.
That said, I see no reason why nesting comments in both articles and users would be a bad thing. It's very descriptive actually - you look at the url and immidiately understand what you're looking at. It makes sense for the app, when *it* looks at the url as well.
Also, I try not to think about SEO too much on that level. SEO should be a tweak on an overall great setup, not a fundamental issue when creating the design in the first place. That's IMHO anyway.
Just my two cents..
@EppO and AC, this may be more of a personal opinion, but from a user standpoint I much prefer concise URLs. However, this is not the sole reason I avoid nested routes.
I find most web sites difficult to fit in a pure hierarchical structure. Certainly we have one-to-many associations in our implementation, but these often collide with one another and can become deep. A URL is often not capable of handling complex associations, so attempting to mirror them blindly can get messy.
Another reason is due to the point of entry. Nested resources seem to make sense when we're only editing comments through the article. But what if User has_many comments as well, and on the user profile page we list his comments? Well this is another point of entry, and nesting comments under user also makes sense. A comment in itself is just a resource, and the URL should not be dependent on the point of entry.
That said, it ultimately comes down to your app requirements. I think nested routes definitely have their place if there's a strong one-to-many association which will always apply. Look at how github.com nests user/project in their URL. That is a great example of when to use nested resources.
@Martin, the controller could have an if condition like this: http://pastie.org/333938
@Olli, good point!
@Laszlo, you could do that. But then you'd have multiple URLs leading to the same resource (/comments/2 and /articles/1/comments/2). That can cause confusion and lead to poor search ranking.
I aggree with AC. And instead of writing this:
map.resources :articles, :has_many => :comments, :shallow => true
map.resources :comments, :only => [:index]
yout could also write this:
map.resources :articles, :has_many => :comments
map.resources :comments, :except => [:create, :new]
don't you?
@Martin: Something along the lines of:
@article = nil
unless params[:article_id].blank?
@article = Article.find(params[:article_id])
@comments = @article.comments
else
@comments = Comment.find(:all)
end
Does anyone have the problem where the flash message stays on the page one reload more than it is supposed to?
So if you reload the page, the flash message is still there, but it goes away after a second reload.
Its a problem because if you carry out an action and you get an error, then do it again and get a success message, the previous message is displayed on the page at the same time as the current one.
I was having a heck of a time getting Paperclip to generate thumnails, even though I have working copies of ImageMagick and RMagick installed. My IM was built from source and installed to /usr/local/bin. The solution was to add a line to my development.rb:
Paperclip.options[:image_magick_path] = '/usr/local/bin/'
Hope that helps someone else out!
Maybe "map.root :articles" isn't such a good idea if some wants to make a seo optimised website. Thats because the content of articles is reachable under / and under /articles .
I did avoid this with a 301 redirect method which is called "map.root :controller => 'articles',:action => 'redirect'"
Thanks for this cast :)
Olli
@David: but when do short/long urls really matter ? Only when pasting urls in irc, forums, emails, etc. In that case shallow routes don't help anyway, because people rarely paste links to edit, or destroy actions. It's mainly index and show in these situations.
On the other hand a full nested routing is descriptive - both for the developer and for the user. It presents a clear hierarchy. I personally, as a user, very often look at the link/form destination url to determine what it really does and how it relates to where I am. It's very helpful.
You keep telling us to avoid nested resources, without giving any reasons other, than "it can get messy".
If that's the sole reason, then I'd rather suggest using the resource_fu plugin along with a little model query abstraction layer.
I added an entity_set method to my controllers, which I use instead of directly calling Model.find. It parses the current route to see what instance variables need to be set - so in case of /articles/1/comments/2 it would set @article = Article.find(1) and @comment = Comment.find(2). And all this I get from one call (e.g. entity_set(:find_one, params[:id])). This deals with the model queries. And resource_fu deals with the urls.
This is part of a larger DRYing layer, that generates the whole controller, model and view for me (allowing for changes where necessary), based on the database layout.
And here's why I think nested routes are better, than what you describe in this episode - they're easy and fast to abstract away. And that's what we should be doing.
Either way, it's been informative, so thanks again for your screencasts!
So, what would be the best way to change CommentsController#index having on the one hand comments nested to a specific Article, and all the comments alone on the other?
Thanks again Ryan- great cast.
Josh: I think Ryan uses iShowU for his screencasts, but I expect he has a decent-ish microphone and setup because it sounds very clear and is well edited.
Gav
I don't see why shallow routes is a good idea. Nested resources define and detail a lot scoped resources. That describes dependencies between parents and children resources.
When a comment (of an article) is edited, anybody changing the ID of the comment in the URL can access to a children of another parent resource. You can of course handle this by an authorization mechanism but the error would be wrong ! It would raise non-authorized error although it is a non-existing error (no comment for this article match).
So I disagree that using Comment.find instead of @article.articles.find is a better idea...
The plugin can now be obtained from http://github.com/technoweenie/restful-authentication/tree/master
Make sure you check the plugin Localized Templates... translating long texts can be hard, so I prefer to have templates fully translated.
http://github.com/josevalim/localized_templates/
Awesome screencasts... I've been a long-time fan.
Can you maybe give me a tip on what software you use to create these screencasts?
I'd like to produce some of my own, and yours are always very high quality. Any hints you can offer would be great!
Great job and good idea !
Congratulations for this screencast !! Best Regards Holz-Export
Ubercool! The new code from Advance Rails Recipes works fantastic. (Rails 2.2.2)
Off topic, but after installing Selenium 1.0b2 from the link you provided into Firefox 3.04, I am now getting endless "spam popups". Even with Firefox's "block popups" turned on.
I'll ask around in the Firefox / Selenium/ google, but if anyone else has encountered this, or has any info I'd greatly appreciate finding out how to kill this malware.
thx
Mike
Thanks for the screen cast, Ryan.
I have been using a jQuery plugin called Ajax Forms, which I find much more intuitive. ($.ajaxForm)
check it out here:
http://malsup.com/jquery/form/
Like a bunch of other people on here, I'm setting up a model with multiple attachments.
I've followed this Railscast and Ryan's article on multiple models in one form in Advanced Rails Recipes (#13).
Here's the code I have so far:
http://gist.github.com/33011
As you can see I'm receiving an 'unknown attribute' error. I think this has to do with the way I'm using a new attribute writer method for in the model, and I don't think paperclip has run at that point. So, there is no attachment attribute yet, and thus the error.
Any advice is appreciated.
P.S. I've looked at the other articles mentioned above on polymorphic associations with paperclip, but none of them worked for me.