Form in Ruby on Rails - ruby-on-rails

I can't sort out the forms. I'm going along with tutorial (Agile Web Development with Rails) and I'm trying to simply add the field Quantity to my line_items table. Can't figure this out. Please help. How can I change button_to to pass extra value?
<% if notice %>
<p id="notice" ><%= notice %></p>
<% end %>
<h1>Your Pragmatic Catalog</h1>
<% #products.each do |product| %>
<div class="entry" >
<%= image_tag(product.image_url) %>
<h3><%= product.title %></h3>
<%=sanitize product.description %>
<div class="price_line" >
<span class="price" ></span>
<%= button_to 'Add to Cart', line_items_path(:product_id => product) %>
</div>
</div>
<% end %>

Could you do something like:
<%= button_to 'Add to Cart', { :action => "delete", :id => #image.id, :locals => {:quantity => quantity} } %>
?

Related

Form_tag routing error after unsuccessful submit

I have an index page with a partial form to submit new records to Package model. I keep this form in the index page, so the user doesn't need to leave the page when repeating this action, several times.
In the same page I have a form_tag fir multiple updates for the same controller, namely packages_controller.
Everything works fine, except the following: when hit the update button, going to the form BUT instead of submitting I go back (with the browser) and try to select other records to be updated then I have a routing error:
Routing Error
No route matches [PUT] "/projects/47/orderlines/18/packages"
My index page looks like this:
<% if current_user %>
<%= render "packages/form" %>
<% end %>
<% if #packages.count >= 1 %>
<table class="table table-striped">
<thead>
<tr>
<th> <input type="checkbox" id="selectAll" value="selectAll"></th>
<th>Packed </th>
<th>#No.</th>
<th>Type</th>
<th>Gross weight</th>
<th>Length</th>
<th>Width</th>
<th>Height</th>
<th></th>
<th>Container</th>
</tr>
</thead>
<%= form_tag edit_multiple_project_orderline_packages_path, method: :get do %>
<tbody>
<% for package in #packages %>
<% if package.packed== true %>
<% #label_type="success" %>
<% else %>
<% #label_type="default" %>
<% end %>
<tr>
<td><%= check_box_tag "package_ids[]", package.id %></td>
<td><span class="label label-<%= #label_type %>"><% if package.packed==true %>Packed<% else %>Unpacked<% end %></span></td>
<td><%= package.package_no %></td>
<td><%= package.package_type %></td>
<td><%= package.gross_weight %></td>
<td><%= package.length %></td>
<td><%= package.width %></td>
<td><%= package.height %></td>
<% if #orderline.packages.count >= 1 %>
<td><%= link_to 'Delete', [package.orderline.project, package.orderline, package],
method: :delete,
data: { confirm: 'Are you sure?' } %></td>
<td><%= #containers.find(package.container_id).container_id if package.packed %></td>
<% end %>
</tr>
<% end %>
</tbody>
</table>
<%= submit_tag "Add to container", class: "btn btn-primary" %>
<% end %>
<br />
<%= will_paginate %>
<br>
And the multiple_edit form
<div class="col-sm-4">
<%= form_tag update_multiple_project_orderline_packages_path, method: :put do %>
<ul>
<% #packages.each do |package| %>
<li>
<%= hidden_field_tag "package_ids[]", package.id %>
<%= package.package_no %>
<%= package.container_id %>
<% package.errors.full_messages.each do |msg| %>
<li><%= msg %></li>
<% end %>
</li>
<% end %>
</ul>
<%= fields_for :package do |f| %>
<div class="field">
<%= f.label :package_no %><br />
<%= f.text_field :package_no, :class => "form-control" %>
</div>
<br />
<div class="field">
<%= f.label :container_id %><br />
<%= select_tag 'package[container_id]', options_from_collection_for_select(#project.containers, 'id', 'container_id', default_blank: true), prompt: "- Select container -", :class => "form-control" %>
</div>
<br />
<div class="field">
<%= f.label :packed %><br />
<%= f.select :packed, [["Packed", true], ["Unpacked", false]],{ prompt: "- Packing -"},{ :class => "form-control" } %>
</div>
<% end %>
<div class="actions">
<br />
<%= submit_tag "Update", :class => "btn btn-primary" %>
</div>
<% end %>
</div>
And the packages controller edit_multiple actions:
def edit_multiple
#project = Project.find(params[:project_id])
#packages = Package.find(params[:package_ids])
end
def update_multiple
#packages = Package.find(params[:package_ids])
#packages.reject! do |package|
package.update_attributes(package_params.reject { |k,v| v.blank? })
end
if #packages.empty?
redirect_to project_orderline_packages_url
else
#package = Package.new(package_params)
render "edit_multiple"
end
end
packages_controller create action:
def create
project = Project.find(params[:project_id])
orderline = project.orderlines.find(params[:orderline_id])
#package = orderline.packages.new(package_params)
#package.save
if #package.save
flash[:success] = "Package(s) was successfully added."
redirect_to :back
else
render 'new'
end
And my routes:
resources :projects do
resources :containers
resources :orderlines do
resources :packages do
collection do
put :packed
get :edit_multiple
put :update_multiple
end
end
end
end
I just added my routes here:
edit_multiple_project_orderline_packages_path GET /projects/:project_id/orderlines/:orderline_id/packages/edit_multiple(.:format)
packages#edit_multiple
update_multiple_project_orderline_packages_path PUT /projects/:project_id/orderlines/:orderline_id/packages/update_multiple(.:format)
packages#update_multiple
project_orderline_packages_path GET /projects/:project_id/orderlines/:orderline_id/packages(.:format)
packages#index
POST /projects/:project_id/orderlines/:orderline_id/packages(.:format)
packages#create
new_project_orderline_package_path GET /projects/:project_id/orderlines/:orderline_id/packages/new(.:format)
packages#new
edit_project_orderline_package_path GET /projects/:project_id/orderlines/:orderline_id/packages/:id/edit(.:format)
packages#edit
project_orderline_package_path GET /projects/:project_id/orderlines/:orderline_id/packages/:id(.:format)
packages#show
PATCH /projects/:project_id/orderlines/:orderline_id/packages/:id(.:format)
packages#update
PUT /projects/:project_id/orderlines/:orderline_id/packages/:id(.:format)
packages#update
DELETE /projects/:project_id/orderlines/:orderline_id/packages/:id(.:format)
your form_tag code is update_multiple_project_orderline_packages_path
I think it should be update_multiple_project_orderline_package_path(project_id, orderline_id, package_id)
I am not 100% sure with my statement above, because you gave scrambled Rails Routes, hard to read
and your form action seems goes to packages#edit_multiple controller
so paste your edit_multiple method, not create method
are you implementing your scenario above with javascript, or just plain HTML?

Can't find root of 'stack level too deep' error when rendering partial

I've been stuck on this problem for a week. I will mail you a bottle of scotch if you can figure it out. Seriously, its come to bribery.
On taxons#show I'm rendering a products partial, _products.html.erb, which lists out all the products on a table to the show view of the taxons controller. When you click a product, by default the app will redirect the user to products#show, where the _cart_local.html.erb partial is rendered to display 'add to cart' options.
But on taxons#show, when a product is clicked I bring up a lightbox instead so the user doesn't have to leave the page. The lightbox code is inside _products.html.erb, and I'm trying to render _cart_form.html.erb inside of the lightbox. When I do, I get the 'stack level too deep' error and taxons#show won't render.
But the cart renders fine in products#how. I changed #product in the partial to just product. That didn't help. I rendered an empty partial and the page loads, which makes me think the problem is with _cart_local (but why would it render on products#show?).
Then I took out all of the code in between the opening form tag and the ending div/end tags and the page also rendered, which makes me think its in that block, but I can't wittle it down any further. I'm stuck
Here's the code for _cart_local, and if I take out the code between the <!-- Here --> and <!-- AND HERE --> comments, the page renders:
<%= form_for :order, :url => populate_orders_path do |f| %>
<div id="inside-product-cart-form" data-hook="inside_product_cart_form" itemprop="offers" itemscope itemtype="http://schema.org/Offer">
<% if product.has_variants? %> <!-- HERE -->
<div id="product-variants" class="columns five alpha">
<h6 class="product-section-title"><%= t(:variants) %></h6>
<ul>
<% has_checked = false
product.variants.active(current_currency).each_with_index do |v,index|
next if v.option_values.empty? || (!v.in_stock && !Spree::Config[:show_zero_stock_products])
checked = !has_checked && (v.in_stock || Spree::Config[:allow_backorders])
has_checked = true if checked %>
<li>
<%= radio_button_tag "products[#{product.id}]", v.id, checked, :disabled => !v.in_stock && !Spree::Config[:allow_backorders], 'data-price' => v.price_in(current_currency).display_price %>
<label for="<%= ['products', product.id, v.id].join('_') %>">
<span class="variant-description">
<%= variant_options v %>
</span>
<% if variant_price v %>
<span class="price diff"><%= variant_price v %></span>
<% end %>
</label>
</li>
<% end%>
</ul>
</div>
<% end%>
<% if product.price_in(current_currency) and !product.price.nil? %>
<div data-hook="product_price" class="columns five <% if !product.has_variants? %> alpha <% else %> omega <% end %>">
<div id="product-price">
<h6 class="product-section-title"><%= t(:price) %></h6>
<div><span class="price selling" itemprop="price"><%= product.price_in(current_currency).display_price %></span></div>
</div>
<div class="add-to-cart">
<% if product.on_sale? %>
<%= number_field_tag (product.has_variants? ? :quantity : "variants[#{product.master.id}]"),
1, :class => 'title', :in => 1..product.on_hand, :min => 1 %>
<%= button_tag :class => 'large primary', :id => 'add-to-cart-button', :type => :submit do %>
<%= t(:add_to_cart) %>
<% end %>
<% else %>
<%= content_tag('strong', t(:out_of_stock)) %>
<% end %>
</div>
</div>
<% else %>
<div id="product-price">
<br>
<div><span class="price selling" itemprop="price"><%= t('product_not_available_in_this_currency') %></span></div>
</div>
<% end %> <!-- AND HERE -->
</div>
<% end %>
And here is _products.html.erb, the file that is loading all the products, contains the lightbox, and has the render cart partial code:
<div class="overlay-container">
</div>
<%
paginated_products = #searcher.retrieve_products if params.key?(:keywords)
paginated_products ||= products
%>
<% if products.empty? %>
<%= t(:no_products_found) %>
<% elsif params.key?(:keywords) %>
<h6 class="search-results-title"><%= t(:search_results, :keywords => h(params[:keywords])) %></h6>
<% end %>
<div class="product_grid_container">
<div class="grid_2"><%= image_tag("store/featured/#{#featured}.jpg") %></div>
<% if products.any? %>
<ul id="products" class="inline product-listing" data-hook>
<% products.each do |product| %>
<% if product.on_display? %>
<%# ******LIGHTBOX******* %>
<div id="product_popup_<%= product.id %>" class="product_popup" data-popid="<%= product.id %>">
<div class="related-products">
<ul class="related_products_list" id="related_products_list_<%= product.id %>" data-listid="<%= product.id %>">
<% #related_products.each do |related_product| %>
<li class="related_products_item"><%= link_to large_image(related_product, :itemprop => "image", :data => {:imageid => related_product.id}, :id => "related_" + related_product.id.to_s, :class => "related_products_image dimmed"), url_for(related_product) %></li>
<% end %>
</ul>
</div>
<div class="popup-image">
<%= large_image(product, :itemprop => "image", :class => "product-image-popup") %>
</div><!-- popup-image -->
<div class="popup_right_content">
<h2 class="popup-title"><%= product.name %></h2>
<p class="popup-price">$<%= product.price %></p>
<p><%= product.description %></p>
<p class="popup-color">color:</p>
<div class="popup-images" data-productid="<%= product.id %>">
<% if (product.images + product.variant_images).uniq.size > 1 %>
<ul id="popup-thumbnails-taxon" class="thumbnails inline" data-hook>
<% product.images.each do |i| %>
<li class='tmb-all' id='tmb-<%= i.id %>'>
<%= link_to(image_tag(i.attachment.url(:small)), i.attachment.url(:popup), :class => 'tmb-all', :id => "tmb-#{i.id}") %>
</li>
<% end %>
</ul>
<% end %>
</div><!-- popup-images -->
</div><!-- popup_right_content -->
<%= render 'spree/shared/cart_local', :locals => {:product => product} %>
</div><!-- product_popup -->
<%# ******END LIGHTBOX******* %>
<div class="grid_1">
<li id="product_<%= product.id %>" class="columns product three <%= cycle("alpha", "secondary", "", "omega secondary", :name => "classes") %>" data-hook="products_list_item" itemscope itemtype="http://schema.org/Product">
<div class="main-image" id="single_<%= product.id %>" data-productid="<%= product.id %>">
<%= link_to large_image(product, :itemprop => "image", :class => "product-image", :id => product.id), product_path(product), :remote => true, :html => {:class => "product_popup"} %>
</div><!-- main-image-->
<div class="prod_info_box">
<%= link_to truncate(product.name, :length => 50), product, :class => 'info', :itemprop => "name", :title => product.name %>
<span class="price selling" itemprop="price"><%= product.price_in(current_currency).display_price %></span>
<!-- BRINGS THUMBNAILS INTO TAXONS PAGE -- PULLED FROM _THUMBNAILS.HTML.ERB -->
<div class="product-images" data-productid="<%= product.id %>">
<% if (product.images + product.variant_images).uniq.size > 1 %>
<ul id="product-thumbnails-taxon" class="thumbnails inline" data-hook>
<% product.images.each do |i| %>
<li class='tmb-all' id='tmb-<%= i.id %>'>
<%= link_to(image_tag(i.attachment.url(:mini)), i.attachment.url(:normal), :class => 'tmb-all', :id => "tmb-#{i.id}") %>
</li>
<% end %>
</ul>
<% end %>
</div><!-- product-images -->
<!-- END THUMBNAILS INTO TAXONS PAGE -->
<div id="product-description-taxon">
<p><%= product.description %></p>
</div><!-- product-description-taxon -->
</div><!-- prod_info_box -->
</li>
</div>
<% end %>
<% end %>
<% reset_cycle("classes") %>
</ul>
<% end %>
</div><!-- product_grid_container -->
<% if paginated_products.respond_to?(:num_pages) %>
<%= paginate paginated_products %>
<% end %>
Let me know if you need anything else. i appreciate it.
Here's a link to the helpers, maybe the problem is there?
https://github.com/spree/spree/tree/v1.3.2/core/app/helpers/spree
In your _products.html.erb partial change that:
<%= render 'spree/shared/cart_local', :locals => {:product => product} %>
to that:
<%= render partial: 'spree/shared/cart_local', :locals => {:product => product} %>
and problem should be resolved.
Why? Because doing it as you have done it won't pass locals into partial and that's why you've received error, check it by yourself by removing locals. Of course the most interesting part is why you get stack level too deep error here, but I am unable to find answer for that now.
Oh, and debugger is your friend ;)

SImple Rails Search

I generated a search_contoller and view for my rails app.
My Controller:
class SearchController < ApplicationController
def index
if params[:commit] == "Search"
# Great, now lets figure out what sort of query we're after
#searchQuery = params[:q]
#resultsReceived = true
if
#sqlResults = Product.where("title like ? OR categories like ?", "%" + params[:q] + "%", "%" + params[:q] + "%").order("published DESC")
end
else
#resultsReceived = false
#sqlResults = []
end
# Render the page when we're done.
respond_to do |format|
format.html
end
end
end
My View
<%= form_tag("/search", :method => "get") do %>
<%= label_tag(:q, "Search for:") %>
<%= text_field_tag(:q) %>
<%= submit_tag("Search") %>
<% end %>
<% if #resultsReceived == true %>
<b><%= #sqlResults.length %> Results Found For: </b><%= #searchQuery %>
<br>
<table>
<tr>
<th>Publish</th>
<th>Product</th>
<th></th>
</tr>
<% #sqlResults.each do |product| %>
<tr class="<%= cycle('oddrow', 'evenrow') %>">
<td><%= check_box_tag "product_ids[]", product.id, product.published, {:id => product.id, :class => "publish_checkbox"} %></td>
<td><%= link_to 'Edit', edit_product_path(product) %></td>
<td><%= link_to 'Destroy', product, confirm: 'Are you sure you want to KILL this product?', method: :delete %></td>
<td>
<div>
<b>Title:</b> <%= product.title %>
</div>
<div class="float_left prod_image">
<img src='<%= product.image_url %>' class='product_image'></img>
</div>
<div class="float_left prod_description">
<div><b>Product is Published: </b> <%= product.published %></div>
<div><b>Category Names:</b> <%= product.category_names %></div>
<div><b>Categories:</b> <%= product.categories %></div>
<div><b>Rating:</b> <%= product.rating %></div>
<div><b>Wow:</b> <%= product.is_curated %></div>
<div><b>Age:</b> <%= product.pr_attributes['ag_type'] %></div>
<div><b>Gender:</b> <%= product.pr_attributes['gender_type'] %></div>
<div>
<b>Description:</b>
<% if product.long_descr.length < 200 %>
<%= product.long_descr %>
<% else %>
<span id="short_desc_<%= product.id %>"><%= product.long_descr[0..199] %>...</span>
<span class="long_description", id="long_desc_<%= product.id %>"><%= product.long_descr %> </span><a id="<%= product.id %>" class="toggle">toggle</a>
<% end %>
</div>
<div><b>Backfill Male:</b> <%= product.backfill_text['male'] %></div>
<div><b>Backfill Female:</b> <%= product.backfill_text['female'] %></div>
<div><b>Backfill Unisex:</b> <%= product.backfill_text['unisex'] %></div>
<div><b>MP Seller Name:</b><%= product.mp_seller_name %></div>
<div><b>Price:</b> Current: $<%= product.curr_item_price %> / Base: $<%= product.base_item_price %></div>
<div><b>ID STR:</b> <%= product.id_str %></div>
<div><b>Stock:</b> <%= product.stock_status %></div>
<div><b>Last Updated by <%= product.updated_by_name %> at <%= product.updated_at %></b></div>
</div>
</tr>
<% end %>
<% end %>
I need the search to be more specific, and would like to break up the sql statement, so I can search for other additional attributes. For example, I would like search for either TITLE (and get results that match only the string entered by the user) or search by GENDER (and get back only the gender I user is searching for). How can I do this? Should I create new form_tags for each type of search I want to perform? Is it possible to have just one search box in the view, and have the user select between radio buttons as to what they want to search for?
With MySQL, your options are pretty limited to self constructing the LIKE clauses. Most Rails apps on MySQL will use other search options, like SOLr (sunspot), ElasticSearch, or Sphinx.
On PostgreSQL, you have many more options to use the built in full text search capabilities, like Texticle.
A lot of links to the above: https://www.ruby-toolbox.com/categories/rails_search

Rails: making a table from a collection

I'm using the Forem blogging gem. It renders the posts of a particular topic this way.
<%= render :partial => "forem/posts/post", :collection => #posts %>
Is there a way to make the output appear in a table? I've put <td> markup around the sections in the partial below that I want to break up into a table.
The row names I would want are Name, Posted At, Message, In Reply to, and Actions.
I thought I might be able to do something like
#posts.each do |p|
<tr>
p
</tr>
but I can't figure out how to get it to work
Partial
<a name='post-<%= post.id %>'></a>
<div id='post_<%= post.id %>' class='post <%= cycle('odd', 'even') -%>'>
<td>
Name:<%= link_to_if Forem.user_profile_links, post.user, [main_app, post.user] %>
</div>
<div class='icon'><%#= avatar(post.user, :size => 60) %></div>
</td>
<td>
<a href='#post-<%= post.id %>'>
<time datetime="<%= post.created_at.to_s(:db) -%>"><%= "#{time_ago_in_words(post.created_at)} #{t("ago")}" %></time>
</a>
</td>
<td>
<%= forem_format(post.text) %>
</td>
<td>
<% if post.reply_to %>
<span class='in_reply_to'>
<%= link_to "#{t("forem.post.in_reply_to")} #{post.reply_to.user}", "#post-#{post.reply_to.id}" %>
</span>
<% end %>
</td>
<td>
<ul class='actions'>
<% if forem_user %>
<% if can?(:reply, #topic) %>
<% if #topic.can_be_replied_to? %>
<li><%= link_to t('reply', :scope => 'forem.topic'), new_topic_post_path(#topic, :reply_to_id => post.id) %></li>
<% end %>
<% if #topic.can_be_replied_to? %>
<li><%= link_to t('quote', :scope => 'forem.topic'), new_topic_post_path(#topic, :reply_to_id => post.id, :quote => true) %></li>
<% end %>
<% end %>
<% if post.owner_or_admin?(forem_user) %>
<% if can?(:edit_post, #topic.forum) %>
<li><%= link_to t('edit', :scope => 'forem.post'), edit_topic_post_path(#topic, post) %></li>
<% end %>
<li><%= link_to t('delete', :scope => 'forem.topic'), topic_post_path(#topic, post), :method => :delete, :confirm => t("are_you_sure") %></li>
<% end %>
<% end %>
</ul>
</td>
</div>
</div>
Have you tried adding instead of at the very beginning of the code for the partial? And perhaps a before the loop over posts?

Display array element in rails

I try to make the two columns list of products, this is my code
<table>
<% (0..#products.length-1).step(2) do |i| %>
<tr><td><div id="product_left">
<%= image_tag #products[i].photo.url(:small) %>
<%= #products[i].name %><br/>
Price: <%= #products[i].price %><br/>
<%= link_to "details", :action=>"show", :id=> #products[i].id %>
<%= link_to "add to card", {:controller=> "carts", :action=>"add", :id=> #products[i].id}, :remote=> true %>
</div> </td>
<% if #products.length > i %>
<td><div id="product_right">
<%= image_tag #products[i+1].photo.url(:small) %>
<%= #products[i+1].name %><br/>
Price: <%= #products[i+1].price %><br/>
<%= link_to "details", :action=>"show", :id=> #products[i+1].id %>
<%= link_to "add to card", {:controller=> "carts", :action=>"add", :id=> #products[i+1].id}, :remote=> true %>
</div></td>
<% end %>
</tr>
<% end %>
</table>
the problem is in the second div, rails give me an error on #products[i+1]. How can I solve it?
<table>
<% #products.each_slice(2) do |products| -%>
<tr>
<% products.zip(["left", "right"]).each do |product, side| -%>
<td>
<div id="product_<%= side %>">
<%= image_tag product.photo.url(:small) %>
<%= product.name %><br/>
Price: <%= product.price %><br/>
<%= link_to "details", product %>
<%= link_to "add to card", [:add, :carts, product], :remote=> true %>
</div>
</td>
<% end %>
</tr>
<% end -%>
</table>
Also you shouldn't use not uniq id. Here you have got multiple product_left and product_right ids. That's not good

Resources