Rails Rendering Issue - ruby-on-rails

Whenever I'm trying to render the games partial, the view it's being rendered in gives a nil return.
here is the games partial:
<%= flash[:notice] %>
<tr>
<% #games.each do |game| %>
<td><%= game.name %></td>
<td><%= link_to('Pick!', vote_up_game_path(game.id), :method => :post) %></td>
</tr>
<% end %>

You should pass #games as a local variable to the partial. Consider looking at the documentation on its usage. I also feel the flash-notice should not belong inside the partial. You might also want to correct your code
<% games.each do |game| %>
<tr>
<td><%= game.name %></td>
<td><%= link_to 'Pick!', vote_up_game_path(game.id), :method => :post %></td>
</tr>
<% end %>
You would render the partial as follows
<%= render :partial => "game_partial", :locals => { :games => #games } %>
It is also important to ensure #games isn't nil. If it is, you will still get your error - you should check your controller; typically I'd imagine your controller would have #games = Game.all, of course this is dependent on your particular implementation.

Related

Rails: How to DRY up multiple use of a partial

Like to DRY up the following code. Created a partial _user.html.erb, which is called either by the users view via
<%= render #users %>
and by the groups view via
<%= render partial: 'users/user', collection: #mailgroup.users, as: :user %>
The partial _user.html.erb is:
<%= content_tag_for(:tr, user) do %>
<td><%= user.id %></td>
<td><%= check_box_tag "user_ids[]", user.id, true %></td>
<td><%= user.firstname %></td>
<td><%= user.lastname %></td>
<td><%= user.function %></td>
<td><%= user.company %></td>
<td><%= user.appendix %></td>
<td><%= user.city %></td>
<td>
<%= link_to button1 ... %>
<%= link_to button2 ... %>
<%= link_to button3 ... %>
<%= link_to button4 ... %>
</td>
<% end %>
Now I like this partial having rendered once with all columns (call 1.), and also with a subset of columns (call 2.). Especially like to hide the check_box_tag in the second column.
I searched around and was confused at the end how to solve: With different layouts? How would I have to do it with partials? Or with checking first from what controller the call comes from? (This doesn't sound very satisfying to me).
In general: How to call the same partial with different subset of columns without maintaining different copies of that partial?
I'm not sure you can use layouts for partials and I agree that checking for controller source is a code smell. I would consider using another local to check if the fields are to be displayed which could be set in the "calling" view e.g.
<%= render #users, locals: {show_buttons: false} %>
<%= render partial: 'users/user', collection: #mailgroup.users, as: :user, show_buttons: true %>
and used in the user partial
<% if show_buttons %>
<td><%= check_box_tag "user_ids[]", user.id, true %></td>
<% end %>
You could dry this out further with a helper method
<td><%= user.id %></td>
<%= check_box(user, show_buttons)
module UsersHelper
def check_box(user, show_buttons)
if show_buttons
content_tag(:td) do
content_tag(:option, "user_ids[]", value: user.id )
end
end
end
end

Rails show action where `id` is not explicitly stated in params

In my app, I have a view that shows a number of products. If a product has an active "deal" on it, a link to that deal is given for that deal that links to the show action for that deal, as below.
<tr>
<% #item.inventory_items.each do |p| %>
<td><%= link_to image_tag("#{p.vendor.image_url}"), vendor_path(p.vendor) %></td>
<td class="price">$<%= p.price %></td>
<td>
<% if Deal.where(:product_code => p.product_code, :vendor_id => p.vendor_id).exists? %>
<%= link_to "See It!", deal_path(Deal.where(:product_code => p.product_code, :vendor_id => p.vendor_id)) %>
<% else %>
<% end %>
</td>
<td>
......
</td>
</tr>
The problem I'm having is that my show action for Deal is looking in params for a deal id. This deal id isn't really in params, so how can I tell this Deal show action which deal I'm interested in? Thanks in advance! As an aside, my above code feels really verbose and very un-rails-like in my if block. If you have any suggestions for it, any advice is much appreciated.
deal/show.html.erb
<%= link_to image_tag("#{#deal.vendor.image}") %>
<%= #deal.vendor.address %>
<%= image_tag(#deal.image) %>
Deal show action:
def show
#deal = Deal.find(params[:id])
end
Try
<%= link_to "See It!", deal_path(Deal.where(:product_code => p.product_code, :vendor_id => p.vendor_id).first) %>
Your code is definitely not very rails-like.
What you should be able to do is something like this:
<tr>
<% #item.inventory_items.each do |p| %>
<td><%= link_to image_tag("#{p.vendor.image_url}"), vendor_path(p.vendor) %></td>
<td class="price">$<%= p.price %></td>
<td>
<% if p.deal.exists? %>
<%= link_to "See It!", deal_path(:id => p.deal.id)) %>
<% else %>
<% end %>
</td>
<td>
......
</td>
</tr>
Note that you can pass parameters along in a link_to. See this question - link_to send parameters along with the url and grab them on target page
If you're models are setup correctly, you shouldn't have to be doing queries in your views.

How to properly render collection in a partial layout from inside another partial layout?

I have a Cart that I want to render in 3 different ways in my app.
In the sidebar. Displays only item count in cart and their total price.
In Cart main view. Displays line items with links to products, quantity and total price for each item. Also displays buttons to increase/decrease item quantity and a button to remove item from cart.
In Order view, shows cart content the same way as main cart view, except links to products, buttons to change quantities and 'remove' button.
So far I render cart like this:
carts/_cart.html.erb
<%= yield %>
Cart sidebar layout carts/_sidebar.html.erb
<ul>
<li class="nav-header">Your Cart (<%= pluralize(#cart.total_items, "Item") %>)</li>
<li>Total Due: <%= number_to_euro(#cart.total_price) %></li>
<% unless #cart.line_items.empty? %>
<li><%= link_to "View Cart & Checkout", cart_path(#cart) %></li>
<li><%= link_to "Empty Cart", #cart, :method => :delete %></li>
<% end %>
</ul>
Which is rendered from layouts/_sidebar.html.erb by <%= render :partial => 'carts/cart', :layout => 'carts/sidebar' %>
Cart main layout carts/_main.html.erb
<table>
<tr>
<th>Product</th>
<th>Quantity</th>
<th>Price</th>
<th>Subtotal</th>
<th></th>
</tr>
<%= render #line_items %>
<tr id="total_line">
<td colspan="3">Total:</td>
<td><%= number_to_euro(#cart.total_price) %></td>
<td></td>
</tr>
</table>
Which is rendered from carts/show.html.erb
<h1><%= pluralize(#cart.total_items, "Item") %> in Your Cart</h1>
<%= render :partial => 'cart/cart', :layout => 'carts/main' %>
<%= link_to "Empty Cart", #cart, :method => :delete %>
<%= link_to "Checkout", new_order_path %>
And there is also carts/_order.html.erb which is currently rendered from orders/new.html.erb the same way as in cart main view.
What I want to do is to create 2 different layouts to render line items from carts/show.html.erb and orders/new.html.erb. And to do so, I have <%= yield %> in line_items/_line_item.html.erb
Line items layout for cart main layout line_items/_main.html.erb
<tr>
<td><%= link_to "#{line_item.product.brand.name} #{line_item.product.title}", product_path(line_item.product) %></td>
<td>
<%= link_to "-", decrement_line_item_path(line_item), :method => :post %>
<%= line_item.quantity %>
<%= link_to "+", increment_line_item_path(line_item), :method => :post %>
</td>
<td><%= number_to_euro(line_item.product.price) %></td>
<td><%= number_to_euro(line_item.total_price) %></td>
<td><%= link_to "Remove"), line_item, :method => :delete %></td>
</tr>
And similar line items layout for new order view line_items/_order.html.erb
<tr>
<td><%= "#{line_item.product.brand.name} #{line_item.product.title}" %></td>
<td><%= line_item.quantity %></td>
<td><%= number_to_euro(line_item.product.price) %></td>
<td><%= number_to_euro(line_item.total_price) %></td>
</tr>
This is where the problem starts. I don't understand how to render collection. I tried rendering line items from carts/_main.html.erb like this
<%= render :partial => 'line_items/line_item', :layout => 'line_items/main', :collection => #line_items %>
And from carts/_order.html.erb like this
<%= render :partial => 'line_items/line_item', :layout => 'line_items/order', :collection => #line_items %>
But I get LocalJumpError in Carts#show
Showing app/views/line_items/_line_item.html.erb where line #1 raised:
no block given (yield)
Any other :collection name simply renders nothing. What am I doing wrong?
Okay, I understand what I've done wrong. First of all, the error message no block given (yield) means there is nothing to yield. And second, there is no need to use :layout when rendering partials in this case.
To render a cart from layouts/_sidebar.html.erb simply call <%= render :partial => 'carts/sidebar' %>.
There is one thing I didn't know about. When rendering partial with collection, the second part of :partial name becomes local variable name inside that collection.
This is the partial for main cart view (carts/_cart.html.erb):
<table>
<tr>
<td>Product</th>
<td>Price</th>
<td>Quantity</th>
<td>Subtotal</th>
<td></th>
</tr>
<%= render :partial => 'line_items/cart_item', :collection => #line_items %>
<tr>
<td colspan="3">Total:</td>
<td><%= number_to_euro(#cart.total_price) %></td>
<td></td>
</tr>
</table>
Which can be rendered by <%= render #cart %>. Notice the /cart_item part in :partial name. That's how we refer to collection items in line_items/_cart_item.html.erb:
<tr>
<td><%= link_to "#{cart_item.product.brand.name} #{cart_item.product.title}", product_path(cart_item.product) %></td>
<td><%= number_to_euro(cart_item.product.price) %></td>
<td>
<%= link_to "-"), decrement_line_item_path(cart_item), :method => :post %>
<%= cart_item.quantity %>
<%= link_to "+"), increment_line_item_path(cart_item), :method => :post %>
</td>
<td><%= number_to_euro(cart_item.total_price) %></td>
<td><%= link_to "Remove"), cart_item, :method => :delete %></td>
</tr>
And the same way with cart shown in Orders controller. carts/_order.html.erb:
...
<%= render :partial => 'line_items/order_item', :collection => #line_items %>
...
line_items/_order_item.html.erb:
<tr>
<td><%= "#{order_item.product.brand.name} #{order_item.product.title}"%></td>
<td><%= number_to_euro(order_item.product.price) %></td>
<td>× <%= order_item.quantity %></td>
<td><%= number_to_euro(order_item.total_price) %></td>
<td></td>
</tr>
Hope it all makes sense.

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 %>

Ruby on Rails, Posting Variables

I'm very new to rails so hopefully this should be a quick fix. I'm writing an application that searches a database and reloads the page displaying the desired results. In rails how does one save a input into a text_field and post it so that it can be retrieved and used in the query for retrieving data.
My view:
<title></title>
</head>
<body>
Search Collection <br>
<%= text_field "person", "name" %>
<%= select_tag(:search_id, '<option value="0">Search by</option><option value="1">Make</option><option value="2">Condition</option>
<option value="3">Sport</option>') %>
<%= link_to 'New catalog', new_catalog_path %>
<br>
<br>
<%= link_to "Search", :search_text => , :action => :index %> <br>
<br>
<h1>Results</h1>
<%= will_paginate #catalogs %>
<table border="1">
<tr>
<th>Catalog id</th>
<th>Year</th>
<th>Make</th>
<th>Card number</th>
<th>Number</th>
<th>Condition</th>
<th>Sport</th>
<th>Tracking list</th>
</tr>
<% for catalog in #catalogs %>
<tr>
<td><%= catalog.Catalog_ID %></td>
<td><%= catalog.Year %></td>
<td><%= catalog.Make %></td>
<td><%= catalog.Card_Number %></td>
<td><%= catalog.Number %></td>
<td><%= catalog.Condition %></td>
<td><%= catalog.Sport %></td>
<td><%= catalog.Tracking_List %></td>
<td><%= link_to 'Show', catalog %></td>
<td>
<%= link_to 'Edit', edit_catalog_path(catalog) %></td>
<td>
<%= link_to 'Destroy', catalog, :confirm => 'Are you sure?', :method => :delete %></td>
</tr>
<% end %>
</table>
<br>
</body>
My Controller method
def index
#search_text = 'T206 White Border'
#catalogs = Catalog.paginate_by_sql ['select * from catalogs where Make =\''+ #search_text+'\'' , 80000], :page => params[:page]
end
Be gentle if its an easy fix, I'm still getting used to the whole MVC thing
Your question has a lot going on, so let's try to sort through it one piece at a time. First, I'll assume your database has a table called catalogs with a column called make, and that you're using the will_paginate plugin. It looks like you got started by copying and modifying some examples straight from the docs. First, your controller - you don't need the more complex paginate_by_sql, you can use the simpler paginate.
controller:
def index
#catalogs = Catalog.paginate(:all, :conditions => {:make => params[:search]}, :page => params[:page])
end
Now your view, just the stuff relevant to the search:
<% form_tag catalogs_path, :method => :get do %>
<%= text_field_tag 'search' %>
<%= submit_tag 'submit search' %>
<% end %>
And that's it. Good luck!

Resources