Undefined method `add' for Hash - ruby-on-rails

I'm implementing this shopping cart gem, but having problems when I add the item to cart in the controller. I tried executing the code using rails console and it works fine. Not sure why I'm getting this error from the controller.
Error:
products_controller.rb:
helper_method :add_to_cart
def add_to_cart
#cart = session[:active_cart]
#product = Product.find(params[:product_id])
#cart.add(#product, 99.99)
end
routes.rb
post '/add_to_cart/:product_id' => 'products#add_to_cart', :as => 'add_to_cart'
views/products/index.html
<% products.each do |product| %>
<%= button_to "Add to Cart", add_to_cart_path(:product_id => product.id), :method => :post %>
<a href="<%= addresses_path(:brand => product.brand.id, :product_id => product.id) %>" class="list-group-item">
<%= image_tag product.image.url(:square), class: "product-list-group-item" %>
<%= product.name %>
<span class="badge">$<%= number_with_precision(product.price, precision: 2) %></span>
</a>
<% end %>

#cart = session[:active_cart] this is returning a hash and that's why you get the mentioned error when you call this:
#cart.add(#product, 99.99)
Because there is no add method implemented for hash object.
I suggest you to inspect the #cart object in your controller like this:
#cart = session[:active_cart]
puts #cart.inspect
puts #cart.class
and then you will see, it's a hash object and you should be able to extract the required cart object from that hash.
The main issue is to get the correct #cart object from the session. Once you do that, then, it should work :)

Related

Missing required keys: [:id] - Routing to a view for each instance of my model with its unique ID

I'm working on a job board to learn/practice rails. I have a separate view for each job category, and I want the user to be able to click on a particular job posting to access another view with all of the listing's details. I've partially figured out the routing, as I'm able to go to localhost:3000/jobs/listing/7 for example to see the view for the listing of id:7. I'm having a problem linking to the /listing/:id from my job category view, and can only access a view for a specific id by typing it into the address bar. I've been working on this for days and checked out many related questions on here, but can't seem to figure it out. I believe I'm overlooking a simple, but critical detail, since i'm not very experienced with rails.
Here is my job category view:
<div class="cat-banner" id="developer">
<h1>Human Resources Jobs</h1>
<h4 class="listing-count"><%= Job.where(:category => 'Human Resources').count.to_s + ' Listings' %></h4>
</div>
<div class="category-page">
<!-- Full-Stack Developer Jobs -->
<div class="jobs-posted">
<hr class="other-line">
<% if Job.where(:category => 'Human Resources').count > 0 %>
<% #jobs.each do |job| %>
<div class="job">
<% if job.category == "Human Resources" %>
<span class="job-logo"><%= image_tag('salesforce.png', :size => "60x40") %></span>
<span id="line-align"><p class="title"><%= link_to job.title, listing_path(#job) %> </p>
<p class="name"><%= job.name %></p></span>
<% if job.location == "Remote" %>
<span class="remote-tag"><%= job.location.upcase %></span>
<% else %>
<p class="location"><%= job.location %></p>
<% end %>
<p class="kind"><%= job.kind %></p>
<p class="time-stamp"><%= job.created_at.strftime("%A, %B %d %Y") %></p>
<hr class="line">
<% end %>
</div>
<% end %>
<% else %>
<p>There are no human resources jobs at the moment...</p>
<p style="text-decoration: underline;"><%= link_to 'Post a Human Resources Job Here', new_job_path %></p>
<% end %>
</div>
<!-- End of Human Resources Jobs -->
</div>
And my routes.rb file:
Rails.application.routes.draw do
get 'subscribers' => 'subscribers#index'
get 'jobs/remote' => 'jobs#remote'
get 'jobs/listing/:id' => 'jobs#listing', as: 'listing'
get 'jobs/company' => 'jobs#company'
get 'jobs/dev' => 'jobs#dev'
get 'jobs/design' => 'jobs#design'
get 'jobs/marketing' => 'jobs#marketing'
get 'jobs/ai' => 'jobs#ai'
get 'jobs/fullstack' => 'jobs#fullstack'
get 'jobs/frontend' => 'jobs#frontend'
get 'jobs/backend' => 'jobs#backend'
get 'jobs/it' => 'jobs#it'
get 'jobs/software' => 'jobs#software'
get 'jobs/product' => 'jobs#product'
get 'jobs/cloud' => 'jobs#cloud'
get 'jobs/mobile' => 'jobs#mobile'
get 'jobs/database' => 'jobs#database'
get 'jobs/datascience' => 'jobs#datascience'
get 'jobs/blockchain' => 'jobs#blockchain'
get 'jobs/security' => 'jobs#security'
get 'jobs/support' => 'jobs#support'
get 'jobs/network' => 'jobs#network'
get 'jobs/finance' => 'jobs#finance'
get 'jobs/sales' => 'jobs#sales'
get 'jobs/hr' => 'jobs#hr'
get 'jobs/businessdev' => 'jobs#businessdev'
resources :jobs
root 'jobs#index'
get 'jobs/index'
get 'jobs/new'
And part of the Jobs Controller:
class JobsController < ApplicationController
def index
#jobs = Job.all
#subscribers = Subscriber.all
end
def new
#job = Job.new
end
def listing
#job = Job.find(params[:id])
end
def show
#job = Job.find(params[:id])
end
def create
#job = Job.new(params.require(:job).permit(:title, :url, :category, :kind, :location, :description, :name, :summary, :website, :email, :companyDescription, :headquarters ))
if #job.save
redirect_to root_path
else
render "new"
end
respond_to :html, :json
end
I've tried:
<%= link_to job.title, listing_path(#job) %>
<%= link_to job.title, listing_path(#job.id) %>
<%= link_to job.title, listing_path(#job[:id]) %>
<%= link_to job.title, listing_path %>
and other variations that I thought would work from reading StackOverflow
I believe my problem comes from this link_to statement (wrong syntax?), as everything looks alright in my jobs controller and routes file.
I either get:
No route matches {:action=>"listing", :controller=>"jobs", :id=>nil}, missing required keys: [:id],
or
undefined method `id' for nil:NilClass,
or
undefined method `[]' for nil:NilClass
The "missing required keys: [:id]" error is confusing me. I've checked out many resources trying to figure out how to pass the :id but can't solve it.
This is my first post on here and I REALLY appreciate any help and look forward to being knowledgeable enough in the future so I can answer questions too.
rake routes
The view that you are putting as example is using the instance variable #jobs. According with your controller that would be your index action where you don't have #job defined
Note: Notice on that view you are using #jobs and job on your iterator
So I think if you change #job for job that would fix the problem on that view
<%= link_to job.title, listing_path(job) %>
As the error clearly states, your path is expecting a job id but it is not getting one, so inspecting your call for the path, in line:
<span id="line-align"><p class="title"><%= link_to job.title, listing_path(#job) %> </p>
you are passing #job as param to the listing path.
change it to job so it would be:
<span id="line-align"><p class="title"><%= link_to job.title, listing_path(job) %> </p>
For the missing id, you should do:
<%= link_to job.title, listing_path(id: #job) %>
since your id is stored in the variable #job
It seems that the reason this isn't working is because you are not sending the correct argument to your link_to here:
<%= link_to job.title, listing_path(#job) %>
You have to remember that you are iterating through all your #jobs and calling each individual job with the job variable between the | |. You are trying to create a link to each individual job, so the correct link_to should be:
<%= link_to job.title, listing_path(job) %>
Where job is the individual job that the link_to is looking for.

Why is my instance variable always Nil in my Rails view

The problem that I'm having is that any instance variables that I declare in my show function of Charges Controller, appears as nil in the view. If I set an instance variable to a number, it doesn't even appear in the view. My home function works perfectly with instance variables.
This is my Controller with the Home and Show functions:
class ChargesController < ApplicationController
def home
#products = Product.all
end
def show
#product = Product.find_by(id: params[:id])
end
This is my View for the Show function(show.html.erb):
<h1>Product Details</h1>
<h3> <%= #product.name %> </h3>
<h4> <%= #product.price %> </h4>
<h5> <%= #product.description %> </h5>
This is my view for the Home function that contains the button that directs to the show page(home.html.erb)
<h1>Products</h1>
<% #products.each do |product| %>
<br>
<p> <%= product.name %>: $<%= product.price %> </p>
<p> <%= product.description %> </p>
<%= button_to "Product Details", charge_path(product.id), :method => "get" %>
<br>
<%end%>
error message I'm receiving
find_by method returns nil if it does not find the record. So that means the product id(params[:id]) you searching in your Product model is not found.
You can check it manually in the rails console.
Type rails c in your terminal then try the bellow code
Product.find_by(id: the_id_you_want_to_search)
Alternatively you can use find method. It raises an exception when it does not find the record.
def show
#product = Product.find(params[:id])
end
By default ,its always find by id,So kindly use only..
def show
#product = Product.find params[:id]
end
Moreover,you can check in rails console using rails c to verify that the record is present with that id using,for example Product.find 18.
Also check the url which should match with your routes..for example../users/:id for get request Only mapped to users#show action.
Get local copy of your routes using rake routes > path.text and use it as reference
In your home.html.erb try change this
<%= button_to "Product Details", charge_path(product.id), :method => "get" %>
to
<%= link_to "Product Details", charge_path(product.id) %>
Then if it does not work, try to raise the params or the instance in your show method
def show
raise params.inspect
#product = Product.find params[:id]
end
or
def show
#product = Product.find params[:id]
raise #product.inspect
end
Those were some simple ways to check whats happening in your code.

why am i getting undefined method `destroy' for nil:NilClass?

