I'm a ruby on rails noob having some trouble deleting a resource with a form_for.
I'm trying to create a wish-list for products where users can add multiple instances of the same product to their list. Rather than create a unique data-base entry for each product on the list (regardless of whether the same product is already on the list), I've included a counter column, 'row,' which increases as the user adds multiples of the same product to his or her wish list. By the same logic, I want the delete action to first decrease this counter until it reaches 0, and then remove the item from the data-base.
Here's what I've got:
The error message:
No route matches [DELETE] "/wish"
Routes
Routes match in priority from top to bottom
wishes_path GET /wishes(.:format) wishes#index
POST /wishes(.:format) wishes#create
new_wish_path GET /wishes/new(.:format) wishes#new
edit_wish_path GET /wishes/:id/edit(.:format) wishes#edit
wish_path GET /wishes/:id(.:format) wishes#show
PATCH /wishes/:id(.:format) wishes#update
PUT /wishes/:id(.:format) wishes#update
DELETE /wishes/:id(.:format) wishes#destroy
wishes/index.html.erb
<div class="wishes_body">
<h2>Your Wish-List</h2>
<table>
<thead>
<tr>
<th class="field-label col-md-2 active">
<label>Name</label>
</th>
<th class="col-md-3">Description</th>
<th class="col-md-1">Amount</th>
<th class="col-md-1">Number</th>
<th class="col-md-2">Total</th>
<th colspan="3" class="col-md-3">Remove</th>
</tr>
</thead>
<tbody>
<% #wishes.all.each do |w| %>
<%= render partial: 'wish', object: w %>
<% end %>
</tbody>
</table>
</div>
_wish.html.erb
<tr>
<td class="field-label col-md-2 active">
<label><%= wish.product.name %></label>
</td>
<td class="col-md-3"><%= wish.product.description %></td>
<td class="col-md-1"><%= '%.2f' % (wish.product.amount/100.00) %></td>
<td class="col-md-1"><%= wish.total %></td>
<td class="col-md-2"><%= '%.2f' % ((wish.product.amount/100.00) * wish.total) %></td>
<%= form for(wish_path(wish), :html => { method: 'delete' }) do %>
<td><%= f.label(:i, "How many:") %></td>
<td><%= f.number_field(:i) %></td>
<td><%= f.submit :value => "Remove" %></td>
<% end %>
</tr>
controllers/wishes.controller.rb
class WishesController < ApplicationController
def index
#wishes = Wish.where("user_id = ?", "#{current_user.id}")
end
def show
#user = current_user
#products = #user.wish_list.products.order("created_at DESC")
end
def create
#product = Product.find(params[:product_id])
if Wish.where(user_id: "#{current_user.id}", product_id: "#{#product.id}").exists?
#wish = Wish.where(user_id: "#{current_user.id}", product_id: "#{#product.id}").first
#wish.total += 1
else
#wish = #product.wishes.new
#wish.user = current_user
#wish.total = 1
end
respond_to do |format|
if #wish.save
format.html { redirect_to action: "index", notice: 'You have added <%= #wish.product %> to your wish list.' }
format.json { render :index, status: :created }
else
format.html { redirect_to #product, alert: 'Wish was not created succesfully.' }
format.json { render json: #wish.errors, status: :unprocessable_entity }
end
end
end
def destroy
case i = params[:i]
when #wish.total > i
#wish.total -= i
respond_to do |format|
format.html { redirect_to action: 'index', notice: 'You removed the item from your wish-list.' }
format.json { head :no_content }
end
when #wish.total == i
#wish.destroy
respond_to do |format|
format.html { redirect_to action: 'index', notice: 'You removed the item from your wish-list.' }
format.json { head :no_content }
end
else
format.html { redirect_to action: 'index', alert: 'You cannot remove more items than you have on your list.' }
format.json { head :no_content }
end
end
end
config.routes.rb
Rails.application.routes.draw do
root 'static_pages#index'
get 'static_pages/about'
get 'static_pages/contact'
get 'static_pages/landing_page'
post 'static_pages/thank_you'
resources :orders, only: [:index, :show, :new, :create]
resources :users
devise_for :users, :controllers => { :registrations => "my_devise/registrations" },
:path => '', :path_names => {:sign_in => 'login', :sign_out => 'logout', :sign_up => 'register'}
resources :wishes
resources :products do
resources :comments
end
resources :payments
end
You should implement this using form_tag instead of form_for, because you're not going to use #wish resource in your form:
<%= form_tag wish_url(wish), method: :delete do %>
etc.
Related
I have a method called calculation_of_total_cost in model Tippy
It's running into problems being called in index.html.erb via tippies views directory.
This is the error I receive: undefined method*' for nil:NilClass`
I have googled it, and now understand that it is the result of the one of the variables being nil.
How do I resolve this, i.e, how do I make the method work in index.html.erb? This is index view that I am calling it from, so I need an instance method, not class, right?
Also, addendum: this same method works fine in show.html.erb
show.html.erb
<br/><br/>
<h1 class="text-center">Your Total Cost</h1>
<br/><br />
<table class="table table-striped">
<tr>
<td>
Cost of Your Meal:
</td>
<td>
<%= humanized_money_with_symbol #tippy.cost %>
</td>
</tr>
<tr>
<td>
Tip You Picked:
</td>
<td>
<%= number_to_percentage(#tippy.tip * 100, format: "%n%", precision: 0) %>
</td>
</tr>
<tr>
<td>
The Total Cost:
</td>
<td>
<%= humanized_money_with_symbol #tippy.calculation_of_total_cost %>
</td>
</tr>
</table>
<%= link_to 'New Tippy', new_tippy_path %>
<%= link_to "Index", tippies_path %>
Here is the Tippy model:
class Tippy < ApplicationRecord
validates :tip, presence: true
validates :cost, presence: true
#monetize :tip_cents
monetize :cost_cents, :numericality => {:greater_than => 0}
TIP_CHOICES = { "10%" => ".10", "20%" => ".20", "30%" => ".30", "40%" => ".40", "50%" => ".50",
"60%" => ".60", "70%" => ".70", "80%" => ".80", "90%" => ".90" }
def calculation_of_total_cost
cost + (tip * cost)
end
end
Here is the index.html.erb file
<p id="notice"><%= notice %></p>
<h1>Tippies</h1>
<table>
<thead>
<tr>
<th>Tip</th>
<th>Cost</th>
<th>Total</th>
<th colspan="3"></th>
</tr>
</thead>
<tbody>
<% #tippies.each do |tippy| %>
<tr>
<td><%= tippy.tip %></td>
<td><%= tippy.cost %></td>
<td><%= tippy.calculation_of_total_cost %></td>
<td><%= link_to 'Show', tippy %></td>
<td><%= link_to 'Edit', edit_tippy_path(tippy) %></td>
<td><%= link_to 'Destroy', tippy, method: :delete, data: { confirm: 'Are you sure?' } %></td>
</tr>
<% end %>
</tbody>
</table>
<br>
<%= link_to 'New Tippy', new_tippy_path %>
Tippy Controller
class TippiesController < ApplicationController
#before_action :set_tippy, only: [:show, :edit, :update, :destroy]
# GET /tippies
# GET /tippies.json
def index
#tippies = Tippy.all
end
# GET /tippies/1
# GET /tippies/1.json
def show
##calculation_of_total_cost
end
# GET /tippies/new
def new
#tippy = Tippy.new
end
# GET /tippies/1/edit
def edit
end
# POST /tippies
# POST /tippies.json
def create
#tippy = Tippy.new(tippy_params)
respond_to do |format|
if #tippy.save
format.html { redirect_to #tippy, notice: 'Tippy was successfully created.' }
format.json { render :show, status: :created, location: #tippy }
else
format.html { render :new }
format.json { render json: #tippy.errors, status: :unprocessable_entity }
end
end
end
# PATCH/PUT /tippies/1
# PATCH/PUT /tippies/1.json
def update
respond_to do |format|
if #tippy.update(tippy_params)
format.html { redirect_to #tippy, notice: 'Tippy was successfully updated.' }
format.json { render :show, status: :ok, location: #tippy }
else
format.html { render :edit }
format.json { render json: #tippy.errors, status: :unprocessable_entity }
end
end
end
# DELETE /tippies/1
# DELETE /tippies/1.json
def destroy
#tippy.destroy
respond_to do |format|
format.html { redirect_to tippies_url, notice: 'Tippy was successfully destroyed.' }
format.json { head :no_content }
end
end
private
# Use callbacks to share common setup or constraints between actions.
def set_tippy
#tippy = Tippy.find(params[:id])
end
# Never trust parameters from the scary internet, only allow the white list through.
def tippy_params
params.require(:tippy).permit(:tip, :cost)
end
end
To solve this problem you need to set a binding.pry or a breakpoint at this line of index.html.erb, so that we can understand in the loop you are executing why tippy is getting value of nil.
You need to install pry gem.
Please also share the values of #tippies and the details of the other variable in the loop that fails, because tippy=nil.
An alternative for pry is just printing the value of the variable in the log with puts tippy.calculation_of_total_cost.
Right now I am guess is that #tippies which includes all #tippy in your tippies table, could have one field that has calculation of total cost = nil. To verifiy this you should check with the debug the value of tippy and of tippy.calculation_of_total_cost in the index.html.erb view.
<% #tippies.each do |tippy| %>
<tr>
<% binding.pry %>
<td><%= tippy.tip %></td>
<td><%= tippy.cost %></td>
<td><%= tippy.calculation_of_total_cost %></td>
<td><%= link_to 'Show', tippy %></td>
<td><%= link_to 'Edit', edit_tippy_path(tippy) %></td>
<td><%= link_to 'Destroy', tippy, method: :delete, data: { confirm: 'Are you sure?' } %></td>
</tr>
<% end %>
also it is a good idea to inspect show.html.erb as there it is working.
def calculation_of_total_cost
cost + (tip * cost)
end
I am new to ruby on rails and any help would be much appreciated. i am unsure on how to go about resolving my error. I think i am meant to do more in my controller but i am confused as this is a nested resources challenge i am facing
i am trying to view the details of an advert (show) in my views, but when i click the link show i get the below error:
No route matches {:action=>"new", :controller=>"adverts", :userr_id=>nil} missing required keys: [:userr_id]
ActionController::UrlGenerationError (No route matches {:action=>"new", :controller=>"adverts", :userr_id=>nil} missing required keys: [:userr_id]):
app/views/shared/_header_recruiter.html.erb:6:in `_app_views_shared__header_recruiter_html_erb___2254802171992378619_70258749378740'
app/views/adverts/show.html.erb:1:in `_app_views_adverts_show_html_erb___3448815807687044417_70258749644120'
app/controllers/adverts_controller.rb:26:in `show'
i have adverts nested under userr (recruiters) - routes.rb
Rails.application.routes.draw do
devise_for :userrs
resources :userrs do
resources :adverts
end
devise_for :userjs
root 'static_pages#homepg'
get 'search', to: 'static_pages#searchpg'
end
i created a static page called searching - static_pages_controller.rb
class StaticPagesController < ApplicationController
respond_to :html, :xml, :json
def searchpg
#adverts = Advert.all
end
end
i have the below codings in my searching view file - searchpg.html.erb
<div>
<table>
<thead>
<tr>
<th>Published</th>
<th>Title</th>
<th>Content</th>
<th>City</th>
<th></th>
</tr>
</thead>
<tbody>
<% #adverts.each do |advert| %>
<tr>
<td><%= advert.created_at.strftime("%B %d, %Y") %></td>
<td><%= link_to advert.title, '#' %></td>
<td><%= advert.content %></td>
<td><%= advert.city %></td>
<td><%= link_to 'Show', userr_advert_path(advert.userr, advert) %></td>
</tr>
<% end %>
</tbody>
</table>
</div>
theses are my routes:
userr_adverts GET /userrs/:userr_id/adverts(.:format) adverts#index
POST /userrs/:userr_id/adverts(.:format) adverts#create
new_userr_advert GET /userrs/:userr_id/adverts/new(.:format) adverts#new
edit_userr_advert GET /userrs/:userr_id/adverts/:id/edit(.:format) adverts#edit
userr_advert GET /userrs/:userr_id/adverts/:id(.:format) adverts#show
PATCH /userrs/:userr_id/adverts/:id(.:format) adverts#update
PUT /userrs/:userr_id/adverts/:id(.:format) adverts#update
DELETE /userrs/:userr_id/adverts/:id(.:format) adverts#destroy
i already have an adverts controller:
class AdvertsController < ApplicationController
respond_to :html, :xml, :json
before_action :set_advert, only: [:show, :edit, :update, :destroy]
def index
#userr = Userr.find(params[:userr_id])
#adverts = #userr.adverts.order("created_at DESC")
respond_with(#adverts)
end
def show
#userr = Userr.find(params[:userr_id])
#advert = #userr.adverts.find(params[:id])
respond_with(#advert)
end
def new
#userr = Userr.find(params[:userr_id])
#advert = #userr.adverts.build
respond_with(#advert)
end
def edit
#userr = Userr.find(params[:userr_id])
#advert = #userr.adverts.find(params[:id])
end
def create
#userr = Userr.find(params[:userr_id])
#advert = #userr.adverts.create(advert_params)
respond_to do |format|
if #advert.save
format.html { redirect_to([#advert.userr, #advert], notice: 'Advert was successfully created.') }
format.json { render json: #advert, status: :created, location: #advert }
else
format.html { render action: "new" }
format.json { render json: #advert.errors, status: :unprocessable_entity }
end
end
end
def update
#userr = Userr.find(params[:userr_id])
#advert = #userr.adverts.find(params[:id])
respond_to do |format|
if #advert.update_attributes(advert_params)
format.html { redirect_to([#advert.userr, #advert], notice: 'Advert was successfully updated.') }
format.json { head :no_content }
else
format.html { render action: "edit" }
format.json { render json: #advert.errors, status: :unprocessable_entity }
end
end
end
def destroy
#userr = Userr.find(params[:userr_id])
#advert = #userr.adverts.find(params[:id])
#advert.destroy
respond_to do |format|
#1st argument reference the path /recruiters/:recruiter_id/adverts/
format.html { redirect_to(recruiter_adverts_url) }
format.json { head :no_content }
end
end
private
def set_advert
#advert = Advert.find(params[:id])
end
def advert_params
params.require(:advert).permit(:title, :content, :category_jobtype_id, :category_positiontype_id, :salarystart, :salaryend, :category_country_id, :city, :town, :postcode, :category_editorialapproval_id, :category_applicationrequest_id, :category_advert_id, :userr_id )
end
end
The error notifies that There is no userr_id in the url which means that advert object does not have userr object or you may forgot to enter userr_id while manually typing the url.
It seems like you don't have a advert.userr object. The easiest way to check that is to print it.
So temporarily, remove your link and print the userr
<% #adverts.each do |advert| %>
<tr>
<td><%= advert.created_at.strftime("%B %d, %Y") %></td>
<td><%= link_to advert.title, '#' %></td>
<td><%= advert.content %></td>
<td><%= advert.city %></td>
<td><%#= link_to 'Show', userr_advert_path(advert.userr, advert) %></td>
<td><%= advert.userr.inspect %></td>
</tr>
<% end %>
So if you can;t see anything, that means your relations between userr and advert is not setup correctly.
The author built a UPS scaffold and rails created the model as up instead of ups. I've hacked some solutions in to make it work, but I can't get the create method to work when called from the new form. Rails calls the index function and no new object is created.
ups_controller.rb
def create
#up = Ups.new(params[:up])
respond_to do |format|
if #up.save
format.html { redirect_to #up, notice: 'Up was successfully created.' }
format.json { render json: #up, status: :created, location: #up }
else
format.html { render action: "new" }
format.json { render json: #up.errors, status: :unprocessable_entity }
end
end
end
def new
#up = Ups.new
respond_to do |format|
format.html # new.html.erb
format.json { render json: #up }
end
end
ups/form.html.erb
<%= form_for(#up) do |f| %>
<table class="table table-striped table-bordered">
<tr>
<th>name</th>
<td><%= f.text_field :name %></td>
</tr>
<tr>
<th>attr</th>
<td><%= f.select :attr_id, options_from_collection_for_select(Attr.order(:name).where(:major => true).all, "id", "name", #up.attr_id) %></td>
</tr>
<tr>
<th>Action</th>
<td><%= f.submit "Submit New UPS" %></td>
</tr>
</table>
<% end %>
routes.rb
resources :ups
match 'ups/create' => 'ups#create'
match 'ups/index' => 'ups#index'
match 'pdus/link_all_ups' => 'pdus#link_all_ups'
Here is the button that calls the new method of the ups_controller:
<%= link_to 'Enter New UPS', new_ups_path, :class => "btn btn-success pull-right" %>
rake routes
ups GET /ups(.:format) ups#index
POST /ups(.:format) ups#create
new_up GET /ups/new(.:format) ups#new
edit_up GET /ups/:id/edit(.:format) ups#edit
up GET /ups/:id(.:format) ups#show
PUT /ups/:id(.:format) ups#update
DELETE /ups/:id(.:format) ups#destroy
ups_index /ups/index(.:format) ups#index
Thanks for any advice.
You also want to make sure rails is sending a Post request like this:
<%= form_for #up, :url=> ups_path, :method => :post do |f| %>
My guess is that your url is correct but rails in sending it as a get instead of a post. As you can see from your routes, the index and create action both have the same url and the only difference is the get/post.
ups GET /ups(.:format) ups#index
POST /ups(.:format) ups#create
I am implementing an application in which i want to change the settings of the application.
While doing so I am getting an error
no routes matches {:action=>"show", :controller=>"settings", format=>"nil"}
while clicking on the open new settings tab.
my index.html is as follows:-
<h1>Listing settings</h1>
<table class="table table-striped table-bordered">
<tr>
<th>ID</th>
<th>Name</th>
<th>Value</th>
<th>Description</th>
<th>Edit</th>
<th>Delete</th>
</tr>
<% #settings.each do |c| %>
<tr>
<td><%= c.id %> </td>
<td><%= c.name %> </td>
<td><%= c.value %> </td>
<td><%= c.description %> </td>
<td><%= link_to 'Edit', {:action => 'edit', :id => c.id} %> </td>
<td><%= link_to 'Delete', {:action => 'delete', :id => c.id},
:data => { :confirm => "Are you sure you want to delete this value?" } %></td>
</tr>
<% end %>
</table>
<br />
<%= link_to 'New Setting', {:action => 'new'} %>
My settings controller is as follows:-
class SettingsController < ApplicationController
# GET /setting
# GET /setting.json
def index
#settings = Setting.all
respond_to do |format|
format.html # index.html.erb
format.json { render json: #settings }
end
end
# GET /setting/1
# GET /setting/1.json
def show
#setting = Setting.find(params[:id])
respond_to do |format|
format.html # show.html.erb
format.json { render json: #setting }
end
end
# GET /setting/new
# GET /setting/new.json
def new
#setting = Setting.new
respond_to do |format|
format.html # new.html.erb
format.json { render json: #setting }
end
end
# GET /setting/1/edit
def edit
#setting = Setting.find(params[:id])
end
# POST /setting
# POST /setting.json
def create
#setting = Setting.new(params[:setting])
respond_to do |format|
if #setting.save
format.html { redirect_to #setting, notice: 'Setting was successfully created.' }
format.json { render json: #setting, status: :created, location: #setting }
else
format.html { render action: "new" }
format.json { render json: #setting.errors, status: :unprocessable_entity }
end
end
end
# PUT /setting/1
# PUT /setting/1.json
def update
#setting = Setting.find(params[:id])
respond_to do |format|
if #setting.update_attributes(params[:setting])
format.html { redirect_to #setting, notice: 'Setting was successfully updated.' }
format.json { head :no_content }
else
format.html { render action: "edit" }
format.json { render json: #setting.errors, status: :unprocessable_entity }
end
end
end
# DELETE /setting/1
# DELETE /setting/1.json
def delete
#setting = Setting.find(params[:id])
#setting.deleted = 1
#setting.save
respond_to do |format|
format.html { redirect_to settings_url }
format.json { render :json => { :success => true } }
end
end
end
My new.html is as follows:-
<h1>New settings</h1>
<%= form_for #setting do |f| %>
<% if #setting.errors.any? %>
<div id="errorExplanation">
<h2><%= pluralize(#setting.errors.count, "error") %> prohibited this setting from being saved:</h2>
<ul>
<% #setting.errors.full_messages.each do |msg| %>
<li><%= msg %></li>
<% end %>
</ul>
</div>
<% end %>
Id: <%= f.text_field :id %><br>
Name: <%= f.text_field :name %><br>
Values: <%= f.text_field :value %><br>
Description: <%= f.text_field :description %><br>
<% end %>
<%= link_to 'Back', settings_path %>
My routes.rb is as follows:-
Lms::Application.routes.draw do
resources :books do
member do
post 'add'
post 'remove'
end
collection do
get 'add'
get 'list' => "books#index"
post 'get_books'
get 'get_books'
end
end
resources :books
resources :book_transactions
resources :book_issues
resources :book_holds
resources :categories
resources :users
resources :admins
resources :library_locations
resources :lov_values
resources :loan_fines
resources :lov_names
resources :loans_fines do
member do
post 'add'
post 'remove'
end
collection do
get 'add'
get 'list'
post 'get_loans_fines'
get 'get_loans_fines'
end
end
resources :settings do
member do
post 'add'
post 'remove'
end
collection do
get 'add'
get 'list'
post 'get_settings'
get 'get_settings'
end
end
root :to => 'books#index'
match ':controller(/:action(/:id))(.:format)'
The strange part is that when i click on new action it is going/redirecting to the show action..I am a bit confused why this is happening..
Can some one help me with this..
To check your routes you can run
rake routes
to inspect if you have the routes defined correctly. Also I would suggest to use
<%= link_to "New Setting", new_setting_pah %>
For your routes definition you are not defining the routes for other methods than add or remove.
I advise you to read this great tutorial on rails routes
i want to update viewcount value in Posts table when user click the "like" link in post........
model
class Post < ActiveRecord::Base
belongs_to :user
has_many :answers
attr_accessible :acceptedanswerid, :body, :userid, :tag, :title, :viewcount, :vote, :anscount
validates_presence_of :title ,:body ,:tag
scope :unanswered, where(:anscount => 0)
scope :byvote, where(:vote=>maximum("vote"))
end
controller
post_controller.rb
class PostController < ApplicationController
def index
#post=Post.new
#answer=Answer.new
#anscomment=Anscomment.new
#posts=(Post.all).reverse
#posts1=Post.all(:limit => 5 ,:order => "id desc")
#unanswered = Post.unanswered
#byvote=Post.byvote
#fid=params[:fid]
session[:flag]=nil
fid=params[:fid]
session[:flag]=fid
end
#def new
# #post=Post.new
# end
def create
# #post=Post.new(params[:post])
#post=Post.new(params[:post])
respond_to do |format|
if #post.save
#if (session[:flag!=nil])
#session[:flag]=1
#end
format.html { redirect_to :controller=>"post" ,:action=>"index" }
format.json { render json: #post, status: :created, location: #post }
#redirect_to :controller=>"post" ,:action=>"index"
else
#session[:flag]=3
format.html { redirect_to :controller=>"home" ,:action=>"index" }
format.json { render json: #post, status: :created, location: #post }
#redirect_to :controller=>"post" ,:action=>"index"
end
end
end
def show
id=params[:id]
#post = Post.find(params[:id])
respond_to do |format|
format.html # show.html.erb
format.json { render json: #post }
end
end
def vote
vcount = User.find(params[:id])
vcount.update_attribute(:viewcount, vcount.viewcount + 4)
end
end
view
views/post/show.html.erb
<table align=center width="60%" bordercolor="black" >
<tr>
<td align="center">
<h2>
<%=#post.title%>
</h2>
</td>
</tr>
<tr>
<td align="center" width="60">
<h3><%=#post.body%></h3>
</td>
</tr>
<tr>
<td align="center">
This Post comes under:<%=#post.tag%>
</td>
</tr>
<tr >
<td align="right">
<%id=#post.userid %>
<%if id==nil %>
<%id='15'%>
<%end%>
<%#user=User.find(id)%>
posted by:<%=#user.fullname%> <p>on <%=#post.created_at%></p>
<%id=nil%>
<h1 align="left"><%=#post.answers.count%></h1>
<!--<%Post.increment_counter(:viewcount,#post.id) %>-->
<%= link_to "like", {:controller => "post", :action => "vote", :id => #post.id } %>
</td>
</tr>
</table>
when i click the "like" the like link i am getting an error like-----Couldn't find Post with id=vote
*application trace: *
app/controllers/post_controller.rb:42:in `show'
plz help me finding the error.......
i think it happens because in your routes.rb file /post/:id is before :controller/:action:/:id, so u have to create named route for this action.
resources :posts do
get 'vote', on: member
end
and the use path helper vote_post_path(post)
http://guides.rubyonrails.org/routing.html