How to pass a view value to a controller on rails - ruby-on-rails

I have a controller called items_controller, I need to send a value to it using my unanswered.html.erb view.
But I'm not getting it, my view makes an each and I need each value of that each to call the controller and receive the value of that controller
items_controller.erb
class MercadoLivre::ItemsController < ApplicationController
before_action :set_items
def items
#details = #get_item_service.item_details
#item = #details.body
end
private
def set_items
#get_item_service = MercadoLivre::Items.new
end
end
My service items.rb
module MercadoLivre
class Items
include HTTParty
base_uri 'https://api.mercadolibre.com'
def initialize(mlb_code_id)
#mlb_code = mlb_code_id
#options = {
headers: {
Authorization: 'Bearer ****'
}
}
end
def item_details
self.class.get("/items/#{#mlb_code}", #options)
end
end
end
my view unanswered.html.erb
<div>
<p class="text-2xl mb-3">Perguntas não respondidas</p>
<%= button_to "Ver perguntas respondidas", questions_answered_path, method: :get, class: "mb-5 mt-5 text-red-700" %>
<div>
<% #list['questions'].each do |q| %>
<div class="flex flex-col">
<div>
<p class="font-bold">Pergunta: </p>
<p><%= q['text'] %> </p>
</div>
<div>
<p class="font-bold">Item:</p>
<p><%= q['item_id'] %> </p>
<%# pass value to controller items_controllers.rb here %>
</div>
<textarea name="" id="" cols="30" rows="10">
</textarea>
<button class="mt-5">Responder</button>
</div>
<% end %>
</div>
</div>

You can try creating a new instance of MercadoLivre::Items with the correct number of parameters it was defined;
def set_items
#get_item_service = MercadoLivre::Items.new(1) # you need a value for +mlb_code+
end

Related

undefined local variable or method `form' for Class

When I'm attempting to show a department view on my product#new page, this is my product#new page
<% #produto.errors.full_messages.each do |msg| %>
<div class="alert alert-danger" role="alert">
<%= msg %>
</div>
<% end %>
<%= form_for #produto do |produto| %>
<div class="row">
<div class="col-sm-3">
<div class="form-group">
<%= produto.label :nome %>
<%= produto.text_field :nome, class:"form-control" %>
</div>
</div>
</div>
<div class="row">
<div class="col-sm-3">
<div class="form-group">
<%= produto.label :descricao %>
<%= produto.text_area :descricao, class:"form-control", rows:"4" %>
</div>
</div>
</div>
<div class="row">
<div class="col-sm-2">
<div class="form-group">
<%= form.label :departamento %>
<%= form.collection_select :departamento_id, #departamentos, :id, :nome, {}, class:"form-control" %>
</div>
</div>
</div>
<%= produto.submit "Criar",class:"btn btn-success" %>
<% end %>
This is my product_controller.rb
class ProdutosController < ApplicationController
def index
#produtos = Produto.order(nome: :asc).limit 5
#produtos_com_desconto = Produto.order(:preco).limit 1
end
def new
#produto = Produto.new
#departamentos = Departamento.all
end
def create
valores_produto = params.require(:produto).permit(:nome, :descricao, :preco, :quantidade)
#produto = Produto.new valores_produto
#Produto.create valores_produto
if #produto.save
flash[:notice] = "Produto criado com sucesso!"
redirect_to root_url
else
render :new
end
end
def destroy
id = params[:id]
Produto.destroy id
redirect_to root_url
end
def search
#nome = params[:nome]
#produtos = Produto.where "nome like ?", "%#{#nome}%"
end
end
So, when i'm trying to access my product/new page , i'm receiving the error NameError in Produtos#new: undefined local variable or method `form' for #<#<Class.
<%= form.label :departamento %> is looking for the form variable but there is none defined. Instead <%= form_for #produto do |produto| %> has defined producto and uses it as <%= produto.label :nome %>. So you probably want <%= producto.label :departamento %>
Note the variable should probably be form. The variable is a FormBuilder, not a Produto. Calling it producto is confusing.

undefined local variable or method `cache_key_for_vendor_products'

I've installed the Spree Multi-Vendor gem and have built my Vendor Show page, but am getting a NameError message from the cache_key_for_vendor_products line. Here is my Vendor Controller
module Spree
class VendorsController < Spree::StoreController
before_action :load_taxon, only: :show
def index
#vendors = Spree::Vendor.active
end
def show
#vendor = Spree::Vendor.active.friendly.find(params[:id])
#searcher = build_searcher(searcher_params)
#products = #searcher.retrieve_products.where(vendor_id: #vendor.id)
end
private
def load_taxon
#taxon ||= Spree::Taxon.friendly.find(params[:taxon_id]) if params[:taxon_id].present?
end
def searcher_params
searcher_params = params.merge(include_images: true)
searcher_params[:taxon] = load_taxon.id if load_taxon.present?
searcher_params
end
def vendor_params
params.require(:spree_vendor).permit(
*Spree::PermittedAttributes.vendor_attributes,
stock_locations_attributes: Spree::PermittedAttributes.stock_location_attributes
)
end
def vendor_user_params
params.require(:spree_vendor).require(:user).permit(Spree::PermittedAttributes.user_attributes)
end
def vendor_stock_location_params
params.require(:spree_vendor).require(:stock_location).permit(Spree::PermittedAttributes.stock_location_attributes)
end
end
end
My Vendor Show
<% description = simple_format(#vendor.about_us, class: 'mb-0') %>
<% short = truncate(description, separator: ' ', length: 200, escape: false) %>
<div class="container">
<div class="row px-lg-3 mt-3 vendor-details">
<div class="col-12 text-uppercase text-center mt-4 mb-5 mb-sm-4">
<h1 class="mt-2 mb-4"><%= #vendor.name %></h1>
</div>
<div class="col-12 col-sm-6 col-lg-5 text-center pt-sm-4 pt-lg-3 pb-sm-5 vendor-details-image">
<% if #vendor.image.present? %>
<%= image_tag main_app.url_for(#vendor.image.attachment), class: 'mw-100' %>
<% end %>
</div>
<div class="col-12 col-sm-6 col-lg-5 offset-lg-1 mt-5 mt-sm-0 d-flex flex-column justify-content-center vendor-description">
<div class="vendor-details-about">
<% if description == short %>
<%= description %>
<% else %>
<div class="js-readMore">
<%= tag.div class: "js-readMore-short" do %>
<%= short %>
<% end %>
<%= tag.div class: "js-readMore-full d-none" do %>
<%= description %>
<% end %>
</div>
<% end %>
</div>
</div>
</div>
<p><%= #vendor.contact_us %></p>
<hr/>
<div class="row">
<div class="col-12 mt-5 vendor-details-products">
<% cache(cache_key_for_vendor_products) do %>
<%= render template: #taxon ? 'spree/taxons/show' : 'spree/products/index' %>
<% end %>
</div>
</div>
</div>
And Multi Vendor Helpers located in lib/spree_multi_vendor/multi_vendor_helpers.rb
module SpreeMultiVendor
module MultiVendorHelpers
include ::Spree::ProductsHelper
include ::Spree::FrontendHelper
def cache_key_for_vendor_products
count = #products.count
max_updated_at = (#products.maximum(:updated_at) || Date.today).to_s(:number)
products_cache_keys = "spree/vendor-#{#vendor.slug}/products/all-#{params[:page]}-#{params[:sort_by]}-#{max_updated_at}-#{count}"
(common_product_cache_keys + [products_cache_keys]).compact.join('/')
end
end
end
I've gotten these codes here: https://github.com/spree-contrib/spree_multi_vendor/pull/120/files
On my vendor show page, I get this error and I can't for the life of me figure out what went wrong:
NameError in Spree::Vendors#show
undefined local variable or method `cache_key_for_vendor_products' for #<#Class:0x00007fc173a88478:0x00007fc176034b40>
Can any of you help?

undefined method to each do Ruby on rails

I have two tables: Dimensions and Task. For each dimension have N task.
so in Task Controller i have this:
def new
#dimensions = Dimension.all
#dimensions.each do |dimension|
#task = Task.new
end
end
and the view Task this
<h1>Tasks#new</h1>
<%= form_for(#task) do |task| %>
<div class='service'>
<li class="col-md-3">
<div class="thumbnail">
<div class="caption">
<h4><%= task.name %></h4>
<p><%= task.description %></p>
</div>
<span>
</span>
</div>
</li>
</div>
<% end %>
but on the task view it shows me this error message
undefined method 'name'
undefined method 'descripcion'
try this,
def new
#dimensions = Dimension.all
#dimensions.each do |dimension|
#task = dimension.tasks.new //OR #task = dimension.build_tasks
end
end

Rails, rendering after destroy

I have a Cart/show.html erb with that renders a partial called carts_row.html.erb
<p id="notice"><%= notice %></p>
</br>
</br>
<div class="cart-container">
<%=render 'carts_row'%>
</div>
</p>
In carts_row it's a shopping cart layout with forms to update quantity and destroy/remove item from your shopping cart.
<h1>Shopping Cart</h1>
<div class="shopping-cart">
<div class="column-labels">
<label class="product-image">Image</label>
<label class="product-details">Product</label>
<label class="product-price">Price</label>
<label class="product-quantity">Quantity</label>
<!-- adding update column to labels -->
<label class="product-update">Update</label>
<label class="product-removal">Remove</label>
<label class="product-line-price">Total</label>
</div>
<%if #cart.cart_items.size == 0%>
<div class="text-center">
<p>Looks like you have nothing in your cart! <%=link_to 'Add something to your cart', products_path%></p>
</div>
<%end%>
<br />
<br />
<%if #cart_items != nil%>
<%#cart_items.each do |item|%>
<div class="product">
<div class="product-image">
<%=image_tag(item.product.picture)%>
</div>
<div class="product-details">
<div class="product-title"><%=item.product.name%></div>
<p class="product-description"><%=item.product.description%></p>
</div>
<div class="product-price"><%=number_to_currency(item.product.price)%></div>
<%=form_for item, remote: true do |f|%>
<div class="product-quantity">
<%=f.number_field :quantity, value: item.quantity, min: 1, max: 8%>
<%=f.hidden_field :product_id, value: item.product.id%>
<!-- <input type="number" value="<%=item.quantity%>" min="1" max="8"> -->
</div>
<div class="product-update">
<%=f.submit 'Update', class: "update-product"%>
<!-- <%=f.hidden_field :product_id, value: item.product.id%> -->
<!-- <button class="update-product">
Update
</button> -->
</div>
<div class="product-removal">
<%= link_to "Remove", item, {data: {confirm: "Are you sure you wish to delete the product '#{item.product.name}' from your cart?"}, method: :delete, remote: true, class: "remove-product"}%>
<!-- <button class="remove-product">
Remove
</button> -->
<%end%>
</div>
<div class="product-line-price"><%=number_to_currency(item.product.price*item.quantity)%></div>
</div>
<%end%>
<%end%>
<br />
<br />
<!--Temporary solution until model methods are written -->
<% if #cart_items != nil%>
<!--subtotal variable -->
<%subtotal =#cart_items.collect {|item| item.quantity*item.unit_price}.sum%>
<!--subtotal + shipping cost -->
<%total=subtotal+15%>
<%end%>
<div class="totals">
<div class="totals-item">
<label>Subtotal</label>
<div class="totals-value" id="cart-subtotal"><%=subtotal%></div>
</div>
<div class="totals-item">
<label>Tax (5%)</label>
<div class="totals-value" id="cart-tax">Included!</div>
</div>
<div class="totals-item">
<label>Shipping</label>
<div class="totals-value" id="cart-shipping">15.00</div>
</div>
<div class="totals-item totals-item-total">
<label>Grand Total</label>
<div class="totals-value" id="cart-total">
<%=total%>
</div></div>
</div>
</div>
<div class="checkout-btn">
<button class="checkout">Checkout</button>
</div>
</div>
The update in the form goes to update.js.erb which has this
<% if #cart.errors.any? || #cart_item.errors.any? %>
alert("Not valid.");
<%else%>
$(".cart-text").html("<%= escape_javascript(render 'layouts/cart_text')%>")
$(".cart-container").html("<%= escape_javascript(render 'carts/carts_row')%>")
<%end%>
And destroy in the form has a same destroy.js.erb
<% if #cart.errors.any? || #cart_item.errors.any? %>
alert("Not valid.");
<%else%>
$(".cart-text").html("<%= escape_javascript(render 'layouts/cart_text')%>")
$(".cart-container").html("<%= escape_javascript(render 'carts/carts_row')%>")
<%end%>
The update renders the carts_row.html.erb form properly.
When I destroy an item it renders the page with empty products and a checkout total at the bottom. When I refresh the page the correct amount of products in the shopping cart is displayed and everything is where it should be!
How is the render of update correct but render of destroy incorrect???
My carts_item controller has these two methods for the forms:
def update
#cart = current_cart
# finding cart_items by cart_id
#cart_item = #cart.cart_items.find(params[:id])
# #cart_items.order(:id)
#cart_item.update_attributes(cart_item_params)
#cart_items = #cart.cart_items.order(:id)
# redirect 'cart_show_path'
end
def destroy
#cart = current_cart
#cart_item = #cart.cart_items.find(params[:id])
#cart_item.destroy
#cart_items = #cart.cart_items
end
You're destroying the item from cart, but not removing it from #cart.cart_items
Try doing this
def destroy
#cart = current_cart
#cart_item = #cart.cart_items.find(params[:id])
#Find the index of #cart_item
item_index = #cart.cart_items.index(#cart_item)
#Remove it from #cart.cart_items when its destroyed successfully
if #cart_item.destroy
#cart.cart_items.delete_at(item_index)
end
#cart_items = #cart.cart_items
end
Let me know if it works!
I figured out the problem. The problem was that I was using a <% if #cart_items != nil %> check in my view.
This always returns false, because ActiveRecord will always return an array!!!!!!!!!! Whether it has product objects in the #cart_items object or not.
After I changed this to test for empty arrays with #cart_items.empty?, then the page worked like I wanted it to.
Thanks kumar for your input.

How to perform POST operation in Rails using AJAX

Scenario
I have created a simple application for learning Rails and Bootstrap. What this application does is it allows users to give nicknames to celebrities and like the nicknames as well. You can check it at http://celebnicknames.herokuapp.com
I have got a link_to button for posting likes for a celebrity in my home/index.html.erb as:
<%= link_to home_updatelike_path(id: nickname.id, search: #search ), method: :post, remote: true, class: "update_like btn btn-xs btn3d pull-right" do %>
<i class="glyphicon glyphicon-thumbs-up"></i>
<% end %>
The corresponding code in my home_controller.rb for the post method is:
def updatelike
#like = Like.new(:nickname_id => params[:id], :ip_address => request.remote_ip)
#like.save
respond_to do |format|
format.html { redirect_to root_path("utf8"=>"✓", "search"=>params[:search], "commit"=>"Search") }
format.json { head :no_content }
format.js { render :layout => false }
end
end
The code in my updatelike.js.erb is as:
$('.update_like').bind('ajax:success', function() {
});
Now, what I want to achieve is to submit a like without performing a page reload.
Problem:
Whenever I press the button, the database operation is done, but the change is not reflected in the page unless I reload it. Please guide me through this noob question and also provide links to resources which explain using AJAX with Rails.
Edit
Here is the entire home/index.html.erb
<div class="jumbotron col-md-6 col-md-offset-3">
<h1 class='text-center'>Nicknamer</h1>
</div>
<div class="container">
<div class="row">
<div class="col-sm-8 col-sm-offset-2 bottom50">
<%= form_tag(root_path, :method => "get", id: "search-form", type: "search") do %>
<div class = "form-group" >
<div class = "col-sm-9 " >
<%= text_field_tag :search, params[:search], placeholder: "Name", class: "form-control" %>
</div>
<div class = "col-sm-3" >
<%= submit_tag "Search", class: "btn btn-default btn-block btn-success"%>
</div>
</div>
<% end %>
</div>
</div>
<% #names.each do |name| %>
<div class="col-md-6 col-xs-8 col-md-offset-3 col-xs-offset-2 bottom50">
<!-- ===== vCard Navigation ===== -->
<div class="row w">
<div class="col-md-4">
<% if name.sex == true %>
<%= image_tag("mal.jpg", :alt => "", class: "img-responsive") %>
<% else %>
<%= image_tag("fem.jpg", :alt => "", class: "img-responsive") %>
<% end %>
</div><!-- col-md-4 -->
<!-- ===== vCard Content ===== -->
<div class="col-md-8">
<div class="row w1">
<div class="col-xs-10 col-xs-offset-1">
<h3><%= "#{name.name}" %></h3>
<hr>
<h5>Also known as</h5>
<% name.nicknames.each do |nickname| %>
<div class = "row w2 bottom10">
<% if nickname.name_id == name.id %>
<div class="col-xs-7">
<%= nickname.nickname %>
</div>
<div class="col-xs-3 text-right">
<%= pluralize(nickname.likes.count, 'like') %>
</div>
<div class="col-xs-1">
<%= link_to home_updatelike_path(id: nickname.id, search: #search ), method: :post, remote: true, class: "update_like btn btn-xs btn3d pull-right" do %>
<i class="glyphicon glyphicon-thumbs-up"></i>
<% end %>
</div>
<% end %><!-- if -->
</div><!-- row w2 -->
<% end %><!-- do -->
<div class = "row w3 bottom30">
<%= form_for #addnickname, as: :addnickname, url: {action: "addnickname"} do |f| %>
<div class = "form-group" >
<%= f.hidden_field :name_id, :value => name.id %>
<%= f.hidden_field :search, :value => #search %>
<div class = "col-xs-9">
<%= f.text_field :nickname , :required => true, class: "form-control" %>
</div>
<div class = "col-xs-3">
<%= f.submit "Add", class: "btn btn-default btn-info"%>
</div>
</div>
<% end %>
</div>
</div><!-- col-xs-10 -->
</div><!-- row w1 -->
</div><!-- col-md-8 -->
</div><!-- row w -->
</div><!-- col-lg-6 -->
<% end %>
</div><!-- /.container -->
and this is the entire home_controller.rb
class HomeController < ApplicationController
def index
#addnickname = Nickname.new
if params[:search]
#search = params[:search]
#names = Name.search(params[:search])
else
#names = Name.all
end
end
def addnickname
#addnickname = Nickname.new(:nickname => params[:addnickname][:nickname], :name_id => params[:addnickname][:name_id])
if #addnickname.save
redirect_to root_path("utf8"=>"✓", "search"=>params[:addnickname][:search], "commit"=>"Search")
else
render :new
end
end
def updatelike
#like = Like.new(:nickname_id => params[:id], :ip_address => request.remote_ip)
#like.save
respond_to do |format|
format.html { redirect_to root_path("utf8"=>"✓", "search"=>params[:search], "commit"=>"Search") }
format.json { head :no_content }
format.js { render :layout => false }
end
end
private
def addnickname_params
params.require(:addnickname).permit(:name_id, :nickname, :search)
end
end
Ok, so you need a way to identify the div with the number that needs to change:
<div class="col-xs-3 text-right">
<%= pluralize(nickname.likes.count, 'like') %>
</div>
The easiest way to do this would be to have an id attribute on the div that corresponds to the (unique) database id of the nickname. Rails has a helper method for this called div_for. So you could change the above code to this:
<%= div_for(nickname, class: "col-xs-3 text-right") do %>
<%= pluralize(nickname.likes.count, 'like') %>
<% end %>
That will generate a div with an id like nickname_1 (if this id of the nickname is 1).
Now in your javascript template you can easily target the div that needs to be updated:
$("nickname_#{#like.nickname.id}").html(#like.nickname.likes.count);
The ajax:success binding is unnecessary here since you are rendering a javascript template. In the template you can access instance variables set in the controller - just like you can from an HTML template. The above code is meant to replace the content of the div that contains the likes count with the new count.

Resources