I want to delete something posted by a user. But it's not working the way it normally does despite the fact that I'm mirroring a setup I've used in other apps.
My html:
<div class="section-wrap">
<% #colors.each do |color| %>
<div class="swatch">
<div class="colorblock" style="background-color: <%= color.backgroundcolor %>">
</div>
<h2>PANTONE<sup>2</sup></h2>
<p><%= color.name %></p>
</div>
<div class="controls">
<% if current_user %>
<%= link_to 'Delete', #color, method: :delete %>
<% end %>
</div>
<% end %>
</div>
My controller action:
def destroy
#color.destroy
redirect_to root_path
end
My routes.rb (in which I should not have to specify the delete route):
resources :colors
delete 'colors', to: 'colors#destroy'
And then rake routes gives the route I'd expect:
DELETE /colors/:id(.:format) colors#destroy
But I get undefined method 'destroy' for nil:NilClass
It doesn't look like you've loaded #color, and instance variables are automatically initialized to nil (in contrast with local variables, which raise an exception if you use them without assigning them). Hence, Ruby complains that destroy is undefined on nil. Load #color first:
#color = Color.find(params[:id])
If you're using Color.find_by_id somewhere else in your controller (eg. a before_action), perhaps the ID just doesn't correspond to an existing Color. Unlike find, find_by_id will return nil when the record is missing.
2 issues:
#View
<% #colors.each do |color| %>
<%= link_to 'Delete', color, method: :delete %> #-> #color doesn't exist
<% end %>
#Controller
def destroy
#color = Color.find params[:id]
#color.destroy
redirect_to root_path
end
The above should work for you.

