I am using a carrierwave and dropzonejs. Everything seems fine however, when I try to press to remove picture button, even though it removes from the database, picture stays on the container.
Here how it looks like;
When I click to remove file link all of them, it becomes;
So I clicked all the remove file buttons, they are removed from the database however, stays on the page. I think it is because of the js code (end part) below,
<script type="text/javascript">
$(document).ready(function(){
// disable auto discover
Dropzone.autoDiscover = false;
// grap our upload form by its id
$("#picture-dropzone").dropzone({
// restrict image size to a maximum 5MB
maxFilesize: 5,
// changed the passed param to one accepted by
// our rails app
paramName: "picture[image]",
acceptedFiles: "image/*",
// show remove links on each image upload
addRemoveLinks: true,
// if the upload was successful
success: function(file, response){
// find the remove button link of the uploaded file and give it an id
// based of the fileID response from the server
$(file.previewTemplate).find('.dz-remove').attr('id', response.fileID);
$(file.previewTemplate).find('.dz-remove').attr('boat_id', response.boatID);
// add the dz-success class (the green tick sign)
$(file.previewElement).addClass("dz-success");
},
//when the remove button is clicked
removedfile: function(file){
//location.reload();
//removeFile(file); *******THIS DOES NOT WORK*******
// grap the id of the uploaded file we set earlier
var id = $(file.previewTemplate).find('.dz-remove').attr('id');
var boat_id = $(file.previewTemplate).find('.dz-remove').attr('boat_id');
// // make a DELETE ajax request to delete the file
$.ajax({
type: 'DELETE',
url: '/boats/' + boat_id + '/pictures/' + id,
success: function(file){
}
});
}
});
});
</script>
pictures controller if anyone wonders,
class PicturesController < ApplicationController
before_action :logged_in_user
before_filter :load_parent
def new
#picture = #boat.pictures.new
#pictures = #boat.pictures.all
end
def show
#picture = #boat.pictures.find(params[:id])
end
def create
#picture = #boat.pictures.new(picture_params)
if #picture.save
render json: { message: "success", fileID: #picture.id, boatID: #boat.id }, :status => 200
else
render json: { error: #picture.errors.full_messages.join(',')}, :status => 400
end
end
def edit
#picture = Picture.find(params[:id])
end
def update
#picture = #boat.pictures.find(params[:id])
if #picture.update_attributes(picture_params)
flash[:notice] = "Successfully updated picture."
render 'index'
else
render 'edit'
end
end
def destroy
#picture = #boat.pictures.find(params[:id])
if #picture.destroy
render json: { message: "File deleted from server" }
#redirect_to new_boat_picture_path(#boat, #picture)
flash[:notice] = "Successfully destroyed picture."
else
render json: { message: #picture.errors.full_messages.join(',') }
end
#flash[:notice] = "Successfully destroyed picture."
#redirect_to new_boat_picture_path(#boat, #picture)
#redirect_to boat_pictures_path(#boat)
#redirect_to boat_path(#boat)
end
private
def picture_params
params.require(:picture).permit(:name, :image)
end
def load_parent
#boat = Boat.find(params[:boat_id])
end
end
write below line in your delete ajax call success method
$(file.previewTemplate).fadeOut()
Related
I have delete action in my controller, this is the code in pickups_controller.rb
def delete
#pickup = Pickup.find(params[:id])
if !#pickup.nil?
#pickup.destroy
render json: { success_message: "Success!, Pickup is deleted." }, status: :ok
end
end
I call the delete action using javascript json by pressing a button using assets/javascripts/pickups.js
document.addEventListener("DOMContentLoaded", function(event) {
var xhttp = new XMLHttpRequest();
// delete the pickup you choose
$('.removepickup.btn.btn-primary').on('click', function() {
var pickup_div = $(this).parents('.removepickupparent');
var pickup_id = pickup_div.attr('id');
var x = "../deletepickup?id=" + pickup_id;
$.ajax({
type: "POST",
url: x,
success: function(data) {
var success = data.success_message;
$(".successr"+ pickup_id).text(success).show(0).delay(1000).hide(0);
setTimeout(function () {
location.reload();
}, 1000);
},
error: function (xhr, ajaxOptions, thrownError){
if(xhr.status==404) {
$(".errorl"+ pickup_id).text("Fail!, pickup Is Already Deleted Before").show(0).delay(1000).hide(0);
setTimeout(function () {
location.reload();
}, 2000);
}
}
});
});
// when pressing on this button, it redirects you to create pickup page
$('.addpickup.btn.btn-primary').on('click', function() {
var success = "Redirecting to add pickup Page"
$(".successp").text(success).show(0).delay(2000).hide(0);
setTimeout(function () {
$(location).attr('href', '../createpickup');
}, 2000);
});
});
the function is working great, but when adding 4 lines extra code inside the delete action, it doesn't work, here's the code after adding 4 lines of extra code inside my delete action, and the action is not working.
def delete
#pickup = Pickup.find(params[:id])
if !#pickup.nil?
# the start of the extra code
#trip = Trip.find(#pickup.trip_id)
if !#trip.nil?
#trip.seatsno = #trip.seatsno + 1
#trip.save
end
# the end of the extra code
#pickup.destroy
render json: { success_message: "Success!, Pickup is deleted." }, status: :ok
end
end
any solutions please? .. knowing that I'm still beginner in Ruby on Rails
Note:
I used byebug, and when reaching the first line in the etra code I got this error in the local server terminal
"request.env["action_dispatch.show_detailed_exceptions"] ||= show_detailed_exceptions?"
Use the find_by instead of the find method. The find' method raises the exception if a particular record is not found, whilefind_by` returns nil.
Usage:
find_by(id: params[:id])
This answer is more of a refactor suggestion than the actual answer, but it may fix your problem as well.
You can refactor your action to this:
def delete
#pickup = Pickup.find(params[:id])
# no need to test #pickup.nil? here because `find` method raise
# an ActiveRecord::RecordNotFound error if the record is not found
# which should be caught by ApplicationController to render a 404
if #pickup.destroy
#pickup.trip.update_attributes(seatsno: #pickup.trip.seatsno + 1)
render json: { success_message: "Success!, Pickup is deleted." }, status: :ok
else
render json: { error_message: "Error, Pickup could not be deleted." }, status: 409
end
end
Even better, move the concern of incrementing seatsno to the Pickup model:
# app/models/pickup.rb
after_destroy :increment_trip_seatsno
def increment_trip_seatsno
self.trip.update_attributes(seatsno: self.trip.seatsno + 1)
end
And remove the concern from the Controller. This way, every time a Pickup record is destroyed via Rails (console or other places in your app), the trip will be updated accordingly.
I am trying to implement a realtime chat application.
I'm using pusher to notify server about the button click, and then pass the message object as message to a subscriber. What I need to do is, render that message in other user's chat screen(show.html.erb) dynamically. Here is my cycle:
// MessagesController.rb
def create
conversation = Conversation.find(params[:conversation_id])
message = Message.create(content: params[:content], user_id: params[:user_id])
conversation.messages << message
Pusher['test_channel'].trigger('my_event', {
message: message
})
end
And my subscriber is
// show.html.erb
// some html code
<ul class="chats">
<%= render #messages %>
</ul>
// some html code
<script>
// some js code
var channel = pusher.subscribe('some_channel');
channel.bind('some_event', function(data) {
// What to do here?
});
</script>
This assumes you are using jquery. It's also untested so may have a few bugs/syntax errors.
Ajax method:
JS
channel.bind('some_event', function(data) {
$.ajax({
url:'/messages/'+data.message.id,
success:function(html){ $('.chats').append(html)}
});
});
routes:
match '/messages/:id' => "messages#show_no_layout"
controller:
def show_no_layout
#message = Message.find(params[:id])
render "show", layout: false
end
view(show.html.erb):
<%= *whatever you want in here* %>
ICH(read more) method:
This will of course require adding an extra js file which is why its not my first suggestion.
Template:
<script id = "messageTemplate" type = "text/html">
{{ message.content }}
// plus whatever else you want.
</script>
channel.bind('some_event', function(data) {
messageHtml = ich.messageTemplate(data.message);
$('.chats').append(messageHtml);
});
If you are using JQuery,
channel.bind('some_event', function(data) {
$('.message').text(data.message);
});
See this tutorial.
I'm newbie with Rails
My purpose is insert song_id and title which received from Javascript via AJAX POST into Database (MySQL)
In my javascript file
var song_id = "23f4";
var title = "test";
$( document ).ready( function() {
jQuery.ajax({
url: 'create',
data: "song_id=" + song_id + "&title=" + title,
type: "POST",
success: function(data) {
alert("Successful");
},
failure: function() {
alert("Unsuccessful");
}
});
} );
In my editor_controller.rb
class EditorController < ApplicationController
def new
#song = Song.new
end
def create
logger.debug("#{params[:song_id]}")
logger.debug("#{params[:title]}")
#song = Song.new(song_params)
if #song.save
redirect_to root_path
else
flash[:notice_song_failed] = true
redirect_to root_path
end
end
private
def song_params
params.require(:song).permit(:song_id, :title)
end
The problem is when I running the Rails app with this code, the Console notices me that
ActionController::ParameterMissing at /editor/create
param is missing or the value is empty: song
I'm trying to use
private
def song_params
params.require(:song).permit(params[:song_id], params[:title])
end
but it doesn't work and notices me the same, moreover in the terminal log told me below
Started POST "/editor/create" for ::1 at 2015-04-01 01:07:23 +0700
Processing by EditorController#create as /
Parameters: {"song_id"=>"23f4", "title"=>"test"}
23f4
test
Completed 400 Bad Request in 1ms
Do I missed something in my code, Thanks for Advance.
You are not sending a song parameter at all. It looks like you need to update the data line in the jQuery.ajax call to include the song parameter like so:
data: {song: {song_id: song_id, title: title}}
This:
params.require(:song).permit(params[:song_id], params[:title])
is saying "require the 'song' parameter, and allow 'song_id' and 'title' through. If you don't pass a song parameter, you'll get a bad request.
You can either:
Change that line of code to remove the require on 'song'
or
Like #infused says, change your ajax call to send a song JSON object.
I'm trying to update vote count via ajax once user has voted. My code works fine except for something which should be pretty basic, which is showing the new total number of votes.
My javascript has the following code:
var voteCount = "<%= #trip.total_up_votes %>";
...
$.ajax({
...
success: function() {
console.log("SAVED TO VOTES TABLE SUCCESSFULLY");
$('#voting_up').html(voteCount);
},
...
});
Once the vote link has been clicked, everything gets added to the table fine except it shows the new vote count as <%= #trip.total_up_votes %> i.e. as a string. The total_up_votes method simply counts the number of up votes from the votes table. This works fine when the page is first loaded or when it's refreshed.
I've tried escape_javascript and many other suggestions after trawling through the internet but I'm still stuck. Could someone help please?
EDIT:
As requested, my votes_controller does this:
def cast_vote()
#vote = Vote.where("user_id = ? AND trip_id = ?", current_user, params[:id]).first || Vote.new(:user_id => current_user)
#vote.vote_type = params[:vote_type]
#vote.user_id = params[:user_id]
#vote.trip_id = params[:id]
respond_to do |format|
#vote.save
format.html {redirect_to :back}
format.js
end
end
Have you tried dropping the quotes?
var voteCount = <%= #trip.total_up_votes %>;
...
$.ajax({
...
success: function() {
console.log("SAVED TO VOTES TABLE SUCCESSFULLY");
$('#voting_up').html(voteCount);
},
...
});
This is all overkill. You should use the ruby ajax helper "remote". use this:
<%= link_to "Vote up", vote_up_path, remote: true %>
The remote: true above will tell the browser to handle the link via ajax, so the page will not get reloaded. vote_up_path is just an example. Lets say vote_up_path takes you to the controller action votes#upvote, then in your votes views folder you should have a file called upvote.js.erb. In that file, have the following code:
var voteCount = <%= #trip.total_up_votes %>;
console.log("SAVED TO VOTES TABLE SUCCESSFULLY");
$('#voting_up').html(voteCount);
My Ajax is posting twice (while i'm expecting only once) on a click, and I can't seem to figure why. I think it may be a double render issue, but I'm pretty new to rails, and need some insight as to where?
The JS:
$("select[name='order[city]']").on("blur",function() {
$("#triangle").fadeOut(800);
$("#cityFee").fadeOut(800);
if (feeSelected == 80 || feeSelected == 81){
$.ajax({
type: "POST",
url: '/line_items',
beforeSend: function(xhr){
xhr.setRequestHeader('X-CSRF-Token', $('meta[name="csrf-token"]').attr('content'))},
data: {product_id: feeSelected, qty_selected: 1, remote: true},
dataType: "script"
});
}
});
The Controller:
def create
#cart = current_cart
product = Product.find(params[:product_id])
ctlQty = params[:qty_selected] #parameter from itemBoxZoom user selected quantity in jquery dialog widget
#line_item = #cart.add_product(product.id, ctlQty) #passes in user selected quantity
respond_to do |format|
if #line_item.save
format.html { redirect_to(store_index_url) }
format.js { #current_item = #line_item }
format.json { render json: #line_item, status: :created, :location => #line_item }
else
format.html { render :action => "new" }
format.json { render json: #line_item.errors, status: :unprocessable_entity }
end
end
end
The method called in my Model:
def add_product(product_id, qty_selected)
current_qty = qty_selected || 1
current_item = line_items.find_by_product_id(product_id)
if current_item
current_item.quantity += current_qty.to_i
else
current_item = line_items.build(:product_id => product_id)
if qty_selected
current_item.quantity += current_qty.to_i - 1 #removes unnecessary default value of 1
end
end
qty_selected = nil
current_item
end
In my console, I see two almost identical post requests to LineItemsController#create, except while the 1st performs "INSERT INTO", the 2nd request performs "SET quantity = 2". All suggestions/help is SO much appreciated. Thanks
If it were a double render issue, you'd get a DoubleRenderError. Have you checked that the JavaScript isn't getting initialized/called twice? Does the form itself submit to the same action? If so, does it return false or otherwise cancel the form submission? I see that you are "submitting" the form on blur. I wonder if when you select the value and press enter, it triggers the blur event and submits the form? Or that the blur event is being triggered twice?
These are just the places I'd start looking.