#80 Simplify Views with Rails 2.0
Rails 2.0 is almost here. One of the many features in this release is the smarter helper methods which can make your views much cleaner. Learn all about it in this Episode.
- Download:
- mp4Full Size H.264 Video (8.24 MB)
- m4vSmaller H.264 Video (5.78 MB)
- webmFull Size VP8 Video (19 MB)
- ogvFull Size Theora Video (12.5 MB)
When I type
<!-- index.html.erb -->
<%= render :partial => @products %>
Then it search for partial in the wrong folder?
/products/_product
and not
/product/_product
If you use the namespace route like that :
map.namespace :admin do |admin|
admin.resources :products
end
you can write this :
<% form_for([:admin,@product]) do |f| %>
Joel, I don't think the problem is a namespace. Jamal probably made a ProductController instead of a ProductsController.
Jamal, always remember to pluralize your RESTful controllers:
script/generate controller products
Seem I am out of date here...So no more rhtml? .html.erb now?
Yet another set of conventions that will help simplify Rails apps. I love it. I know a lot of people were disappointed that Rails 2.0 wasn't going to add any "big" features, but it's good to see that the focus has been on further simplifying the code that's written for the most common cases.
Thanks for the video, I like this one.
But I have a question. This with REST is very confusing. If I have created a controller for example "ruby script/generate controller products/toys". How do I write in route.rb? I can't write "map.resources :products/toys".
please give us more info on rails 2.0. i just can't wait for the final RC.
One thing that annoys me about the rails 2 view shortcuts is when using restful nested controllers.
Maybe I'm just doing something wrong.
routes.rb:
map.resources :people,
:has_many => :written_articles
now, in views for my WrittenArticlesController, I can't use form_for @article anymore.
Neither can I use link_to 'Show', @article anymore.
I have to revert to person_written_messages_path(@person, @article) which is silly.
This isn't the worst,
It is far worse that form_for @article won't work anymore (which is very nice to have, because new and edit can use the same form) and I have to revert to full paths again, and _manually_ tell the form to use PUT or POST.
Am I doing something wrong here? Wouldn't it be much cleaner for rails to just assume (since it's rendering a view for the written_articles controller) I'm talking about the @article in scope of the person who wrote it? And then if I really want to link to the message itself force me to use article_path(@article) ?
Since mew.html.erb and edit.html.erb share the same code except the Title maybe, can we replace the foll. code with a partial like <%= render :partial => "form" %>?
<!-- new.html.erb and edit.html.erb -->
<% form_for @product do |f| %>
...
<% end %>
Will the system be smart enough to detect if it is the case of new or edit from within the partial?
Ok...I feel stupid, can someone give me links or explain a little bit of ERB?
Please! :)
I mean, why the use of the filename ".html.erb"?
PS: sorry for the many posts, this keyboard doesn't behave well...
@Jose .. just rename your rhtml files to html.erb, and your rxml to xml.builder and everything will work well or just use this code:
[code]
task :rhtml2erb do
desc 'Renames all your rhtml views to erb'
Dir.glob('app/views/**/*.rhtml').each do |file|
puts `svn mv #{file} #{file.gsub(/\.rhtml$/, '.html.erb')}`
end
end
[/code]
Everyone who want to use the latest version of rails has just to use this in his application root folder:
[code]
"svn co http://dev.rubyonrails.org/svn/rails/trunk vendor/rails"
[/code]
it will checkout the latest version from trunk and puts it into vendor/rails ... rails will check if it is available automatically before it uses the installed version.
one remark -> (the version aufter 8165 seems to have one bug and does not work correct today, but maybe they correct it until tomorrow)
so append "--revision 8165" to the upper command.
@Mathijs, try this:
form_for [@person, @article]
I normally don't use nested resources so I'm not certain this will work.
@Andy, the map.resources method supports a :path_prefix option. Try using that:
map.resources :toys, :path_prefix => 'products'
Untested.
@Rupak, yep, form_for works great when placed in a partial. That's what I usually do.
any plan for using jquery instead of prototype?
Hey, thanks a lot QuBiT, very helpful.
Ryan, great work as usual!
@Mathijs
...#6432 from the changelog
url_for([parent, child])
generates /parents/1/children/2 for the nested resource.
Likewise with the other simply helpful
methods like
form_for
and
link_to.
@Jose
in addition to what QuBit said:
xyz.js.erb for Javascript-generating files in the views
xyz.erb for mail-generating files in the views
If you are looking for jQuery for Rails, check this out. http://ennerchi.com/projects/jrails
Hey Ryan. Thou art the man. Rock on.
Nice screencast, good work!
Nice work. I like the simplified div_for, and partials as well.
I'm a little confused on puts vs. post/get
I'm a little confused. If you use
<!-- index.html.erb -->
<%= render :partial => @products %>
<!-- show.html.erb -->
<%= render :partial => @product %>
does it means the the _product.html.erb partial contains the fields of the forms (edit/new) and also the lines of your list (index).
What am I missing here?
@sandro, the "_product.html.erb" partial only contains the html to display the product - not any form/fields to edit a product. I did not put form fields in a partial for simplicity sake, but you would likely want to create some kind of "_form.html.erb" partial for that.
When I do this I get a 'undefined method "article_path"' error from my partial. It doesn't like "article" in my link_to.
Would you pl help me to fix this,in my old rails version i used to render files like
render(:partial=>'list_categories')
Now its not working with version 2.0.2.How can i make it work???
Thanks in advance
really needed to work with the new concepts in rails 2.0.2
Great cast as always.
1) PLease can you tell me where the best place to find documentation on this feature is (rails api)
2) I'm not quite sure how this would work since it's likely that the partial for an index will need to be different for a partial from the show. The index view is likely to be much briefer than show view.
Thanks for any tips
Anthony
I'd like to ask sandro.d#s question agian in a slightly different form
I'd like the 'view' and 'edit'/'new' to look the same. Same layout and laels & screen position. So I'd like to use the same ... well, its not really a _form now is it? Or is it? And how would you address it in 'view.rhtml.erb'?
Just a quick question. When you use the shortcut for displaying partials:
render :partial => @products
does it make any assumptions about where the partial is stored? I have a feeling it assumes the partial is stored in the controller with the same name.
To illustrate, imagine a directory like such:
views/products/_product.html.erb
views/users/_product.html.erb
When rendering by doing:
render :partial => @product
the shortcut automatically gets the partial from views/products, even though the render may be in the users controller.
However, this problem does not occur when doing it the long way:
render :partial => 'product', :object => @product
Any comments?
Ryan,
I have been using this style of rendering partials since I first watched this screencast, and I really appreciate the abbreviated syntax and the conventions that it encourages. However, I seem to be having some issues passing locals to partials with this method, as in I can't seem to do it at all. I have asked the railsforum, but haven't had any luck and was hoping you might chime in. Thanks! The post is here:
http://railsforum.com/viewtopic.php?id=15301
As a followup to my previous post, my issue appears to have been a bug, and has been resolved in changeset 8822.
http://dev.rubyonrails.org/changeset/8822
How would I use a path prefix to my restful routes?
ex.
Instead of "http://mysite.com/articles/1...
Have "http://mysite.com/blog/articles/1...
Do i make a separate controller?
script/generate controller Blog::Articles ?
Or is it something simple that I'm completely overlooking?
@Rome, there is a :path_prefix option for map.resources which should do the job:
map.resources :articles, :path_prefix => '/blog'
@Wesley, yes, the partial is assumed to be in the controller with the same name (no matter what controller you're currently in). Usually this is an acceptable assumption, but if you don't want this behavior it's best to define the location manually.
@Anton, if you want the show, edit, and new actions to use all the same view you can create just one (show.html.erb) and define that in the other actions:
def new
#...
render :action => 'show'
end
If there are minor differences then I recommend you stick with a partial.
Yeah, rails is making shorter and shorter. That's nice but I am wondering when we approach the border when one command will do everything:D.
Great cast as usually.
I extracted the following from a new.html.erb template:
<h3> Entity Header </h3>
<% fields_for(@entity) do |e| %>
<fieldset>
<p>
<b>Entity Name</b><br />
<%= e.text_field :entity_name %>
</p>
<p>
<b>Entity Legal Name</b><br />
<%= e.text_field :entity_legal_name %>
</p>
<p>
<b>Entity Legal Form</b><br />
<%= e.text_field :entity_legal_form %>
</p>
</fieldset>
<% end %>
and put this in its place:
<% form_for(@client) do |f| %>
<% render :partial => "entities/entity_fields_for", :object => @entity %>
When i try and add a new client the log shows this:
Parameters: {"action"=>"new", "controller"=>"clients"}
Rendering template within layouts/clients
Rendering clients/new
Rendered entities/_entity_fields_for (0.00368)
Completed in 0.05866 (17 reqs/sec) | Rendering: 0.01921 (32%) | DB: 0.00000 (0%) | 200 OK [http://localhost/clients/new]
but nothing from the partial actually appears in the html that is generated. This is my very first attempt at using partials and I am at a loss. Is there anything obvious that I am doing wrong?
I left off the = from the opening <% of the render call. Sigh.
When using a namespace, is there a path to load the partial. For instance, is there anything like:
form_for([:admin, @post]) do
render :partial => [:admin, @post]
end
to tell the partial to look in /admin/post/_post.html.erb instead of /post/_post.html.erb?
@Jose - If your "keyboard doesn't behave well" wouldn't there be fewer posts from you?
I'm trying to expose a form in an admin interface with all fields and in the normal user interface with just a subset. To stay as dry as possible, I'd like to include (in the C sense) a file with the common fields defined. Rendering a partial doesn't cut it because:
1. Inside the partial, it blows up on every f.field reference because it doesn't know what f is.
2. I'd like to come back to the original form declaration to pick up the submit button declaration specific to the use.
Does anyone know how/if I can do this?
I wonder how rails implement render action from views just like ASP.NET MVC?
可以说中文么?