Ruby on rails. Mailboxer, move multiple conversations to trash. Undefined method for #<Array

I am struggling with sending multiple items to the trash folder using checkboxes. I get an
undefined method `move_to_trash' for #<Array:0x007...etc...
move_to_trash works fine on single conversations.
I have a checkbox next to each conversation rendered by a partial, and a button to delete all checked conversations.
Anyway, my conversations controller:
def trash_multiple
#convo = mailbox.conversations.find(params[:trash_id])
#convo.move_to_trash(current_user)
redirect_to mailbox_inbox_path
end
The checkbox which is in a partial, placed next to each conversation:
<%= check_box_tag "trash_id[]", conversation.id %>
The id's are correct.
The form:
<div class="message-cont">
<div class="col-md-8">
<%= form_tag trash_multiple_conversations_path, method: :post do %>
<%= submit_tag "Trash selected" %>
<div class="panel-body">
<% if is_conversation %>
<%= render 'conversations/form' %>
<% else %>
<div class="msg-cnter">
<%= render partial: 'conversations/conversation', collection: messages %>
</div>
<% end %>
<% end %>
</div>
</div>
</div>
And my routes:
resources :conversations do
member do
post :reply
post :trash
post :untrash
end
collection do
get :trashbin
post :empty_trash
post :trash_multiple
end
end
Any hints on getting this to work for an array would be greatly appreciated, thanks.
SOLUTION:
changing controller to:
def trash_multiple
params[:trash_id].each do |element|
#convo = mailbox.conversations.find(element)
#convo.move_to_trash(current_user)
end
redirect_to mailbox_inbox_path
end
as stated by #wpp has fixed this.
move_to_trash works fine on single conversations.
My guess is that you want to invoke the move_to_trash method on each element of the array:
array.each do |element|
element.move_to_trash
end
or shorter:
array.map(&:move_to_trash)
Try this
#convo.each {|c| c.move_to_trash(current_user) }

How an action call works in Rails

I have the following action method:
class CommandsController < ApplicationController
.
.
.
def usersList
#command = Command.find_by(id: params[:id])
#users_list = #command.user_commands.paginate(page: params[:page], per_page: 10)
end
end
The following view: users_list.html.erb
<% provide(:title, "Command list") %>
<h1>Lista Utenti per <%= #command.content %></h1>
<%= will_paginate #users_list %>
<ul class="users">
<% #users_list.each do |user| %>
<li><%= user.name.capitalize %>, <%= user.email %></li>
<% end %>
</ul>
And in the routes.rb
get 'commands/:id/usersList' => 'commands#users_list', as: :list
Now I don't understand why going to lochalhost:3000/commands/1/usersList I receive the following error:
undefined method `content' for nil:NilClass
refered to line <h1>Lista Utenti per <%= #command.content %></h1>
Why does it do so? When I call an action, before it renders the page and then after it executes the code inside the method?
I resolved the problem by changing the names: usersList --> userslist and then users_list.html.erb --->userslist.html.erb and in the routes.rb ----> get 'commands/:id/userslist' => 'commands#userslist', as: :list
Then I don't understand the naming convention...if I declare an action usersList how should I rename the related view?
You should change your action name to users_list.

Resources