Rails 3.2 form_for for all database entries - ruby-on-rails

I'd like to create a page where I can edit all my entries at once.
For example, I have 10 devices, at that point, I'm creating a html table with at each row a device with the possibility to edit each line without having to do extra clicking.
I've already tried these things (index.html.erb)
<% #devices.each do |device| %>
<%= render 'form', locals: { device: #device }%>
or
<%= render 'form', :collection => :device %>
or
<%= render 'form', :device %>
<% end %>
And my form partial
<%= form_for #device do |f| %>
<td><%= f.submit %></td>
<td><%= f.name%></td>
<td><%= f.type</td>
<td>Style app</td>
<td></td>
<td></td>
<% end %>
But I'm still getting this error
undefined method `model_name' for NilClass:Class
Does anyone have a clue?
Thanks

From what you have tried it looks like you are very close. What if you try rendering it as a partial?
<% #devices.each do |device| %>
<%= render partial: 'form', locals: { device: device } %>
<% end %>
Another difference here is the scope of the device param on the second line.

You need to change your partial... You are rendering global variable, you need to render local variable...
So, this is your solution:
<% #devices.each do |device| %>
<tr>
<%= render 'form', locals: { device: device }%>
</tr>
and
<%= form_for device do |f| %>
Here, you should only be using the # in #devices... Nowhere else.
Edit: Don't forget your <tr></tr>

Related

Rails: How to use same partial file for one to many relationship?

For the normal situation. Different views can use the same partial like this
<h1>New zone</h1>
<%= render partial: "form", locals: {zones: #zones} %>
<h1>Editing zone</h1>
<%= render partial: "form", locals: {zones: #zones} %>
<% zones.each do |zone| %>
<%= zone.location%>
<% end %>
But my situation is a bit different, the origin code like this
one belongs_to two #one = One.all
one.html.erb
<%= render partial: "one",locals:{one: #one} %>
_one.html.erb
<% one.each do |n|%>
<%= n.location%>
<% end %>
two has_many one #two = Two.all
two.html.erb
<%= render partial: "two", #two %>
_two.html.erb
<% #two.each do |one|%>
<% one.each do |n|%>
<%= n.location %>
<% end %>
<% end %>
For this situation, how can I code render for two.html.erb if I want one.html.erb and two.html.erb use the same partial _one.html.erb ?
this one is definitely incorrect, but how to correct this?
two.html.erb
<%= render partial: "one/one", locals: {one: #two} %>
========================update============================
I think the basic of question is whether we can use the same partial for an object and at the same time for a collection.

undefined method `errors' for #<Array:0x7fa1cbbbde50>

This is my edit_scheme.rhtml file in which i'm getting this error.
<%=stylesheet_link_tag 'showpage'%>
<%=stylesheet_link_tag 'easy'%>
<%= error_messages_for 'scheme' %>
<% form_tag({:action =>'updatescheme', :id =>#scheme},:multipart=>true) do %>
<!--[form:document]-->
<h2>Edit Scheme</h2>
<%#role = Role.find(:first, :conditions =>["role_name=?",'Help Desk'])%>
<%= render :partial=> 'schemeform'%>
<!--[endform:document]-->
<tr style="text-align:right;">
<td></td>
<td> Status:</td>
<td> <%=radio_button :scheme, :status, "Active"%>Active
<%=radio_button :scheme, :status, "In-Active"%>In-Active</td>
</tr>
<p align="center" style="padding-top:10px;">
<%= submit_tag 'Edit' ,:style=>"padding:2px;"%>
<%if session[:role]=="Administrator"%>
<%= link_to 'Back',:action=>'scheme_search'%>
<%end%>
</p>
<% end %>
The error refers to this line
<%= error_messages_for 'scheme' %>
What I'm Missing? Any help is appreciated!
If you want to list all errors for i.e. a product from a form:
<% #product.errors.full_messages.each do |msg| %>
<li><%= msg %></li>
<% end %>
You should also test are there any errors at all.
<% if #product.errors.any? %>
...
<% end %>
This should work with a collection too.
Try using the :object param as the second arg:
<%= error_messages_for 'scheme', :object => #scheme %>
I found this comment in the source of Rails 2.2 above the error_messages_for method:
# If the objects cannot be located as instance variables, you can add an extra <tt>:object</tt> parameter which gives the actual
# object (or array of objects to use):
#
# error_messages_for 'user', :object => #question.user
https://github.com/rails/rails/blob/c6cb5a5ab00ac9e857e5b2757d2bce6a5ad14b32/actionpack/lib/action_view/helpers/active_record_helper.rb#L162

Refactoring into partials in Rails

In page1, I use code A+B+C
In page2, I use code B+C
So when I make a partial, I realy have no idea in how to deal with this.
For example, In a Post-Comment system. I want to show #comments in 2 different pages. In the comment index page,
We show the post it belongs to. And in the post show page, We only have to show the comments content.(Since there is no need to show the comment.post again)
#Comment Index Page
<% #comments.each do |comment| %>
<%= comment.post %>
<%= comment.author %>
<%= comment.content %>
<% end %>
..
#Post Show Page
<% #comments.each do |comment| %>
<%= comment.author %>
<%= comment.content %>
<% end %>
So, how do I make a partial to reuse the code? Perhaps like this? But this there more elegant way of doing this?
#Comment Index Page
<% #comments.each do |comment| %>
<%= comment.post %>
<%= render comment %>
<% end %>
#Post Show Page
<% #comments.each do |comment| %>
<%= render comment %>
<% end %>
Updated:
I adopt the local variable approach, and update my code like:
# partial
<% if include_topic %>
<div class="Topic">
<h5><%= link_to "#{comment.topic.content}", comment.topic %></h5>
</div>
<% end %>
#Index
<%= render #comments, :locals => {:include_topic => true } %>
But I get undefined local variable or method `include_topic' for #<#
I just find nowhere to debug this issue
Your partial:
<%= comment.post if include_post %>
<%= comment.author %>
<%= comment.content %>
your code:
#index page
<%= render :partial => "partial_path", :collection => #comments, :as => :comment, :locals => {:include_post => true } %>
#show page
<%= render :partial => "partial_path", :collection => #comments, :as => :comment, :locals => {:include_post => false } %>
Syntax could be much shorter but it depends whether or not you stick to rails conventions see doc.
Sidenote: I don't like 1.8.7 syntax
In the partial,
<% comments.each do |comment| %>
<%= comment.post if params[:controller] == "comments" %>
<%= comment.author %>
<%= comment.content %>
<% end %>
and now render this partial in both comments/index and posts/show pages by specifying the comments as a local variable.

rails 3 rendering error div_for?

I am working a on rails 3 project and am trying to render a partial on the user profile page. Rendering works fine for everything except photo. When I try to access a user profile page I get the following error
undefined methodmodel_name' for NilClass:Class`
user show.html.erb
def show
#user= User.find(params[:id])
#photo = Photo.find_by_id(params[:id])
end
In the profile show.html.erb
<%= content_tag :h2, "My photos" %>
<% photo = #user.photos %>
<% if photo.blank? %>
<%= link_to 'Create photo', new_photo_path %>
<% else %>
<%= render :partial => 'photos/photo', :locals => {:photo => #photo} %>
<% end %>
Here is the partial that it is rendering
<%= div_for photo do %>
<table>
<tr>
<th>Title</th>
<th>Date</th>
<th>Extra</th>
</tr>
<tr>
<td><%= photo.title %></td>
<td><%= photo.date %></td>
<td><%= photo.extra %></td>
<td><%= link_to 'View photos', photo %></td>
</tr>
</table>
<% end %>
Any ideas or suggestions on how I can get rid of this error? Thanks in advance
The error is thrown because in :locals => {:photo => #photo}, #photo is null
Note that you are sending the list #user.photos, not a single image.
Here #photo = Photo.find_by_id(params[:id]) you are getting the photo by id, photo_id. I believe you want to find the user's photo
#photos = #user.photos
#for only one photo, also you need to make sure its not null
#photo = #user.photos.first
There isn't photo with this id in database #photo = Photo.find_by_id(params[:id])
And, therefore, you sending nil object to partial. If you want to show all user photos, try this.
<%= content_tag :h2, "My photos" %>
<% photos = #user.photos %>
<% if photos.empty? %>
<%= link_to 'Create photo', new_photo_path %>
<% else %>
<% photos.each do |photo| %>
<%= render :partial => 'photos/photo', :locals => {:photo => photo} %>
<% end %>
<% end %>
When using the div_for note is nil so I would try accessing it by iterating through the code Like I've done below. Then photos should be accessible now.
<% #photos.each do |photo| %>
<%= div_for photo do %>
Code here
<% end %>
<% end %>

RailsTutorial.org book design question

Hi I worked through Michael Hartl's RAILSTUTORIAL book and I have a question about how he builds the user's show page.
The page is supposed to list all the posts a user has made.
UsersController
def show
#user = User.find(params[:id])
#posts = #user.posts.paginate(:per_page => "10",:page => params[:page])
#title = #user.name
end
users/show.html.erb
<table class="profile" summary="Profile information">
<tr>
<td class="main">
<h1><%= #user.name %></h1>
<%= render 'follow_form' if user_signed_in? %>
<% unless #user.posts.empty? %>
<table class="posts" summary="User posts">
<%= render #posts %> # this goes to posts/_post and sends the object as post
# that makes the _post view use a local variable correct?
</table> # is there a way to do with with an #post variable?
<%= will_paginate #posts %>
<% end %>
</td>
<td class="sidebar round">
<%= link_to avatar_for(#user), #user.avatar.url %><br />
<strong>Name</strong> <%= #user.name %><br />
<strong>URL</strong> <%= link_to user_path(#user), user_path(#user) %>
<strong>Posts</strong> <%= #user.posts.count %>
<%= render 'shared/stats' %>
</td>
</tr>
</table>
posts/_post.html.erb
<tr>
<td class="post">
<span class="title"><strong><%= link_to post.title, post %></strong></span><br />
<span class="timestamp">
Posted <%= time_ago_in_words(post.created_at) %> ago. </span>
Likers<span id="likers"><br />
</span>
</td>
<% if current_user?(post.user)%>
<td>
<%= link_to "delete", post, :method => :delete,
:confirm => "You sure?",
:title => post.content %>
</td>
<%end%>
</tr>
I need to render a partial in the users view that uses the post object, but it asks for it as #post and since no #post has been defined in the show action of the user's controller I get a nil error.
It seem odd to me to go from the user's controller to the posts view and use a local variable, which if I understand local variables correctly can't be used outsider that view. Is there a way to assign the value of post in that view to #post in the users view?
Thanks for the help
You need to use a local variable in the partial, and assign it in the locals hash. This line is a shortcut for iterating through the array and rendering the partial. I'm not sure if this works anymore in Rails 3:
<%= render #posts %>
The way I would do it:
<% #posts.each do |post| %>
<%= render 'posts/post', :post => post %>
<% end %>
The slightly older way of rendering partials:
<% #posts.each do |post| %>
<%= render :partial => 'posts/post', :locals => {:post => post} %>
<% end %>

Resources