AJAX GET request in Rails without rendering views/json - javascript

Making a GET request to check whether or not to send a followup POST request and don't need to render anything following the first request. I'm using render nothing: true at the base of my controller action, so I'm not sure what's causing the ActionView::MissingTemplate at /able_to_claim error when I sent the request through the browser console:
def able_to_claim
role, user_id = params[:role], params[:user_id]
if role == "Senior Editor" or role == "Admin"
return true
else
active_essays = 0
Claim.where(:user_id => user_id).each {|claim| active_essays += 1 if Essay.find(claim.essay_id).status != "Complete"}
if role == "Editor" and active_essays < 5
return true
elsif role == "Managing Editor" and active_essays < 15
return true
else
return false
end
end
render nothing: true
end
Route: get '/able_to_claim' => 'users#able_to_claim'
js file:
response = $.ajax({
type: 'GET',
url : '/able_to_claim/?role=' + userRole + '&user_id=' + userId,
crossDomain: true,
contentType:'application/json; charset=utf-8',
dataType: 'json'
});
userRole and userId defined in application.html.erb:
<%= javascript_tag "var userId = #{current_user.id};" if current_user %>
<%= javascript_tag "var userRole = '#{current_user.role}';" if current_user %>

Wow, feel really silly. I had no idea that return breaks out of the rest of the function. With some refactoring:
def able_to_claim
role, user_id = params[:role], params[:user_id]
if role == "Senior Editor" or role == "Admin"
can_claim = true
else
active_essays = User.find(user_id).essays.where.not(status: 'Complete').count
if role == "Editor" and active_essays < 5
can_claim = true
elsif role == "Managing Editor" and active_essays < 15
can_claim = true
else
can_claim = false
end
end
render json: {can_claim: can_claim}
end

Related

Setting state when page loads, Depending on (database?) contents

So in my code, I want it where a single User can only have one booking/reservation per Hotel, but every time after the page is refreshed, my state keeps reverting back to it's default value, even if the Hotel has already been reserved...
BTW, all of the code is functioning, it is just the state that is giving me a problem...
I've been troubleshooting and debugging the code for a couple of hours but nothing concrete so far.
I've included code from most of the files, but I can't bring in the code from all of the ones needed, or it wouldn't quite be an "minimal" reproducible example, so I'll try to summarize the structure here:
There is a many-to-many relationship between Users and Hotels, which has Bookings belonging to both. This enables me to use hotel.users, etc.
I've just tried adding in a new state (const [bookingObject, setBookingObject] = useState();), but I haven't been able to get it to give me a truthy value 100% of the time... Can anyone see what it is that I'm doing wrong? Anyone have any suggestions or ideas?
bookings_controller.rb:
class BookingsController < ApplicationController
skip_before_action :authorize, only: [:create, :destroy]
def show
render json: #booking
end
def create
booking = Booking.new(booking_params)
if booking.save
render json: booking, status: :created
else
render json: {errors: "Something went wrong!"}
end
end
def destroy
#booking = Booking.find(params[:id])
#booking.destroy
end
private
def set_booking
#booking = Booking.find(params[:id])
end
def booking_params
params.require(:booking).permit(:id, :user_id, :hotel_id)
end
end
hotels_controller.rb:
class HotelsController < ApplicationController
skip_before_action :authorize, only: [:create, :destroy]
def index
render json: Hotel.all
end
def show
render json: #hotel
end
def hotel_params
params.require(:hotel).permit(:name, :city, :country, :company)
end
end
Hotel.jsx:
import React, {useContext, useState} from 'react';
const {bookings, setBookings} = useContext(BookingsContext);
const [booked, setBooked] = useState(false);
const [bookingObject, setBookingObject] = useState();
function toggleBooking(e){
if(booked){
const booking = bookings.find(booking => {return booking.hotel.id == e.target.id});
deleteBookings(booking.id);
setBooked(!booked);
} else if(booked === false){
postBookings();
setBooked(!booked);
}
}
function postBookings(){
const newBooking={
user_id: (currentUser.id),
hotel_id: (hotel.id)
}
fetch(`http://localhost:3001/users/${currentUser.id}/bookings`, {
method: "POST",
headers: {"Content-Type": "application/json"},
body: JSON.stringify({
booking: newBooking
}),
}).then((r) => r.json())
.then((data) => {
setBookingObject(data);
setBookings([...bookings, data]);
})
}
function deleteBookings(bookingId){ fetch(`http://localhost:3001/users/${currentUser.id}/bookings/${bookingId}`, {
method: "DELETE"
})
.then((r) => {
if(r.ok)onDeleteBookings(bookingId);
})
}
function onDeleteBookings(deletedBooking){
const updatedBookings = bookings.filter((booking) => booking.id !== deletedBooking.id);
setBookings(updatedBookings);
setBookingObject();
}
return(
<div id='hotels'>
<p>{hotel.name}</p><p>{hotel.city}, {hotel.country}</p>
<button id={hotel.id} onClick={toggleBooking} >{booked ? ("Booked") : ("Book Now")}</button>
</div>
);
}
export default Hotel;

