deleting a task from todoapp - ruby-on-rails

Hello can you pls explain me how should I delete my task from a todo app?
My show_html_erb form looks like this:
this is my third day learning ruby i am quite confused i saw the documentation did the same but it just not listening to my commands:(
<%= form_for([#todo_list, #todo_item]) do |f| %>
<div class="input-group mb-4">
<%= f.text_field :description , class:"form-control", placeholder:'Add todo items'%>
<div class="input-group-append">
<%= f.submit 'Add', class:"btn btn-primary input-group-btn"%>
</div>
</div>
<%end%>
<ul class='list-group'>
<% #todo_list.todo_items.each do |todo_item| %>
<% if todo_item.completed?%>
<li class='list-group-item bg-light'>
<div class="d-flex justify-content-between">
<span class="text-muted">
<em> <%= todo_item.description%></em>
</span>
**<%= link_to 'DELETE',todo_list_path(todo_item),method: :delete, class:'btn btn-dark'%>** ------>> **THISSSS**
<%= link_to '#', class:'btn btn-dark' ,data:{reflex: 'click->TodoItem#mark_incomplete',id:todo_item.id} do%>
<i class='fas fa-undo-alt'></i>
<%end%>
</div>
</li>
<%else%>
<li class='list-group-item'>
<div class="d-flex justify-content-between">
<span>
<%= todo_item.description%>
</span>
<%= link_to 'Destroy', todo_list_path(todo_item),
method: :delete,
data: { confirm: 'Are you sure?' } ,class:'btn btn-dark'%> ------>> THIIIISSSSS
<%= link_to '#', class:'btn btn-info',data:{reflex: 'click->TodoItem#mark_complete',id:todo_item.id} do %>
<i class='fas fa-check'></i>
<%end%>
</div>
</li>
<%end%>
<%end%>
</ul>
</div>
what do i give wrong ,( i suppose the path , when i delete )
My todolist controller looks like this:
class TodoListsController < ApplicationController
before_action :set_todo_list, only: [:show, :edit, :update, :destroy]
# GET /todo_lists
# GET /todo_lists.json
def index
#todo_lists = TodoList.all
end
# GET /todo_lists/1
# GET /todo_lists/1.json
def show
#todo_item = TodoItem.new
end
# GET /todo_lists/new
def new
#todo_list = TodoList.new
end
# GET /todo_lists/1/edit
def edit
end
# POST /todo_lists
# POST /todo_lists.json
def create
#todo_list = TodoList.new(todo_list_params)
respond_to do |format|
if #todo_list.save
format.html { redirect_to #todo_list, notice: 'Todo list was successfully created.' }
format.json { render :show, status: :created, location: #todo_list }
else
format.html { render :new }
format.json { render json: #todo_list.errors, status: :unprocessable_entity }
end
end
end
# PATCH/PUT /todo_lists/1
# PATCH/PUT /todo_lists/1.json
def update
respond_to do |format|
if #todo_list.update(todo_list_params)
format.html { redirect_to #todo_list, notice: 'Todo list was successfully updated.' }
format.json { render :show, status: :ok, location: #todo_list }
else
format.html { render :edit }
format.json { render json: #todo_list.errors, status: :unprocessable_entity }
end
end
end
# DELETE /todo_lists/1
# DELETE /todo_lists/1.json
def destroy
#todo_list = TodoList.find(params[:id])
#todo_list.destroy
respond_to do |format|
format.html { redirect_to todo_lists_url, notice: 'Todo list was successfully destroyed.' }
format.json { head :no_content }
end
end
private
# Use callbacks to share common setup or constraints between actions.
def set_todo_list
#todo_list = TodoList.find(params[:id])
end
# Only allow a list of trusted parameters through.
def todo_list_params
params.require(:todo_list).permit(:title)
end
end

The issue is that you are not passing the correct object/path to delete. Try the below code.
<%= link_to 'Destroy', todo_item,
method: :delete,
data: { confirm: 'Are you sure?' } ,class:'btn btn-dark'%>
And I believe the html which you shared above is index.html.erb not show.html.erb

So i found the answer , what i had to do is linking the delete method like that:
<%= link_to 'Destroy', todo_list_todo_item_path(#todo_list,todo_item),
method: :delete,
data: { confirm: 'Are you sure?' } ,class:'btn btn-dark'%>
that fixed my problem ( the reason why is because as you could see in my show.html.erb file that ive used a nested scaffold )

Related

link_to in Rails 7

I am new to Ruby on Rails and I am making a view page showing a table from the database. I want to add a link_to to delete this record. I tried the code written below and nothing worked for me.
The browser keeps refreshing and does nothing.
ruby 3.1.2
Rails 7.0.4
<%= link_to 'Delete', #friend, data: {turbo_method: :delete, turbo_confirm: 'Sure?'}, class: "btn btn-danger" %>
also with this
<%= link_to 'Delete', #friend, method: :delete, data: { confirm: 'Are you sure?' }, class: "btn btn-danger" %>
html.erb code
<p style="color: green"><%= notice %></p>
<%= render #friend %>
<div>
<%= link_to "Edit this friend", edit_friend_path(#friend) %> |
<%= link_to "Back to friends", friends_path %>
<%#= button_to "Destroy this friend", #friend, method: :delete,data: {turbo_confirm: 'Are you sure?'} %>
<%#= button_to "Destroy this friend", #friend, method: :delete,data: {turbo_confirm: 'Are you sure?'} %>
<%= link_to 'Delete', #friend, method: :delete, data: { confirm: 'Are you sure?' }, class: "btn btn-danger" %>
</div>
Controller code
class FriendsController < ApplicationController
before_action :set_friend, only: %i[ show edit update destroy ]
# GET /friends or /friends.json
def index
#friends = Friend.all
end
# GET /friends/1 or /friends/1.json
def show
end
# GET /friends/new
def new
#friend = Friend.new
end
# GET /friends/1/edit
def edit
end
# POST /friends or /friends.json
def create
#friend = Friend.new(friend_params)
respond_to do |format|
if #friend.save
format.html { redirect_to friend_url(#friend), notice: "Friend was successfully created." }
format.json { render :show, status: :created, location: #friend }
else
format.html { render :new, status: :unprocessable_entity }
format.json { render json: #friend.errors, status: :unprocessable_entity }
end
end
end
# PATCH/PUT /friends/1 or /friends/1.json
def update
respond_to do |format|
if #friend.update(friend_params)
format.html { redirect_to friend_url(#friend), notice: "Friend was successfully updated." }
format.json { render :show, status: :ok, location: #friend }
else
format.html { render :edit, status: :unprocessable_entity }
format.json { render json: #friend.errors, status: :unprocessable_entity }
end
end
end
# DELETE /friends/1 or /friends/1.json
def destroy
#friend.destroy
respond_to do |format|
format.html { redirect_to friends_url, notice: "Friend was successfully destroyed." }
format.json { head :no_content }
end
end
private
# Use callbacks to share common setup or constraints between actions.
def set_friend
#friend = Friend.find(params[:id])
end
# Only allow a list of trusted parameters through.
def friend_params
params.require(:friend).permit(:first_name, :last_name, :email, :phone, :twitter)
end
end
Your code should work
<%= link_to 'Delete', #friend,
data: {turbo_method: :delete, turbo_confirm: 'Sure?'}, class: "btn btn-danger" %>
But more reliable to use button_to that generate form tag with button
<%= button_to 'Delete', #friend,
method: :delete, form: {data: {turbo_confirm: 'Sure?'}}, class: "btn btn-danger" %>

NoMethodError in Stocks#show

I'm trying to create a stock market app and I have a button that is breaking my web app. My issue is with this bit of embedded ruby on my
show.html.erb page:
<%= render #stock %>
<div>
<%= link_to "Edit this stock", edit_stock_path(#stock) %> |
<%= link_to "Back to stocks", stocks_path %>
<%= button_to "Delete this stock", #stock, method: :delete %>
</div>
This#stock.destroy line is needed for removing entries for a user. The error rails throws:
Showing C:/stockmarketapp/app/views/stocks/show.html.erb where line #9 raised:
undefined method `destroy' for #<StockQuote::Stock:0x000001f7fc0aa780 #attribution="Data provided for free by IEX (https://iexcloud.io).",
#response_code=200, #avg_total_volume=2261555,
#calculation_price="close", #change=-0.36, #change_percent=-0.00331,
#close=108.41, #close_source="official", #close_time=1654286400058,
#company_name="BlackRock Institutional Trust Company N.A. - iShares Core High Dividend ETF", #currency="USD", #delayed_price=108.4,
#delayed_price_time=1654286390674, #extended_change=0, #extended_change_percent=0, #extended_price=108.41,
#extended_price_time=1654300800004, #high=108.93, #high_source="15
minute delayed price", #high_time=1654286395170, #iex_ask_price=nil,
#iex_ask_size=nil, #iex_bid_price=nil, #iex_bid_size=nil,
#iex_close=108.43, #iex_close_time=1654286330444,
#iex_last_updated=nil, #iex_market_percent=nil, #iex_open=108.81,
#iex_open_time=1654263316934, #iex_realtime_price=nil,
#iex_realtime_size=nil, #iex_volume=nil,
#last_trade_time=1654286394157, #latest_price=108.41,
#latest_source="Close", #latest_time="June 3, 2022",
#latest_update=1654286400058, #latest_volume=876363, #low=108.25,
#low_source="15 minute delayed price", #low_time=1654273215082,
#market_cap=13133871500, #odd_lot_delayed_price=108.395,
#odd_lot_delayed_price_time=1654286390033, #open=108.33,
#open_time=1654263000128, #open_source="official", #pe_ratio=nil,
#previous_close=108.77, #previous_volume=1062893,
#primary_exchange="NYSE ARCA", #symbol="HDV", #volume=876363,
#week52_high=110.91, #week52_low=91.09,
#ytd_change=0.07801100501710605, #is_us_market_open=false>
Extracted source (around line #9):78910
<%= link_to "Edit this stock", edit_stock_path(#stock) %> |
<%= link_to "Back to stocks", stocks_path %>
<%= button_to "Delete this stock", #stock.destroy, method: :delete %>
</div>
Rails.root: C:/stockmarketapp
Application Trace | Framework Trace | Full Trace
app/views/stocks/show.html.erb:9
These are my files related to #stock and #stock.destroy:
class StocksController < ApplicationController
before_action :set_stock, only: %i[ show edit update destroy ]
before_action :correct_user, only: [:show, :edit, :update, :destroy]
before_action :authenticate_user!
#api = StockQuote::Stock.new(api_key: "pk_153e93f4bce64c3d87e7d4d3510153ed")
# GET /stocks or /stocks.json
def index
#stocks = Stock.all
end
# GET /stocks/1 or /stocks/1.json
def show
#stocks = Stock.all
end
# GET /stocks/new
def new
#stock = Stock.new
end
# GET /stocks/1/edit
def edit
end
# POST /stocks or /stocks.json
def create
#stock = Stock.new(stock_params)
respond_to do |format|
if #stock.save
format.html { redirect_to stock_url(#stock), notice: "Stock was successfully created." }
format.json { render :show, status: :created, location: #stock }
else
format.html { render :new, status: :unprocessable_entity }
format.json { render json: #stock.errors, status: :unprocessable_entity }
end
end
end
# PATCH/PUT /stocks/1 or /stocks/1.json
def update
respond_to do |format|
if #stock.update(stock_params)
format.html { redirect_to stock_url(#stock), notice: "Stock was successfully updated." }
format.json { render :show, status: :ok, location: #stock }
else
format.html { render :edit, status: :unprocessable_entity }
format.json { render json: #stock.errors, status: :unprocessable_entity }
end
end
end
# DELETE /stocks/1 or /stocks/1.json
def destroy
#stock.destroy
respond_to do |format|
format.html { redirect_to stocks_url, notice: "Stock was successfully destroyed." }
format.json { head :no_content }
end
end
def correct_user
#ticker = current_user.stocks.find_by(id: params[:id])
redirect_to stocks_path, notice: "Not Autherized to edit this stock" if #ticker.nil?
end
private
# Use callbacks to share common setup or constraints between actions.
def set_stock
#stock = Stock.find(params[:id])
end
# Only allow a list of trusted parameters through.
def stock_params
params.require(:stock).permit(:ticker, :user_id)
end
end
Stock partial:
<% #stock= StockQuote::Stock.quote(stock.ticker) %>
<div id="<%= dom_id stock %>">
<p>
<strong>Ticker:</strong>
<%= #stock.symbol %>
</p>
<p>
<strong>Open</strong>
$<%= #stock.open %>
</p>
<p>
<strong>Price</strong>
$<%= #stock.latest_price %>
</p>
<p>
<strong>Close</strong>
$<%= #stock.close %>
</p>
<p>
<strong>Company Name</strong>
<%= #stock.company_name %>
</p>
<p>
<strong>Primary Exchange</strong>
<%= #stock.primary_exchange %>
</p>
<p>
<strong>Volume</strong>
<%= number_with_delimiter(#stock.volume, :delimiter => ',') %>
</p>
<p>
<strong>Market Cap</strong>
$<%= number_with_delimiter(#stock.market_cap, :delimiter => ',') %>
</p>
</div>
Github Repo: https://github.com/Maikkeru/Stockmarketapp
I assume that am wielding the stock object incorrectly but I don't know where that slipup is occurring. Thanks for your time.

Rails app - extra record displaying

I have an app that allows users to add albums they like to a database. Anyone can then come along and write a review for that album. Pretty simple.
I am running into a problem where an extra record appears to be created for the reviews on each album's show page. Every album, even if it has not ever been reviewed, has an additional, seemingly empty review being displayed when I use .each to display each review in the album show page. I want to get rid of that.
Here is an image of the problem. I have used CSS to highlight reviews in red. As you can see, there is an empty review at the bottom. When I inspect the review in question, it's raty title is "Not reviewed yet!"
Here is my albums_controller:
class AlbumsController < ApplicationController
before_action :set_album, only: [:show, :edit, :update, :destroy]
before_action :authenticate_user!, only: [:edit, :new, :update, :destroy]
def index
#albums = Album.all
if params[:search].nil?
#albums = Album.all.order(year: :desc).order(title: :asc).paginate(:page => params[:page], :per_page => 24)
else
#albums = #albums.where("albums.title || albums.year || albums.artist LIKE ?", "%#{params[:search]}%").order(year: :desc).order(title: :asc).paginate(:page => params[:page], :per_page => 24)
end
end
def show
if #album.reviews.blank?
#average_review = 0
else
#average_review = #album.reviews.average(:rating).round(2)
end
#review = #album.reviews.build
end
def new
#album = Album.new
end
def edit
end
def create
#album = current_user.albums.build(album_params)
respond_to do |format|
if #album.save
format.html { redirect_to #album, notice: 'Album was successfully created.' }
format.json { render :show, status: :created, location: #album }
else
format.html { render :new }
format.json { render json: #album.errors, status: :unprocessable_entity }
end
end
end
def update
respond_to do |format|
if #album.update(album_params)
format.html { redirect_to #album, notice: 'Album was successfully updated.' }
format.json { render :show, status: :ok, location: #album }
else
format.html { render :edit }
format.json { render json: #album.errors, status: :unprocessable_entity }
end
end
end
def destroy
#album.destroy
respond_to do |format|
format.html { redirect_to albums_url, notice: 'Album was successfully destroyed.' }
format.json { head :no_content }
end
end
private
# Use callbacks to share common setup or constraints between actions.
def set_album
#album = Album.find(params[:id])
end
def album_params
params.require(:album).permit(:title, :artist, :year, :cover)
end
end
Here is the album show page, which is where the extra review is being displayed:
<div class="row">
<div class="col-xs-10 col-md-6 col-md-push-3 col-xs-push-1 top bottom">
<%= image_tag #album.cover, class: 'show_image' %>
<h2><%= #album.title %></h2>
<h4><%= #album.artist %></h4>
<h5><%= #album.year %></h5>
<p class="white">Average Review<div class="average-review-rating" data-score=<%= #average_review %>></div></p>
<% if user_signed_in? %>
<% if #album.user_id == current_user.id %>
<%= link_to 'Edit', edit_album_path(#album), class: 'grey' %>
| <%= link_to 'Delete', album_path, method: :delete, data: {confirm: "Are you sure?"}, class: 'grey' %>
<% end %>
<% end %>
<br /><br />
<h4>Reviews</h4>
<% if user_signed_in? %>
<p class="grey">Write a review</p>
<%= form_for [#album, #review] do |r| %>
<div class="form-group">
<div id="rating-form">
<label>Rating</label>
</div>
</div>
<div class="form-group">
<%= r.text_area :comment, class: 'form-control', placeholder: "Write a comment" %>
</div>
<div class="form-group">
<%= r.submit "Create", class: 'btn btn-success' %>
</div>
<% end %>
<% end %>
<br />
<% #album.reviews.each do |r| %>
<div class="red">
<div class="review-rating" data-number="<%= r.rating %>">
</div>
<p class="white"><%= r.comment %></p>
<% if user_signed_in? %>
<% if current_user.id == r.user_id %>
<%= link_to 'Edit', edit_album_review_path(#album, r.id), class: 'grey' %> |
<%= link_to 'Delete', album_review_path(#album, r.id), method: :delete, data: {confirm: "Are you sure?"}, class: 'grey' %>
<% end %>
<% end %>
<br /><br />
</div>
<% end %>
</div>
</div>
<script>
$('.review-rating').raty({
readOnly: true,
score: function() {
return $(this).attr('data-number');
},
path: '/assets/'
});
$('#rating-form').raty({
path: '/assets/',
scoreName: 'review[rating]'
});
$('.average-review-rating').raty({
readOnly: true,
path: '/assets/',
score: function() {
return $(this).attr('data-score')
}
});
</script>
Any help would be very appreciated!
The problem here is on the last line of your show method: #review = #album.reviews.build. This line not only creates a new Review instance and assigns it to #review, but it also adds that instance to the array in #album.reviews. So, in your view, when you iterate over #album.reviews, you will see all of the persisted reviews as well as the one new, not persisted review that was built with build.
The easiest way to fix this would be to add this line in your view:
<% #album.reviews.each do |r| %>
<% next unless r.persisted? %>
Another solution would be to associate the new review with the album, but not on the #album instance. In the controller:
#review = Review.new(album: #album)
I think it could be because of last line in show.
#review = #album.reviews.build
It builds an empty review.

How to show nested database

Hello I have a nested database "processing" which belongst to "shopping_process". However I want somehow to see the messages, which are saved in processing. How can I do that? If I go to http://localhost:3000/processings/index the Error: Couldn't find Processing with 'id'=index appears. Has somebody an idea?
processings_controller.rb
class ProcessingsController < ApplicationController
before_action :set_processing, only: [:show, :edit, :update, :destroy]
# GET /processings
# GET /processings.json
def index
#processings = Processing.all
end
# GET /processings/1
# GET /processings/1.json
def show
end
# GET /processings/new
def new
#processing = Processing.new
end
# GET /processings/1/edit
def edit
end
# POST /processings
# POST /processings.json
def create
#processing = Processing.new(processing_params)
respond_to do |format|
if #processing.save
format.html { redirect_to #processing, notice: 'Processing was successfully created.' }
format.json { render :show, status: :created, location: #processing }
else
format.html { render :new }
format.json { render json: #processing.errors, status: :unprocessable_entity }
end
end
end
# PATCH/PUT /processings/1
# PATCH/PUT /processings/1.json
def update
respond_to do |format|
if #processing.update(processing_params)
format.html { redirect_to #processing, notice: 'Processing was successfully updated.' }
format.json { render :show, status: :ok, location: #processing }
else
format.html { render :edit }
format.json { render json: #processing.errors, status: :unprocessable_entity }
end
end
end
# DELETE /processings/1
# DELETE /processings/1.json
def destroy
#processing.destroy
respond_to do |format|
format.html { redirect_to processings_url, notice: 'Processing was successfully destroyed.' }
format.json { head :no_content }
end
end
private
# Use callbacks to share common setup or constraints between actions.
def set_processing
#processing = Processing.find(params[:id])
end
# Never trust parameters from the scary internet, only allow the white list through.
def processing_params
params.require(:processing).permit(:shopping_process_id, :shopping_list_id, :accepted, :responded, :message)
end
end
view/processings/index.html.erb
<p id="notice"><%= notice %></p>
<h1>Processings</h1>
<table>
<thead>
<tr>
<th colspan="3"></th>
</tr>
</thead>
<tbody>
<% #Processing.all.each do |processing| %>
<tr>
<td><%= link_to 'Show', processing %></td>
<td><%= link_to 'Edit', edit_processing_path(processing) %></td>
<td><%= link_to 'Destroy', processing, method: :delete, data: { confirm: 'Are you sure?' } %></td>
</tr>
<% end %>
</tbody>
</table>
<br>
<%= link_to 'New Processing', new_processing_path %>
models/processing.rb
class Processing < ApplicationRecord
# db associations
belongs_to :shopping_process
belongs_to :shopping_list
# validations
validates :shopping_list, :presence => true
end
Now here comes the code for the database "shopping_processes"
shopping_processes_controller.rb
class ShoppingProcessesController < ApplicationController
load_and_authorize_resource
layout 'shopping_process', only: [:shopper_show, :senior_show]
# GET /shopping_processes/1
# GET /shopping_processes/1.json
def show
end
# POST /shopping_processes
# POST /shopping_processes.json
def create
#shopping_process.status =nil
#shopping_process.processed = nil
puts params.inspect
respond_to do |format|
if #shopping_process.save
format.html { redirect_to #shopping_process, notice: 'Shopping process was successfully created.' }
format.json { render :show, status: :created, location: #shopping_process }
else
format.html { render :new }
format.json { render json: #shopping_process.errors, status: :unprocessable_entity }
end
end
end
# PATCH/PUT /shopping_processes/1
# PATCH/PUT /shopping_processes/1.json
def update
respond_to do |format|
if #shopping_process.update(shopping_process_params)
format.html { redirect_to #shopping_process, notice: 'Shopping process was successfully updated.' }
format.json { render :show, status: :ok, location: #shopping_process }
else
format.html { render :edit }
format.json { render json: #shopping_process.errors, status: :unprocessable_entity }
end
end
end
# DELETE /shopping_processes/1
# DELETE /shopping_processes/1.json
def destroy
#shopping_process.destroy
respond_to do |format|
format.html { redirect_to shopping_processes_url, notice: 'Shopping process was successfully destroyed.' }
format.json { head :no_content }
end
end
def shopper_show
#shopping_process = ShoppingProcess.find(params[:id])
#users = {}
first = true
#shopping_process.shopping_lists.each do |shopping_list|
user = shopping_list.user
#users[user.id] = {color: (first ? 'blue' : 'yellow'), name: user.firstname + ' ' + user.lastname}
first = false
end
end
def senior_show
#shopping_process = ShoppingProcess.find(params[:id])
#shopping_process.shopping_lists.each do |shopping_list|
#if shopping_list.user == current_user
# #shopping_list = shopping_list
#end
#shopping_list = shopping_list
#to show the correct shopping list uncomment the block above and remove the declartion underneath it
end
end
private
# Use callbacks to share common setup or constraints between actions.
def set_shopping_process
#shopping_process = ShoppingProcess.find(params[:id])
end
# Never trust parameters from the scary internet, only allow the white list through.
def shopping_process_params
params.require(:shopping_process).permit(:user_id, :status, :appointed, :processed, :shopping_list_id, processings_attributes: [ :shopping_list_id, :message ])
end
end
views/shopping_processes/form.html.erb
<%= form_for(shopping_process) do |f| %>
<% if shopping_process.errors.any? %>
<div id="error_explanation">
<h2><%= pluralize(shopping_process.errors.count, "error") %> prohibited this shopping_process from being saved:</h2>
<ul>
<% shopping_process.errors.full_messages.each do |message| %>
<li><%= message %></li>
<% end %>
</ul>
</div>
<% end %>
<div class="field">
<%= f.label :appointed %>
<%= f.datetime_select :appointed %>
</div>
<div class="field">
<%= f.label :shopper %>
<%= f.text_field :user_id, value: current_user.id, :readonly => true%>
</div>
<div class="field">
<%= f.label :shopping_list_id %>
<%= f.select :shopping_list_id, ShoppingList.accessible_by(current_ability).map{ |sl| [sl.name, sl.id] } %>
</div>
<!-- SUB FORM FOR NESTED RESOURCE : PROCESSINGS -->
<%= f.fields_for :processings, #shopping_process.processings.build do |ff| %>
<div>
<%= ff.label :Begleiter %>
<%= ff.select :shopping_list_id, ShoppingList.all.map{ |sl| [sl.user.firstname, sl.id]} , {:prompt => true} %>
</div>
<div>
<%= ff.label :message %>
<%= ff.text_field :message%>
</div>
<% end %>
<!-- Submit-->
<div class="actions">
<%= f.submit %>
</div>
<% end %>

Empty child record gets created after creating Parent record (Rails 4)

I have a model called Images with an uploader attached to it (Carrierwave). Images belongs to a model called Listing. After creating a listings I'm redirected to the Images index page to upload files (localhost:3000/listings/1/images)
But for some reason every time I create a listing an image it's created at the same time. There's actually no image present but it displays the "delete" link I have for each image.
<span><%= link_to 'DELETE', listing_image_path(#listing, image.id), data: { confirm: 'Are you sure?' }, :method => :delete, :class => 'delete' %></span>
Any help? Thanks.
Listings Controller
class ListingsController < ApplicationController
before_action :set_listing, only: [:show, :edit, :update, :destroy]
before_filter :authenticate_user!, :except => [:show, :index]
def index
#listings = Listing.order('created_at DESC')
respond_to do |format|
format.html
format.json { render json: #listings }
end
end
def show
end
def new
#listing = Listing.new
#listing.user = current_user
end
def edit
end
def create
#listing = Listing.new(listing_params)
#listing.user = current_user
respond_to do |format|
if #listing.save
format.html { redirect_to listing_images_path(#listing), notice: 'Post was successfully created.' }
else
format.html { render action: 'new' }
format.json { render json: #listing.errors, status: :unprocessable_entity }
end
end
end
def update
respond_to do |format|
if #listing.update(listing_params)
flash[:notice] = 'Deal was successfully updated.'
format.html { redirect_to #listing }
format.json { head :no_content }
else
format.html { render action: 'edit' }
format.json { render json: #listing.errors, status: :unprocessable_entity }
end
end
end
def destroy
#listing.destroy
respond_to do |format|
format.html { redirect_to listings_url }
format.json { head :no_content }
end
end
private
# Use callbacks to share common setup or constraints between actions.
def set_listing
#listing = Listing.friendly.find(params[:id])
end
# Never trust parameters from the scary internet, only allow the white list through.
def listing_params
params.require(:listing).permit(:id, :condition, :description, :nickname, :price, :size, :title, :user_id)
end
end
Listings Form
<%= form_for(#listing, :html => { :class => 'form', :multipart => true }) do |f| %>
<% if #listing.errors.any? %>
<div id="error_explanation">
<h2><%= pluralize(#listing.errors.count, "error") %> prohibited this listing from being saved:</h2>
<ul>
<% #listing.errors.full_messages.each do |msg| %>
<li><%= msg %></li>
<% end %>
</ul>
</div>
<% end %>
<div>
<%= f.label :title %>
<%= f.text_field :title, :required => true %>
</div>
<div>
<%= f.label :price %>
<%= f.text_field :price %>
</div>
<div class="actions">
<%= f.submit 'Submit', :class => 'buyNow' %>
</div>
<% end %>
Images Controller
class ImagesController < ApplicationController
before_action :set_image, only: [:show, :edit, :update, :destroy]
before_filter :load_listing
def index
#images = #listing.images.load
#image = #listing.images.new
end
def new
end
def edit
end
def create
#image = #listing.images.new(image_params)
respond_to do |format|
if #image.save
format.html { redirect_to :back, notice: 'Image was successfully created.' }
format.json { head :no_content }
else
format.html { render action: 'new' }
format.json { render json: #image.errors, status: :unprocessable_entity }
end
end
end
def update
respond_to do |format|
if #image.update(image_params)
format.html { redirect_to (#image.listing), notice: 'Image was successfully updated.' }
format.json { head :no_content }
else
format.html { render action: 'edit' }
format.json { render json: #image.errors, status: :unprocessable_entity }
end
end
end
def destroy
#image = #listing.images.find(params[:id])
#image.destroy
respond_to do |format|
format.html { redirect_to :back }
format.json { head :no_content }
end
end
private
# Use callbacks to share common setup or constraints between actions.
def set_image
#image = Image.find(params[:id])
end
def load_listing
#listing = Listing.find(params[:listing_id])
end
# Never trust parameters from the scary internet, only allow the white list through.
def image_params
params.require(:image).permit(:file, :listing_id)
end
end
Images Index
<div>
<%= form_for [#listing, #image], :html => { :class => 'uploadImages', :multipart => true } do |f| %>
<%= f.hidden_field :listing_id %>
<div>
<%= f.label :file, 'Upload Images' %>
<%= f.file_field :file, multiple: true, name: 'image[file]' %>
</div>
<% end %>
</div>
<div id="progress"></div>
<% if #images.present? %>
<ul class="editGallery">
<% #listing.images.each do |image| %>
<li>
<%= image_tag image.file_url(:list) if image.file? %>
<span><%= link_to 'DELETE', listing_image_path(#listing, image.id), data: { confirm: 'Are you sure?' }, :method => :delete, :class => 'delete' %></span>
</li>
<% end %>
</ul>
<% end %>
The problem is this line:
#image = #listing.images.new
That's building a new image for #listing, so when you call #listing.images.each that new image is included in the images array. Check that the image has actually been saved to the database before constructing a delete link for it.
<% #listing.images.each do |image| %>
<% unless image.new_record? %>
<li>
<%= image_tag image.file_url(:list) if image.file? %>
<span><%= link_to 'DELETE', listing_image_path(#listing, image.id), data: { confirm: 'Are you sure?' }, :method => :delete, :class => 'delete' %></span>
</li>
<% end %>
<% end %>
Take a look at this part of your code:
<% if #images.present? %>
<ul class="editGallery">
<% #listing.images.each do |image| %>
<li>
<%= image_tag image.file_url(:list) if image.file? %>
<span><%= link_to 'DELETE', listing_image_path(#listing, image.id), data: { confirm: 'Are you sure?' }, :method => :delete, :class => 'delete' %></span>
</li>
<% end %>
</ul>
I believe your problem is a combination of this and your images controller index action.
When you hit the index action you create a new record #image = #listing.images.new
Now your #listing.images.each call registers on the object that hasn't been saved.

Resources