displaying one too many items rails - ruby-on-rails

I am building a simple app and in many views I am displaying all of the objects associated with a certain model (many-to-one relationship). For example, I have a house model and an Item model where House has many Items. On the Show view for house I have the following code:
<% #house.items.each do |item| %>
<% if item.needed == true%>
<p>
<%= item.description %>
</p>
<% end %>
<% end %>
and this displays all the items along with one blank item. If I delete all the items, leaving an empty array there is still one empty item remaining. I can hack this using the code:
<% #house.items[0..-2].each do |item| %>
<% if item.needed == true%>
<p>
<%= item.description %>
</p>
<% end %>
<% end %>
This is probably a really simple question, but I would like to avoid using the latter code, and would like to understand why this is happening. Thanks.

The issue you are seeing is data related. This is to say, you need to figure out what is being returned by #house.items. Perhaps you have an item that has needed == true and a blank description? To trouble shoot this verify what is being returned by the house object in question by opening up the rails console, loading the house object in question and checking what is returned by house.items.

When using #house.items.new to set up a new Item object, it will alter the #house.items array, even though the new item is not yet persisted to the database. Example:
items = #house.items
items.length
# => 3
item = #house.items.new
items.length
# => 4
You could either add a check inside your loop for something like if item.persisted? or unless item.new_record?. Or, you could build the new item this way instead, which won't include it in #house.items until it's actually saved to the database:
item = Item.new(house_id: #house.id, needed: true)

Related

What is the best way to find all products by id array?

I am trying to make it possible for an unregistered user to shop.
I use cookies for this.
For the cart view I use:
in controller: #cart_items = cookies[:cart_items].split(',')
in view:
<% #cart_items.each do |cart_item| %>
<%= Product.find(cart_item).title %>
<%= Product.find(cart_item).price %>
<% end %>
but i think it's not so good.
What is the best way to find all products by id array?
in controller do this so you are preparing the queried one in the view
controller:
#cart_items = Product.where(:id => cookies[:cart_items].split(','))
and in the view you do this
<% #cart_items.each do |cart_item| %>
<%= cart_item.title %>
<%= cart_item.price %>
<% end %>
Cookie parsing definitely does not belong in the view. And you should also generally avoid querying the database in the view. The view should ideally just take data from the controller and display it.
Also never use .find in a loop. It will create a database query for each iteration. It will also raise a ActiveRecord::RecordNotFound exception if any of the ids where not found in the database.
So:
#cart_items = Product.where(id: cookies[:cart_items].split(','))
Is less bad. But hardly ideal as it won't let you handle quantities. Instead you could store JSON or create a "guest" Cart record in the database.

Rails show custom label for attribute in view

I'm sure this has already been asked and it's pretty easy but I don't really know what to search to find a solution.
If I have values in a column table like 1,-1,2 where -1 = sale, 1 = purchase etc, how do I show purchase instead of 1 or sale instead of -1?
Database table stockmovements column name reason.
Whenever I face such situation I create a readable_method in model.
In your model class add method like this:
def readable_reason
case reason
when -1
"sale"
when 1
"purchase"
end
end
Then In your view,
<td>stockmovement.readable_reason</td>
It keeps my view file more readable. Also I don't have to copy case-when in every view where I want to show reason.
You can do like this:
<% if stockmovement == 1 %>
purchase
<% elsif stockmovement == -1 %>
sale
<% end %>
Inside your table's document you should put:
<td>
<% case stockmovement %>
<% when 1 %>
"purchase"
<% when 2 %>
"sale"
<% end %>
</td>

Getting the latest entry for a user from a table

I am having a table named names in which there is a column named name. The users will enter a text before proceeding to next page.
In the next page I want to show them the data they entered on previous page.
In controller I tried something like #names = current_user.names.all
In views I did
<ul class="names-list">
<% #names.each do |nname| %>
<li>
<%= link_to nname.name, edit_name_path(nname) %>
</li>
<% end %>
</ul>
and show the last list item for the latest date. But surely there will a Rails shortcut to fetch the last data for the user. Any help?
UPDATED : Now I did something like
#last_name = current_user.names.last in controller and in view
<%= #last_name.to_s %> and it is generates #<Name:0x007fae23ee1b68>
instead of name string.
I think <%= #last_name.to_s %> only outputs the object #last_name's name in memory, since thats specifically what you're asking it to output.
If your names table contains the column "name",
the correct code in your view should be <%= #last_name.name %>
This specifically outputs the object #last_name's name, and not the objects name itself (in memory).
Figured out via #Lanny
In controller
#last_name = current_user.names.last
In view
<%= #names.name %>

Confused about nil rails view

I'm simply trying to ensure a value exists in a certain block and to display it's contents if it does and if not display "Nothing for this yet." I've researched other SO posts but my implementation must be off.
<% #profiles.each do |profile| %>
<%= profile.current_club %>
<% if profile.listings %>
<%= video_thumb_embed(profile.listings.last.video).html_safe %>
<% end %>
<% end %>
Video is an attribute of the listings model.
I'm trying to display all user profiles on an index page and to display the latest video they have added on this index page.
It errors out if a user hasn't added a listing so I added what I thought would be a simple check in the each block but it errors out with the below
undefined method `video' for nil:NilClass
What am I not understanding here? With the above I expect a profile would show on the index page with a video if it had one and if it didn't it wouldn't display anything.
You want to check and make sure that profile.listings is not blank or empty. If you call the last method on an empty array, it returns nil.
<% if profile.listings %> will return true even if you have an empty array.
<% if !profile.listings.blank? %> or <% unless profile.listings.blank? %> should do the trick.

Ruby/Rails - Sorting and Presenting a Large Amount of associated data

I have a model that have a column for name and a column for categories. There are a large amount of names that I would like to list by category but I haven't figured out how to do it.
Currently in the view I have
<% for car in #cars %>
<%= car.name %>
<% end %>
which just presents this huge list of that is way too unwieldy. I'm using #car = Car.find(:all) in the controller to get the selection.
=> If there a way I can create some form of dynamic table where it groups all the car records by category and makes a new column for each category instance, with a listing of all the associated cars?
=> I'm also afraid that that might be too many columns so after 5 or so columns can I start a new row?
=> Should I do all this in the controller or the view?
Can you specify some sample values for the category column?
Depending on what you have stored you may be able to do this:
Car.find(:all).group_by(&:category)
Which will put the cars into an ordered hash indexed by the different category values.
<% #car_categories.sort.each do |category, cars| %>
<h3><%= category %></h3>
<% for cart in cars %>
<p><%= interest.name %></p>
<% end %>
<% end %>

Resources