I am creating multiple edit on my app. I have followed the revised Rails screencast and this code that adapts it to Rails 5.
In my Categories Controller:
def edit_multiple
#categories = Category.where(ID: params[:category_ids])
redirect_to categories_url
end
In my index:
<table class="table" summary="Category list">
<tr class="header">
<th style="text-align: left"><%= sort_link(#q, :NAME, 'NAME', default_order: :desc) %></th>
<th style="text-align: left">POSITION</th>
<th style="text-align: left">ACTIONS</th>
</tr>
<%= render "list" %>
</table>
<%= submit_tag "Edit Checked" %>
In my list partial:
<% form_tag edit_multiple_categories_path, method: :get do %>
<% #categories.each do |category| %>
<tr class="<%= cycle('odd', 'even') %>">
<td><%= check_box_tag "category_ids[]", category.ID %></td>
<td><%= link_to category.NAME, {:action => 'show', :ID => category.ID} %>
<td><%= category.RANK_POSITION %></td>
<td class="actions">
<%= link_to("Edit", {:action => 'edit', :ID => category.ID}, :class => 'button tiny') %>
<%= link_to("Delete", {:action => 'delete', :ID => category.ID}, :class => 'alert button tiny') %>
</td>
</tr>
<% end %>
<% end %>
When I open the categories page, it doesn't show anything from _list partial. There's only table headers and Edit Checked button.
Before adding the code relative to multiple edits the table was showing values from partial.
Note that db column names are capital as I'm building the app on existing db.
How can I fix it?
The problem was simply that
<% form_tag edit_multiple_categories_path, method: :get do %>
should be:
<%= form_tag edit_multiple_categories_path, method: :get do %>
I copied that from the railscast #165
Perhaps someone will find same issue and will find this useful.
Related
Basically I created a controller, model and view for subjects. Basically I have 6 actions inside my controller and set up a REST inside my routes file to route the right file.
When I entered, http://localhost:3000/subjects/index it shows me the view for show.html.erb instead of the index.html.erb
Here's what my subject controller looks like:
class SubjectsController < ApplicationController
def index
#subjects = Subject.sorted
end
And here's the content of my index.html.erb file.
<% #page_title = "All Subjects" %>
<div class="subjects index">
<h2>Subjects</h2>
<%= link_to("Add New Subject", new_subject_path, :class => "action_new") %>
<table class="listing" summary="Subject list" border="1">
<tr class="header">
<th>#</th>
<th>Subject</th>
<th>Visible</th>
<th>Pages</th>
<th>Actions</th>
</tr>
<% #subjects.each do |subject| %>
<tr>
<td><%= subject.position %> </td>
<td><%= subject.name %> </td>
<td class="center"><%= status_tag(subject.visible) %></td>
<td class="center"><%= subject.pages.size %> </td>
<td class="actions">
<%= link_to("View Pages", pages_path(:subject_id => subject.id), :class => 'action show') %>
<%= link_to("Show", subject_path(subject), :class => 'action show') %>
<%= link_to("Edit", edit_subject_path(subject), :class => 'action edit') %>
<%= link_to("Delete", delete_subject_path(subject), :class => 'action delete') %>
<td>
</tr>
<% end %>
<table>
</div>
Also here's what I set up on my routes:
resources :subjects do
member do
get :delete
end
end
Any idea what am I missing?
The answer is simple: in order you access the index page, you need to hit the following URL:
http://localhost:3000/subjects
Obviously, it will be with GET
The reason why you got the error is: since, anything of the format subjects/:id will take you to the show action within SubjectsController, so Rails interprets subjects/index as you are trying to access the page subjects/:id with index as id of the subject. Here's nothing wrong with Rails, since in RESTful web services, you access the index page by ONLY using the plural name of the resource, like in your case http://localhost:3000/subjects
I have a Listing model that I am using to represent a listing for a sublet (apartment), and I created a Filter model as a way for a user to filter listings to his liking. Here in my Filter class, that has a method listings to query listings based on a form submission.
class Filter < ActiveRecord::Base
attr_accessible :air_conditioning, :available_rooms, :bathrooms, :furnished, :negotiable, :new, :parking, :maximum_price, :private_bathroom, :show, :term, :total_rooms, :utilities, :washer_dryer
serialize :term
def listings
#listings ||=find_listings
end
private
def find_listings
listings=Listing.order(:price)
listings=listings.where("listings.price <= ?", maximum_price) if maximum_price.present?
listings=listings.where(total_rooms: total_rooms) if total_rooms.present?
listings=listings.where(available_rooms: available_rooms) if available_rooms.present?
listings=listings.where(bathrooms: bathrooms) if bathrooms.present?
listings=listings.where(term: term)
listings=listings.where(furnished: furnished)
listings=listings.where(negotiable: negotiable)
listings=listings.where(utilities: utilities)
listings=listings.where(air_conditioning: air_conditioning)
listings=listings.where(parking: parking)
listings=listings.where(washer_dryer: washer_dryer)
listings=listings.where(private_bathroom: private_bathroom)
listings
end
end
In order to show these, I created a show method for filter that I want to render a partial template. This is what I currently have, but it won't render the template I created called _listings.html.erb in /listings
<p id="notice"><%= notice %></p>
<%= #filter.listings.size %>
<%= render #filter.listings %>
And here is the template
<div style="padding:5px">
<%= link_to 'New Listing', new_listing_path,{:style=>'', :class => "btn"} %>
<h1>Available Sublets</h1>
<table id="listingTable" class="table table-bordered table-hover">
<tr>
<th><%= link_to 'Filter', new_filter_path,{:style=>'', :class => "btn"} %><%= link_to 'Clear Filter', listings_path, {:style=>'', :class => "btn"} %></th>
<th>Address</th>
<th><u><%= "Price Per Month" %></u></th>
<th>Description</th>
</tr>
<% if #listings !=nil %>
<% #listings.each do |listing| %>
<tr onmouseover="this.style.cursor='pointer';"
onclick="window.location.href = '<%= url_for(:controller => 'listings', :action => 'show', :id=>listing.id) %>' " >
<td><%= image_tag listing.photo.url(:small) %></td>
<td><%= listing.address %></td>
<td>$<%= listing.price %></td>
<td width="40%"><%= listing.description %></td>
</tr>
<% end %>
<% end %>
<% else if #listings==nil %>
<p> Sorry, No Sublets Fit Your Criteria! </p>
<% end %>
</table>
I think my naming conventions are messed up, but I can't find the correct way to do this. Anyone have any suggestions. Also, the filter always seems to come up empty. I've tested it many times with simple filters but it never works. If anyone sees an error in my filter feel free to point it out. Thanks!
If you call render and pass it an array or relation, it will actually call the singular version on the partial. When you call
<%= render #filter.listings %>
What it ends up doing is equivalent the following:
<%= render :partial => 'listings/listing', :collection => #filter.listings %>
which is equivalent to
<% #filter.listings.each do |listing| %>
<%= render listing %>
<% end %>
Also, there is an error in or partial around the `<% end %> <% else if ... %>, it should be the following
<% if #listings != nil %>
<% #listings.each do |listing| %>
<tr onmouseover="this.style.cursor='pointer';"
onclick="window.location.href = '<%= url_for(:controller => 'listings', :action => 'show', :id=>listing.id) %>' " >
<td><%= image_tag listing.photo.url(:small) %></td>
<td><%= listing.address %></td>
<td>$<%= listing.price %></td>
<td width="40%"><%= listing.description %></td>
</tr>
<% end %>
<% else %> (since you already checked if it was nil, you it is implied at this point the value is nil
<p> Sorry, No Sublets Fit Your Criteria! </p>
<% end %>
I would recommend writing it the following way, as it is more Ruby-esque
<% if #listings.blank? %>
<p> Sorry, No Sublets Fit Your Criteria! </p>
<% else %>
<% #listings.each do |listing| %>
<tr onmouseover="this.style.cursor='pointer';"
onclick="window.location.href = '<%= url_for(:controller => 'listings', :action => 'show', :id=>listing.id) %>' " >
<td><%= image_tag listing.photo.url(:small) %></td>
<td><%= listing.address %></td>
<td>$<%= listing.price %></td>
<td width="40%"><%= listing.description %></td>
</tr>
<% end %>
<% end %>
The way I would ultimately handle this case is the following:
Your Filter show view
<p id="notice"><%= notice %></p>
<%= #filter.listings.size %>
<div style="padding:5px">
<%= link_to 'New Listing', new_listing_path,{:style=>'', :class => "btn"} %>
<h1>Available Sublets</h1>
<table id="listingTable" class="table table-bordered table-hover">
<tr>
<th><%= link_to 'Filter', new_filter_path,{:style=>'', :class => "btn"} %><%= link_to 'Clear Filter', listings_path, {:style=>'', :class => "btn"} %></th>
<th>Address</th>
<th><u><%= "Price Per Month" %></u></th>
<th>Description</th>
</tr>
<%= render(#filter.listings) || "<p> Sorry, No Sublets Fit Your Criteria! </p>".html_safe %>
</table>
Your 'listings/_listing.html.erb'
<tr onmouseover="this.style.cursor='pointer';"
onclick="window.location.href = '<%= url_for(listing) %>' " >
<td><%= image_tag listing.photo.url(:small) %></td>
<td><%= listing.address %></td>
<td>$<%= listing.price %></td>
<td width="40%"><%= listing.description %></td>
</tr>
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.
How could you do what's covered in RyanB's Railscast on editing multiple records individually, using Formtastic? Formtastic doesn't use form_tag, which RyanB's method relies on.
The semantic_form_for is just a wrapper around form_for so you can use the same parameters. Here is a formtastic version of Ryan Bates' screencast
views/products/edit_individual.html.erb
<% semantic_form_for :update_individual_products, :url => update_individual_products_path, :method => :put do |f| %>
<% for product in #products %>
<% f.fields_for "products[]", product do |ff| %>
<h2><%=h product.name %></h2>
<%= render "fields", :f => ff %>
<% end %>
<% end %>
<p><%= submit_tag "Submit" %></p>
<% end %>
views/products/index.html.erb
<% semantic_form_for :edit_individual_products, :url => edit_individual_products_path do %>
<table>
<tr>
<th></th>
<th>Name</th>
<th>Category</th>
<th>Price</th>
</tr>
<% for product in #products %>
<tr>
<td><%= check_box_tag "product_ids[]", product.id %></td>
<td><%=h product.name %></td>
<td><%=h product.category.name %></td>
<td><%= number_to_currency product.price %></td>
<td><%= link_to "Edit", edit_product_path(product) %></td>
<td><%= link_to "Destroy", product, :confirm => 'Are you sure?', :method => :delete %></td>
</tr>
<% end %>
</table>
<p>
<%= select_tag :field, options_for_select([["All Fields", ""], ["Name", "name"], ["Price", "price"], ["Category", "category_id"], ["Discontinued", "discontinued"]]) %>
<%= submit_tag "Edit Checked" %>
</p>
<% end %>
Please note that you can use the form_for helpers as well in formtastic.
Update
If you like to use nested attributes as well it should work out of the box, using fields_for on the form partial. Lets stick with the railscast example and say that:
product.rb
has_many :commments
accepts_nested_attributes_for :comments
You can edit the comments on the _fields.html.erb of the products like:
<%= f.fields_for :comments do |cf| %>
<%=render 'comments/fields', :f=>cf%>
<%end%>
And make sure you have a fields partial in your comments views.
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!