Calling coffeescript in rails form - javascript

I have this coffeescript for dynamic select boxes to show only those models in models select box which relate to selected makes in makes select box.
And I am gonna have multiple fields working with this function separately, so anonymous function wont work.
Coffeescripts looks like this
../assets/javascripts/diys.coffee
DynamicSelect = (makesSelect, modelsSelect) ->
$(document).on 'change', makesSelect, (evt) ->
$.ajax 'update_make_models',
type: 'GET'
dataType: 'script'
data: {
make_id: $("'makesSelect' option:selected").val()
}
error: (jqXHR, textStatus, errorThrown) ->
console.log("AJAX Error: #{textStatus}")
success: (data, textStatus, jqXHR) ->
console.log("Dynamic make select OK!")
../views/diys/update_make_models.coffee
$(modelsSelect).empty()
.append("<%= escape_javascript(render "make_models/make_model") %>")
And here's part of my form, which will repeat multiple times, only id's will change, which I will pass as arguments to "DynamicSelect" function. So where and what do I need to put to launch this function properly?
<div class="vehicle_field">
<%= f.fields_for :attached_vehicles do |av| %>
<p>Select make</p>
<%= av.select :make, options_for_select(#makes.collect { |m| [m.make_name, m.id] }), { include_blank: "Select make" }, { id: 'makes_select1' } %><br>
<p>Select model</p>
<%= av.select :model, (render "make_models/make_model"), {prompt: "Select model"}, { id: 'models_select1' } %><br>
<p>Select years</p>
<%= av.select :start_year, (Time.now.year + 1).downto(Time.now.year - 100).to_a, prompt: "Year (from)" %>
<%= av.select :end_year, (Time.now.year + 1).downto(Time.now.year - 100).to_a, prompt: "Year (to)" %><br>
<% end %>
</div>
------------------------------------------------------------------------------------------------------------------------------------
Edit, trying to accomplish dynamic select boxes with data-remote attribute as Richard Peck suggested
In console it seems that I'm getting right "make_id" in parameters when selecting make in makes select box, but I can't find the way to pass it to controllers #models variable, am I doing anything right?
Form part for selecting attached vehicles from view
<div class="vehicle_field">
<%= f.fields_for :attached_vehicles do |av| %>
<p>Select make</p>
<%= av.select :make, (#makes.collect { |m| [m.make_name, m.id] }), { include_blank: "Select make" }, { data: { remote: true, url: "update_make_models", name: "make", update: "#diy_attached_vehicles_attributes_0_model"} } %><br>
<p>Select model</p>
<%= av.collection_select :model, #models, (render "make_models/make_model"), {prompt: "Select model"} %><br>
<p>Select years</p>
<%= av.select :start_year, (Time.now.year + 1).downto(Time.now.year - 100).to_a, prompt: "Year (from)" %>
<%= av.select :end_year, (Time.now.year + 1).downto(Time.now.year - 100).to_a, prompt: "Year (to)" %><br>
<% end %>
</div>
_make_model.html.erb partial
<% #models.collect do |models| %>
<option value="<%= models.id %>"><%= models.make_model_name %></option>
<% end %>
New action in diys_controller
def new
#diy = Diy.new
#step = #diy.steps.new
#attached_vehicle = #diy.attached_vehicles.new
#step.add_images_to_steps.new
#makes = Make.all
#models = MakeModel.where("make_id = ?", params[:make])
end
Also removed both coffeescripts and edited routes
get '/diys/update_make_models', to: 'diys#new', as: 'update_make_models'
And this is what I'm getting in console after selecting make
Started GET "/diys/update_make_models?diy%5Battached_vehicles_attributes%5D%5B0%5D%5Bmake%5D=12" for ::1 at 2016-02-17 20:03:21 +0200
Processing by DiysController#new as JS
Parameters: {"diy"=>{"attached_vehicles_attributes"=>{"0"=>{"make"=>"12"}}}}
Make Load (1.0ms) SELECT "makes".* FROM "makes"
MakeModel Load (1.0ms) SELECT "make_models".* FROM "make_models" WHERE (make_id = NULL)
Rendered make_models/_make_model.html.erb (3.0ms)
Rendered diys/_form.html.erb (151.0ms)
Rendered diys/new.html.erb within layouts/application (260.0ms)
Completed 200 OK in 451ms (Views: 446.4ms | ActiveRecord: 2.0ms | Solr: 0.0ms)

You can just bind .on to the element itself:
#app/assets/javascripts/application.coffee
$(document).on "change", "select#makes_select1", (evt) ->
$.ajax 'update_make_models',
type: 'GET'
dataType: 'script'
data:
make_id: $(this).find("option:selected").val()
error: (jqXHR, textStatus, errorThrown) ->
console.log "AJAX Error: #{textStatus}"
success: (data, textStatus, jqXHR) ->
console.log "Dynamic make select OK!"
Something cool you'll want to look at is the data-remote attribute for select boxes:
= f.collection_select :attribute, #collection, :id, :name, {}, { data: {remote: true, url: "update_make_models"} }
This passes the variable params[:object][:attribute] to the data-url, which you'll be able to mange in your controller to pull back the required data you want.
Using the above code will rid you of the need for the ajax definition in your JS.

Related

Rails/Javascript: Data attribute not returned through partial, but present in DOM

I am trying to display the value of a select field for shipping costs beneath the field. Thanks to #Vasfed I am tying to use data attributes and javascript. But while the data attribute is rendered in the DOM while loading th page it is not returned in the data returned for the AJAX call when inspecting console or resources.
In DOM:
<select id="shippingservices_select" name="cart[shippingservice_id]"><option value="">select a carrier</option>
<option value="7" data-price="3.9">UPS</option>
<option value="19" data-price="10.0">DHL</option>
</select>
The fetched partial:
$("#shippingservices_select").empty()
.append("<option value=\"7\">UPS<\/option><option value=\"19\">DHL<\/option>");
I am using the following ajax call:
$(document).on("change", "#lands_select", function(event){
jQuery.ajax({
url: "/carts/update_shipping/" + event.target.value,
type: "GET",
error: function (xhr, status, error) {
console.error('AJAX Error: ' + status + error);
},
success: function (response) {
console.log(response);
}
});
});
Which should return both value and data attribute, for the form:
<%= form_for :cart, :url => {:action => "show_shipping"}, :html => { :method => "get", :remote => true } do |f| %>
<%= f.collection_select(:land_id, Land.all, :id, :name, {:prompt => "select a country"}, {:id => 'lands_select'}) %><br>
<%= f.select(:shippingservice_id, options_for_select(#shippingservices.collect { |s| [s.name.titleize, s.id, {'data-price' => s.price}] }), {:prompt => "select a carrier"}, {:id => 'shippingservices_select'}) %><br>
<% end %>
Shipping: €<div id="shipping_cost"></div><br>
with the update_shipping.js.erb view:
$("#shippingservices_select").empty()
.append("<%= escape_javascript(render(:partial => #shippingservices)) %>");
and the rendered partial _shippingservice.html.erb of:
<option value="<%= shippingservice.id %>" data-price="<%= shippingservice.price %>"><%= shippingservice.name.titleize %></option>
In the controller I have:
def update_shipping
...
respond_to do |format|
format.js
end
end
Following my partial _shippingservice.html.erb I should get both value and data attribute, but I do not. I think this is the reason why:
$(document).on("change", "#shippingservices_select", function(event){
var price = $(event.target).data('price');
$("#shipping_cost").html(price);
});
Does not return the value of data-price.
How can I get this to work? Thank you in advance.
UPDATE
I was trying to troubleshoot it and things appear to be quite strange.
Both selectors display data in the DOM. The shipping service select field which get’s loaded on page load shows everything. On changing the land selector, the partial which gets loaded and which I can inspect in console does only display option value + name, but when changing the _shippingservice partial I found out that the code which gets loaded through AJAX appears not to be generated by the partial referenced in the JS Ajax call, since I can change the code inside without producing any effect on the delivered payload.
But when substituting
<%= escape_javascript(render(:partial => #shippingservices))%>
By
<%= escape_javascript(render ‘carts/shippingservice’)%>
Nothing is displayed and loaded.
You can check what partials are getting rendered on the terminal where you are running rails. Looks like you have more than 1 possible partial for shipping services.
You can also specify which partial to use instead of letting rails guess:
render partial: 'carts/shippingservice', collection: #shippingservices, as: :shippingservice

Dynamic dropdown in rails simple_form

I have a simple has_many and belongs_to relationship in my rails app. I'm using simple_form and want to dynamically change the dropdown options based on the value chosen by the user.
Models
class Processor < ApplicationRecord
has_many :processor_bank_accounts
end
class ProcessorBankAccount < ApplicationRecord
belongs_to :processor
end
Form inputs
<%= simple_form_for [#customer, #transaction] do |f| %>
<%= f.error_notification %>
<div class="form-inputs">
<%= f.input :status, :collection => ["payment request"], include_blank: false %>
<%= f.input :processor, collection: #processors ,label_method: :name,value_method: :id,label: "Processor" , include_blank: false %>
<%= f.input :processor_bank_account, collection: #bank_accounts , label_method: :bank_name, value_method: :id, label: "Processor Bank Account" , include_blank: true %>
<%= f.input :tcurrency, collection: #currencies, include_blank: false, label: 'currency' %>
<%= f.input :amount, as: :decimal, label: 'amount' %>
</div>
<div class="form-actions text-center">
<%= f.button :submit, "Add transaction", class: "form-button"%>
</div>
<% end %>
So essentially, I need the processor_bank_account dropdown to populate based on the processor chosen by the user. In the console, this would just be: ProcessorBankAccount.where(processor: processor).
Need to load options using JS and think I need to use JSON but not sure where to go from here
One way to do this would be to use jQuery to make an AJAX call to a controller action and then let Rails handle the rest through an erb template.
So on your page, with the form, invoke the action via AJAX using something like:
<script>
$(document).ready(function() {
$('#processor_id').on('change', function() {
$.ajax({
url: '/transactions/get_processor_bank_accounts',
type: 'GET',
data: {
processor_id: this.value
},
dataType: 'script',
error: function() {
alert('An error occurred retrieving bank accounts for the selected processor.');
}
});
});
});
</script>
NB, #processor_id is the id for your dropdown control.
Next, instantiate the bank accounts within your action in your controller:
def get_processor_bank_accounts
#processor_bank_accounts = ProcessorBankAccount.where(processor_id: params[:processor_id])
end
And finally simply create a view that will be responsible for repopulating your dropdown:
$select_list = $('#processor_id');
$select_list.empty();
<% #processor_bank_accounts.each do |pba| %>
$select_list.append($('<option value="<%= pba.id %>"><%= pba.name %></option>'));
<% end %>
I came up with the following solution:
1) Add a new method to my processors controller to render the inputs for the second (dynamic) dropdown in JSON format:
def processor_bank_accounts
render json: #processor.processor_bank_accounts.each do |bap|
{ id: bap.id, name: bap.name }
end
end
2) Assign this new function to a new route in config/routes:
get 'api/bankaccounts', to: 'processors#processor_bank_accounts', as: 'bankaccounts'
3) Create a JS function to access the route with the id of the processor selected in the first dropdown and populate the second dropdown with items from the JSON array:
// select first dropdown
const processor = document.getElementById("transaction_processor");
// select second dropdown
const bapSelect = document.getElementById("transaction_processor_bank_account");
function update_baps(processor_id) {
const url = `INSERTWEBURLHERE/api/bankaccounts?id=${processor_id}`;
fetch(url)
.then(response => response.json())
.then((data) => {
bapSelect.innerHTML = ""; // clear second dropdown
data.forEach((bap) => { // go through all the BAPs
const elem = `<option value="${bap.id}">${bap.bank_name}</option>`; // create option elements to insert into the second dropdown, bank_name is the chosen label method in the form
bapSelect.insertAdjacentHTML("beforeend", elem); // insert options into the dropdown
});
});
}
4) Trigger the JS when the first dropdown field is changed:
processor.addEventListener('change', function () {
update_baps(parseInt(processor.value));
});
You should add an id to the selects so you can identify them form the script.
$('select#processor').on('change', function() {
var processor_id = this.value;
var processor_bank_account = $('select#processor_bank_account')
$.ajax({
type: "GET",
url: <%= your_path %> ,
data: { processor_id: processor_id },
success: function(data, textStatus, jqXHR){
processor_bank_account.empty();
var option = new Option(data.bank_name, data.id, false, false);
processor_bank_account.append(option);
},
error: function(jqXHR, textStatus, errorThrown){...}
})
});

Ruby on Rails Partial won't refresh with AJAX but says it is rendering the partial in the console

I am trying to get a table to refresh on my Rails 5 application. It is being hosted on a Linux CentOS 7 system and accessed via my Firefox browser on Windows 7. I have tried much research and tried the Rails-AJAX gem to no avail (this gem also broke my links for some reason so I disabled it for now). In my console it claims to be rendering the partial after I make a change to the database, but this change is not reflected until I manually refresh the page in the browser.
The partial I'm trying to refresh is an entire table filled with data from the database and it has an image of an on/off light depending on if the status in the database says 'on' or 'off'. This image is what I look for if the table is actually being refreshed. Unfortunately, this image only changes when I manually refresh. Note: Svc/svc is the name of the model/table from the database that I'm using.
This is the console message I get when clicking my 'start' button:
Started GET "/boundbooks/1" for *IP ADDRESS* at 2018-06-29 17:51:10 -0400
Cannot render console from *IP ADDRESS*! Allowed networks: 127.0.0.1, ::1, 127.0.0.0/127.255.255.255
Processing by BoundbooksController#startServer as JS
Parameters: {"id"=>"1"}
Svc Load (0.8ms) SELECT "svc".* FROM "svc" WHERE "svc"."id" = ? LIMIT ? [["id", 1], ["LIMIT", 1]]
↳ app/controllers/boundbooks_controller.rb:26
(0.2ms) begin transaction
↳ app/controllers/boundbooks_controller.rb:30
Svc Update (4.2ms) UPDATE "svc" SET "STATUS" = ? WHERE "svc"."id" = ? [["STATUS", "on"], ["id", 1]]
↳ app/controllers/boundbooks_controller.rb:30
(23.8ms) commit transaction
↳ app/controllers/boundbooks_controller.rb:30
Svc Load (0.5ms) SELECT "svc".* FROM "svc"
↳ app/views/boundbooks/_boundbooks_table.html.erb:8
Rendered boundbooks/_boundbooks_table.html.erb (17.8ms)
Completed 200 OK in 83ms (Views: 36.3ms | ActiveRecord: 29.5ms)
Code from views/boundbooks/index.html.erb:
<div id="bb-table">
<%= render partial: 'boundbooks_table', locals: { boundbooks: #boundbooks } %>
</div>
<br><br>
<% #boundbooks.each do |svc| %>
<%= link_to 'Refresh', boundbookUpdate_path(:bb_id => svc.id), id: 'refresh-button', class: 'btn', remote: true %>
<% end %>
Yes, I know the refresh button is printed multiple times, but I did not know how to link one button to the database.
HTML for table partial:
<table id="boundbooktable" border="1">
<thead><th>Status</th><th>Name</th><th>IP Address</th><th>Port</th><th>Action</th></thead>
<tbody>
<%# btnCounter gives each button a different ID by incrementing at the end of the loop %>
<% btnCounter = 1 %>
<%# statusOn = true %>
<%# creates a for-loop that utilizes the svc database table %>
<% #boundbooks.each do |svc| %>
<% status = svc.STATUS %>
<tr>
<td class="status-cell">
<% if status == "on" %>
<%= image_tag ("statusOn.png") %>
<% else %>
<%= image_tag ("statusOff.png") %>
<% end %>
</td>
<td><%= svc.NAME %></td>
<td><%= svc.IP %></td>
<td><%= svc.PORT %></td>
<td>
<% if status == "off" %>
<%= link_to "Start", boundbookStart_path(svc.id), id: 'start-button' + btnCounter.to_s, class: 'btn-start',
data: { confirm: "Start " + svc.NAME + "?" }, remote: true %>
<% else %>
<%= link_to "Start", boundbookStart_path(svc.id), id: 'start-button' + btnCounter.to_s, class: 'btn-start',
data: { confirm: svc.NAME + " is already on." }, remote: true %>
<% end %>
<% if status == "on" %>
<%= link_to "Stop", boundbookStop_path(svc.id), id: 'stop-button' + btnCounter.to_s, class: 'btn-stop', remote: true,
data: { confirm: "ALERT: Stop " + svc.NAME + "?" }, onclick: 'myFunction()' %>
<% else %>
<%= link_to "Stop", boundbookStop_path(svc.id), id: 'stop-button-already-off' +btnCounter.to_s, class: 'btn-stop',
remote: true, data: { confirm: svc.NAME + " is already off." } %>
<% end %>
<%= link_to "Log", boundbooks_path, id: 'log-button' + btnCounter.to_s, class: 'btn btn-log', remote: true %>
</td>
</tr>
<% btnCounter += 1 %>
<% end %> <%# end for-loop going through database %>
</tbody>
</table>
Code for boundbooks controller update and startServer methods:
def update
#boundbooks = Svc.all
#selected = Svc.where(:boundbook_id => params[:bb_id])
respond_to do |format|
format.js
end
end
def startServer
server = Svc.find(params[:id])
if server.STATUS == "off"
#boundbooks = Svc.all
server.update_attribute(:STATUS, "on")
refresh_dom_with_partial('div#bb-table', 'boundbooks_table')
render partial: 'boundbooks_table', locals: { boundbooks: #boundbooks }
else
puts ">>>> >>>> >>>> Server already on"
end
end
JavaScript code for AJAX in update.js.erb in the boundbooks views folder:
$.ajax({ url: "boundbooks_controller/update",
success: function() {
$("#boundbookstable").html("<%= escape_javascript(render partial: 'boundbooks_table', locals: { boundbooks: #selected } ) %>");
}});
these are the relevant routes in routes.rb:
get '/welcome' => 'welcome#index'
get '/boundbooks/:id/', controller: 'boundbooks', action: 'startServer', as: 'boundbookStart'
get '/boundbooks/:id/edit', controller: 'boundbooks', action: 'stopServer', as: 'boundbookStop'
get '/boundbooks/:bb_id/update' => 'boundbooks#update', as: 'boundbookUpdate'
get '/boundbooks_controller/update' => 'boundbooks#update'
How would I get this to actually refresh the table properly?
Your error seems simple
you are trying to change the html of the div with id 'boundbookstable'
$("#boundbookstable").html(...
but in your html, the div has the id of 'boundbooktable'
<table id="boundbooktable" border="1">
just be sure that they are exactly the same on both, change the html or the js, but be sure they are both equal on both files.

Can't find reason why xhr is not defined

I am getting an uncaught reference error: XHR is not defined in my coffeescript below.
jQuery ->
# Create a comment
$(".comment-form")
.on "ajax:beforeSend", (evt, xhr, settings) ->
$(this).find('textarea')
.addClass('uneditable-input')
.attr('disabled', 'disabled');
.on "ajax:success", (evt, data, status, xhr) ->
$(this).find('textarea')
.removeClass('uneditable-input')
.removeAttr('disabled', 'disabled')
.val('');
$(xhr.responseText).hide().insertAfter($(this)).show('slow')
# Delete a comment
$(document)
.on "ajax:beforeSend", ".comment", ->
$(this).fadeTo('fast', 0.5)
.on "ajax:success", ".comment", ->
$(this).hide('fast')
.on "ajax:error", ".comment", ->
$(this).fadeTo('fast', 1)
I have been unable to figure out the issue and I've pretty weak in javascript.
What I'm trying to do is add a comment to a users page then show it via AJAX. The comment saves without any problem as I can see it if I manually refresh the page. However neither the create or delete actions work in the Coffeescript.
Since neither the create or delete AJAX calls seem to work, I am assuming it's in the way the script is called. I'll include the relevant controller code here as well.
class CommentsController < ApplicationController
before_action :set_comment, only: [:show, :destroy]
def create
#comment_hash = comment_params
#obj = #comment_hash[:commentable_type].constantize.find(#comment_hash[:commentable_id])
# Not implemented: check to see whether the user has permission to create a comment on this object
#comment = Comment.build_from(#obj, current_user, #comment_hash[:body])
#comment.user = current_user
if #comment.save
render partial: "comments/comment", locals: { comment: #comment }, layout: false, status: :created
else
p #comment.errors
render js: "alert('error saving comment');"
end
end
def destroy
if #comment.destroy
render json: #comment, status: :ok
else
render js: "alert('error deleting comment');"
end
end
private
# Use callbacks to share common setup or constraints between actions.
def set_comment
#comment = Comment.find(params[:id])
end
# Never trust parameters from the scary internet, only allow the white list through.
def comment_params
params.require(:comment).permit( :commentable_id, :commentable_type, :body, :user_id)
end
end
Also my partial for the comment:
<div class='comment'>
<hr>
<%=link_to "×", comment_path(comment), method: :delete, remote: true, confirm: "Are you sure you want to remove this comment?", disable_with: "×", class: 'close' %>
<small><%=comment.updated_at.to_s(:short) %></small>
<p><%= comment.body %></p>
And the form itself to add new comments:
<div class='comment-form'>
<%= simple_form_for comment, remote: true do |f| %>
<%= f.input :body, input_html: { rows: "2" }, label: false %>
<%= f.input :commentable_id, as: :hidden, value: comment.commentable_id %>
<%= f.input :commentable_type, as: :hidden, value: comment.commentable_type %>
<%= f.button :submit, 'New Note', class: "button tiny radius", disable_with: "Submitting…" %>
<% end %>
</div>
Any help would be appreciated since I just don't know where to start right now. I'm not sure how I should be defining the XHR.
Incidentally, most of the code for this was from the tutorial here

Completely Stuck on AJAX Form Submission With Stripe

I am so frustrated. I'm working with Stripe to create a form submission system for payments. Basically, the form makes an AJAX call to Stripe, which gives me a token on success, which I then use to resubmit the form, also through AJAX. If the form is successful, it redirects to a new page, if not, it populates the form with error messages without re-navigation. Here's my form:
<%= form_for([#issue, #issue_order]) do |f| %>
<% if #issue_order.errors.any? %>
<div class="error_messages">
<h2><%= pluralize(#issue_order.errors.count, "error") %> occurred. </h2>
<ul>
<% #issue_order.errors.full_messages.each do |msg| %>
<li><%= msg %></li>
<% end %>
</ul>
</div>
<% end %>
<% f.hidden_field :issue_id %>
<%= f.hidden_field :stripe_card_token %>
<div class="field">
<%= f.label :email %>
<%= f.text_field :email %>
</div>
<div class="field">
<%= label_tag :card_number, "Credit Card Number " %>
<%= text_field_tag :card_number, nil, name: nil %>
</div>
<div class="field">
<%= label_tag :card_code, "Security Code on Card (CVV) " %>
<%= text_field_tag :card_code, nil, name: nil %>
</div>
<div class="field">
<%= label_tag :card_month, "Card Expiration " %>
<%= select_month nil, {add_month_numbers_true: true}, {name: nil, id: "card_month"} %>
<%= select_year nil, {start_year: Date.today.year, end_year: Date.today.year + 15}, {name: nil, id: "card_year"} %>
</div>
<div id="stripe_error"></div>
<div class="actions"><%= f.submit "Purchase Issue", id: "submit_issue_order" %></div>
<% end %>
<div class="errors"></div>
Here is the javascript that handles the form and sets up the stripe information:
var issueOrder;
$(function() {
Stripe.setPublishableKey($('meta[name="stripe-key"]').attr('content'));
issueOrder.setupForm();
});
var issueOrder = {
setupForm: function() {
$('#new_issue_order').submit(function(e) {
e.preventDefault();
$('#submit_issue_order').attr('disabled', true);
issueOrder.processCard();
return false;
});
},
processCard: function() {
var card;
card = {
number: $('#card_number').val(),
cvc: $('#card_code').val(),
expMonth: $('#card_month').val(),
expYear: $('#card_year').val()
};
Stripe.createToken(card, issueOrder.handleStripeResponse)
},
handleStripeResponse: function(status, response) {
if (status == 200) {
$('#issue_order_stripe_card_token').val(response.id);
// $('#new_issue_order')[0].submit();
$.ajax({
type: "POST",
url: $('#new_issue_order').attr('action'),
data: { "issue_order": {
"stripe_card_token": $('#issue_order_stripe_card_token').val(),
"email": $('issue_order_email').val(),
},
"issue_id": $('#issue_order_issue_id').val()
},
dataType: "script"
}, issueOrder.processOrder);
}
else {
$('#stripe_error').text(response.error.message);
$('input[type=submit]').attr('disabled', false)
}
}
And here is my controller:
def create
charge = Stripe::Charge.create(
:amount => 400,
:currency => "usd",
:card => params['issue_order']['stripe_card_token']
)
if charge['paid'] == true
#issue_order = IssueOrder.new(email: params['issue_order']['email'], issue_id: params['issue_id'])
if #issue_order.save
#pdf_token = #issue_order.pdf_token
PdfMailer.pdf_email(params['issue_order']['email'], #issue_order).deliver
else·
flash[:error] = []
flash[:error].push("Your card was charged, but sadly we were unable to create·
a record in the database. Please contact us for your copy of the issue.")
respond_to do |format|
format.js
end
end
else
# run checks for errors and return error messages
flash[:error] = []
flash[:error].push("There was an error in processing your payment.")
render :json => {success: false}
end
end
Typical stripe setup stuff. Works fine when the stripe order is successfully processed. Well, it did before I hand-rolled the AJAX call, I'm assuming it'd be fine if I threw a respond_to |format| in the success case in the controller that redirected to the success page. However, for the error cases, my controller renders create.js.erb, which looks like this:
console.log('yo');
$('.errors').empty();
errors = xhr.getResponseHeader('X-Flash-Error').split(',');
<% flash[:error].each do |error| %>
$('.errors').append($('<p>' + <%= error %> + '</p>'));
<% end %>
setTimeout(function() {
$('.errors').empty();
}, 3500);
The controller clearly reaches the file and renders it, as evidenced by the logs:
Started POST "/issues/1/issue_orders" for 127.0.0.1 at 2013-11-12 23:33:17 -0500
Processing by IssueOrdersController#create as JS
Parameters: {"issue_order"=>{"stripe_card_token"=>"tok_102vmu2pSkyWUgPAToj334Oa"}, "issue_id"=>"1"}
(0.4ms) BEGIN
(0.4ms) ROLLBACK
Rendered issue_orders/create.js.erb (0.1ms)
["Your card was charged, but sadly we were unable to create \n a record in the database. Please contact us for your copy of the issue."]
Completed 200 OK in 1363ms (Views: 3.9ms | ActiveRecord: 0.8ms)
But NOTHING happens on my page, including the console log! If I don't hand roll the AJAX and use remote: true, it gets even worse -- it recognizes my submit() call as HTML and doesn't know what to do with the format, rendering an Unknown Format error.
Help!

Categories