ActionCable not getting data on Rails

I am trying to build a chat feature in my app and initially, the action cable had worked for it seems like it is not getting any data to broadcast. I have tried to console log in the chatroom_channel.js but the "data" is not being populated on the console.
initChatroomChannel is also exported from application.js
I have also tried to use the solution from the ticket below but that also did not help out.
ActionCable Not Receiving Data
There's are the related files.
Thank you
Onur
messages_controller
class MessagesController < ApplicationController
def create
#chatroom = Chatroom.find(params[:chatroom_id])
#message = Message.new(message_params)
#message.chatroom = #chatroom
#message.user = current_user
if #message.save
ChatroomChannel.broadcast_to(
#chatroom,
render_to_string(partial: "message", locals: { message: #message })
)
redirect_to chatroom_path(#chatroom, anchor: "message-#{#message.id}")
else
render "chatrooms/show"
end
end
def message_params
params.require(:message).permit(:content)
end
chatrooms_controller
class ChatroomsController < ApplicationController
def index
#chatrooms = []
all_chatrooms = Chatroom.all
all_chatrooms.each do |chatroom|
#chatrooms << chatroom if (current_user.id == chatroom.engager_id || current_user.id == chatroom.receiver_id)
end
end
def show
chat = Chatroom.find(params[:id])
if (current_user.id == chat.engager_id || current_user.id == chat.receiver_id)
#message = Message.new
#chatroom = chat
else
redirect_to chatrooms_path
end
end
def destroy
#chatroom = Chatroom.find(params[:id])
#chatroom.destroy
redirect_to chatrooms_path
end
end
chatroom_channel.rb
class ChatroomChannel < ApplicationCable::Channel
def subscribed
# stream_from "some_channel"
chatroom = Chatroom.find(params[:id])
stream_for chatroom
end
# def unsubscribed
# # Any cleanup needed when channel is unsubscribed
# end
end
chatroom_channel.js
import consumer from "./consumer";
const initChatroomCable = () => {
const messagesContainer = document.getElementById('messages');
if (messagesContainer) {
const id = messagesContainer.dataset.chatroomId;
consumer.subscriptions.create({ channel: "ChatroomChannel", id: id }, {
received(data) {
console.log(data)
messagesContainer.insertAdjacentHTML("beforeend", data)
},
});
}
}
export { initChatroomCable };
application.js
import Rails from "#rails/ujs"
import Turbolinks from "turbolinks"
import * as ActiveStorage from "#rails/activestorage"
import "channels"
Rails.start()
Turbolinks.start()
ActiveStorage.start()
// External imports
import "bootstrap";
import { loadDynamicBannerText } from '../componets/banner';
// Internal imports, e.g:
import { initChatroomCable } from '../channels/chatroom_channel';
document.addEventListener('turbolinks:load', () => {
initChatroomCable();
jQuery.fn.carousel.Constructor.TRANSITION_DURATION = 2000
var $item = $('.carousel-item');
var $wHeight = $(window).height();
$item.eq(0).addClass('active');
$item.height($wHeight * 0.75);
$item.addClass('full-screen');
$('.carousel img').each(function () {
var $src = $(this).attr('src');
var $color = $(this).attr('data-color');
$(this).parent().css({
'background-image': 'url(' + $src + ')',
'background-color': $color
});
$(this).remove();
});
$(window).on('resize', function () {
$wHeight = $(window).height();
$item.height($wHeight * 0.75);
});
$('.carousel').carousel({
interval: 6000,
pause: "false"
});
const banner = document.getElementById("banner-typed-text")
if (banner) {
loadDynamicBannerText();
}
});
import "controllers"
_message.html.erb
<div class="message-container" id="message-<%= message.id %>">
<i class="author">
<% User.find(message.user_id).name ? name = User.find(message.user_id).name : name = "Unknown Cat" %>
<span><%= User.find(message.user_id) == current_user ? "me" : name %></span>
<small><%= message.created_at.strftime("%a %b %e at %l:%M%p") %></small>
</i>
<p><%= message.content %></p>
</div>
cable.yml
development:
adapter: async
test:
adapter: test
production:
adapter: redis
url: <%= ENV.fetch("REDIS_URL") { "redis://localhost:6379/1" } %>
channel_prefix: Cat_Tinder_production

Django Ajax Post request

Error is: Forbidden (CSRF token missing or incorrect.): /tracker/
i try a URL : tracker, tracker/, /tracker/, http://127.0.0.1:8000/tracker/'
I'm new to Django. I try many URL and I also try a Moesif CORS(Extention)
console Error is: jquery-3.5.1.js:10099 POST http://127.0.0.1:8000/tracker/ 403 (Forbidden)
send # jquery-3.5.1.js:10099
ajax # jquery-3.5.1.js:9682
(anonymous) # (index):276
dispatch # jquery-3.5.1.js:5429
elemData.handle # jquery-3.5.1.js:5233
urls.py file:
urlpatterns = [
path('', views.index, name="index"),
path('preview/<int:id>/', views.preview, name="preview"),
path('checkout/', views.checkout, name="checkout"),
path('tracker/', views.tracker, name="tracker"),
]
console.log('working')
$('#trackerForm').submit(function(event){
$('#items').empty();
var formdata = {
'orderId' : $('input[name=order_id]').val(),
'email' : $('input[name=email]').val(),
'csrfmiddlewaretoken': $('input[name=csrfmiddlewaretoken]').val()
};
$.ajax({
type : 'POST',
url : 'http://127.0.0.1:8000/tracker/',
data:'formdata',
encode: true
})
.done(function(data){
console.log(data)
updates = JSON.parse(data);
if (updates.length > 0 & updates != {}) {
for (i = 0; i < updates.length; i++) {
let text = updates[i]['text'];
let time = updates[i]['time'];
mystr = `<li class="list-group-item d-flex justify-content-between align-items-center">
${text}
<span class="badge badge-primary badge-pill">${time}</span>
</li>`
$('#items').append(mystr);
}
} else {
mystr = `<li class="list-group-item d-flex justify-content-between align-items-center">
Sorry, We are not able to fetch this order id and email. Make sure to type correct order Id and email</li>`
$('#items').append(mystr);
}
})
event.preventDefault();
})
Views.py
def tracker(request):
if request.method == "POST":
order_id = request.POST.get('order_id')
email = request.POST.get('email')
try:
order = Order.objects.filter(order_id=order_id, email=email)
if len(order) > 0:
update = updateOrder.objects.filter(order_id=order_id)
updates = []
for item in update:
updates.append({'text':item.order_desc, 'time':item.timestamp})
responce = json.dumps(updates, default=str)
print(responce)
return HttpResponse(responce)
else:
return HttpResponse({})
except Exception as e:
return HttpResponse({})
context={}
return render(request, 'cart/tracker.html', context)
Remove the quotes around 'formdata' -> formdata
formdata= {
...
}
...
$.ajax({
type : 'POST',
url : 'http://127.0.0.1:8000/tracker/',
data: formdata,
encode: true
})

Ajax Call Returns HTML page as response instead of rendering page (Rails)

Hey having a issue with the rendering of a .erb file, in my AJAX call I make a call to my create action on rails where I validate and process the form data and sent back the completed order data as render: json which works fine.
I have a conditional that checks to see if parameter exists, it if does then the completed order data is passed back as a response via render: json
It if doesn't exists it will render a receipt page.
The problem is when I render the receipt page, the full HTML receipt page comes back as a response instead of rendering the page. Please Help!
$scope.placeOrder = function() {
var body = composeOrderBody();
var isValid = validateForm(body.order);
if(isValid) {
var orderComplete = '<%= #orderComplete %>';
var baseUrl = '<%= request.base_url %>';
console.log('Passing order object: ', body.order);
$http({
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
url: checkout_url,
data: {
order: body.order,
xhr_request: true
},
}).then((function(_this) {
return function(response) {
if(typeof response.data == 'undefined' || response.data == null || !response.data) {
console.log('Error: missing Order Number from Order Confirmation data.', response.data);
}
console.log('Order Confirmation response data object:' , response.data);
if(orderComplete) {
var redirectUrl = 'http://' + orderComplete
var order_params = `?oid=${response.data.oid}?cart=${response.data.cart}?total=${response.data.total}`
window.location.href = redirectUrl + order_params;
} else {
console.log('Base Url: ', baseUrl);
// window.location.href = `${baseUrl}/receipt`;
}
};
})(this));
} else {
console.log('Form Validation or Stripe Validation Failed');
}
} // end placeOrder
Rails Code
# Redirect to orderComplete URL if it's set
if !#orderComplete.blank?
puts 'orderComplete parameter is not blank'
# Sum up all the line item quantities
qty = #order.line_items.inject(0) {|sum, line_item| sum + line_item.quantity}
# Get all of the coupons (and values) into a string
coupons = #order.applied_coupons.map { |coupon| coupon.coupon }.join(',')
coupon_values = #order.applied_coupons.map { |coupon| '%.2f' % coupon.applied_value.to_f }.join(',')
order_params = {
"oid" => URI::escape(#order.number),
"cart" => URI::escape(#cart),
"total" => URI::escape('%.2f' % #order.total),
}
#redirectUrl = URI.parse(URI.escape(#orderComplete))
#redirectUrl.query = [#redirectUrl.query, order_params.to_query].compact.join('&')
#redirectUrl = #redirectUrl.to_s
if params[:xhr_request]
render json: order_params.to_json
return
end
render 'receipt_redirect', :layout => 'receipt_redirect'
else
puts 'OrderComplete Parameter is blank'
render 'receipt', :layout => 'receipt', :campaign => #campaign
end

Stripe RailsJS, Cannot charge a customer that has no active card

I keep getting the "Cannot charge a user that has no active card" error when trying to bill a test user.
The app works so that a user gets charged $10 on sign up after they input their CC credentials.
I know the customers are being created but the charges aren't being sent
Here is the Stripe error
My credit_card_form.js file which is what collects the credit card info and sends it to stripe without it hitting my database.
$(document).ready(function(){
var show_error, stripeResponseHandler, submitHandler;
submitHandler = function (event) {
var $form = $(event.target);
$form.find("input[type=submit]").prop("disabled", true);
//If Stripe was initialized correctly this will create a token using the credit card info
if(Stripe){
Stripe.card.createToken($form, stripeResponseHandler);
show_error("CC token generated")
} else {
show_error("Failed to load credit card processing functionality. Please reload this page in your browser.")
}
return false;
};
// calling the SUBMIT
$(".cc_form").on('submit', submitHandler);
// RESPONSE HANDLER
stripeResponseHandler = function (status, response) {
var token, $form;
$form = $('.cc_form');
if (response.error) {
console.log(response.error.message);
show_error(response.error.message);
$form.find("input[type=submit]").prop("disabled", false);
} else {
token = response.id;
$form.append($("<input type=\"hidden\" name=\"payment[token]\" />").val(token));
$("[data-stripe=number]").remove();
$("[data-stripe=cvv]").remove();
$("[data-stripe=exp-year]").remove();
$("[data-stripe=exp-month]").remove();
$("[data-stripe=label]").remove();
$form.get(0).submit();
}
return false;
};
//ERROR HANDLING
show_error = function (message) {
if($("#flash-messages").size() < 1){
$('div.container.main div:first').prepend("<div id='flash-messages'></div>")
}
$("#flash-messages").html('<div class="alert alert-warning"><a class="close" data-dismiss="alert">×</a><div id="flash_alert">' + message + '</div></div>');
$('.alert').delay(5000).fadeOut(3000);
return false;
};
});
And payment.rb
class Payment < ApplicationRecord
attr_accessor :card_number, :card_cvv, :card_expires_month, :card_expires_year
belongs_to :user
def self.month_options
Date::MONTHNAMES.compact.each_with_index.map{|name,i| ["#{i+1} - #{name}", i+1]}
end
def self.year_options
(Date.today.year..(Date.today.year+10)).to_a
end
def process_payment
customer = Stripe::Customer.create email:email, card:token
Stripe::Charge.create customer:customer.id, amount: 1000, description: "Premium", currency: "usd"
end
end
And a snippet of the devise registrations new.html.erb which is where the user will be charged from
<div class="col-md-3">
<%=p .select :card_expires_month, options_for_select(Payment.month_options), {include_blank: "Month"}, "data-stripe"=>"exp-month", class: "form-control", required: true%>
</div>
<div class="col-md-3">
<%=p .select :card_expires_year, options_for_select(Payment.year_options.push), {include_blank: "Year"}, class: "form-control", data: {stripe: "exp-year"}, required: true%>
</div>
I know that the customers are being created but I have no clue why my customers aren't paying when I use the test credit card numbers. No answers on stack overflow have helped me as of yet.
Jack and I had a chat and discovered that Stripe.js wasn't loading, so the token wasn't being sent in the request.
The issue was <%= javascript_include_tag 'https://js/stripe.com/v2' %> being a mistyped js link in application.html.erb
The fix was making it <%= javascript_include_tag 'https://js.stripe.com/v2/' %>

Categories

Resources