On the page that contains my order form, in the <head>, I have:
= jquery_include_tag Rails.application.config.jquery_version
= javascript_include_tag "https://js.stripe.com/v2/"
:javascript
$(function(){
Stripe.setPublishableKey('pk_test_NEgBLhQ1dJGvlE8SDFEXqRQ4');
});
(function() {
var stripeResponseHandler;
$("#new_order").submit(function(event) {
var form;
form = $(this);
form.find("#submit_order").prop("disabled", true);
Stripe.createToken(form, stripeResponseHandler);
return false;
});
stripeResponseHandler = function(status, response) {
var form, token;
form = $("#new_order");
if (response.error) {
form.find(".payment-errors").text(response.error.message);
form.find("#submit_order").prop("disabled", false);
} else {
token = response.id;
form.append($("<input type=\"hidden\" name=\"stripeToken\">").val(token));
form.get(0).submit();
}
};
}).call(this);
The key you see listed above is labelled "Test Publishable Key" at https://manage.stripe.com/account/apikeys.
The form on that page includes:
= simple_form_for #order, :html => {:id => "new_order"} do |f|
= f.error_notification
= text_field_tag :number, nil, :name => nil, "data-stripe" => "number"
= text_field_tag :cvc, nil, :name => nil, "data-stripe" => "cvc"
= text_field_tag :expiry_month, nil, "data-stripe" => "exp-month"
= text_field_tag :expiry_year, "data-stripe" => "exp-year"
= f.button :submit, :as => :button, :id => 'submit_order'
(With all the labels/placeholders/etc and non-Stripe fields stripped out.)
At present I am running this in development mode on localhost without any SSL.
When I complete an order with valid or invalid credit card data and click Create Order, my Rails app logs an order but the Javascript does not seem to communicate with the Stripe server. I see no errors -- or any Javascript activity at all as far as I can tell -- in Chrome's Javascript console. And I see no charges -- successful or otherwise -- at https://manage.stripe.com/test/events.
I know my way around Rails but am a Javascript novice. How can I diagnose what's going on here? And what might be the cause?
(function() {
This should maybe be
$(function() {
(and you can ditch the .call(this) stuff)
It's executing immediately in the <head>, which probably means $("#new_order") isn't finding the form — the browser hasn't even rendered it, or possibly even received the HTML for it off the network, yet — so the selector matches zero items, and the event binding is a no-op.
Alternatively, if you put the code just before your </body>, that'd do the trick, too.
(Also, putting the Stripe.setPublishableKey() in a $(function() { … }) block is not useful.)
Related
My app has a live search implemented and it works properly. The problem that I have is that now I have a table with a lot of columns and I want to search through all elements. I want to have only one text input and a drop down that will select the column that I want to search in.
Searchable module
module Searchable
extend ActiveSupport::Concern
module ClassMethods
def search_for(present_column,record)
record.present? ? where(present_column+' LIKE ?', record+"%") : all
end
end
end
People controller
class PeopleController < ApplicationController
def index
#people = Person.page(params[:page]).per(5).search_for(params[:object_columns], params[:search])
end
The search engine
<%= form_tag do %>
<% valid_column_names = target.column_names.reject{|r| r == "created_at" || r == "updated_at" || r == "slug"} %>
<%= select_tag :object_columns, options_for_select(valid_column_names) %>
<%= text_field_tag :search, '', autocomplete: :off %>
<% end %>
The live search js
$(function () {
$("input#search").keyup(function () {
$.get($("#object_columns option:selected").text(), $("#object_columns").serialize(), null, "script");
$.get($("#search").attr("action"), $("#search").serialize(), null, "script");
});
});
The input text is returned as expected, but nothing comes from the object_columns. When I type the word "n", for example, my server terminal returns this message:
Started GET "/people?&search=n&_=1463081307356" for 127.0.0.1 at 2016-05-12 16:28:34 -0300
Processing by PeopleController#index as JS
Parameters: {"search"=>"n", "_"=>"1463081307356"}
EDIT:
I had an idea later on and made some changes. I gave the form an ID and used it to do the request, now I can have both information (column names and the search record) at the same time. The only problem now is with the path, it is returning an URI error.
The search engine
<%= form_tag people_path, class: "form_id" do %>
<% valid_column_names = target.column_names.reject{|r| r == "created_at" || r == "updated_at" || r == "slug"} %>
<%= select_tag :object_columns, options_for_select(valid_column_names) %>
<%= text_field_tag :search, '', autocomplete: :off %>
<% end %>
The live search
$(function () {
$("input#search").keyup(function () {
$.get($(".form_id"), $(".form_id").serialize(), null, "script");null, "script");
});
});
In your search_for method, the return value is always all. You really want the return value to be the result of the ternary operator directly above it. Remove the last all and you should be good to go.
module ClassMethods
def search_for(present_column,record)
record.present? ? where(present_column+' LIKE ?', record+"%") : all
# all <== this should be removed
end
end
In your javascript, you'll need a few changes:
$(function () {
function search() {
$.get("/search", { column_name: $("select#column_name").val(), search: $("#search").val() }, null, "script");
};
$("select#column_name").change(search);
$("input#search").keyup(search);
});
The actual Ajax call has been changed to:
remove the undefined "action" attribute on the search input field
explicitly reference the URL to send the request
create hash parameters for the ajax call
remove the unnecessary calls to serialize()
This also installs a handler on the change event of the column selection, hence the refactoring of the Ajax call to a separate function.
I have the ff:
app/views/reports/index.html.erb
<h1>Reports</h1>
<br>
<legend>Categories</legend>
<div class="row">
<div class="span5">
<ol>
<li><%= link_to 'COMMENDATION', commendations_path(format: 'pdf'), { id: 'commendations_click' } %></li>
<%= collection_select(nil,
:employee_id,
#employees,
:id,
:last_name,
{:prompt => "Select an Employee"},
{:id => 'employees_select'}) %>
<br>
<%= collection_select(nil,
:employee_movement_id,
#employeemovements,
:id,
:position,
{:prompt => "-"},
{:id => 'employee_movements_select'}) %>
<li><%= link_to 'REPORT2', '#' %></li>
<li><%= link_to 'REPORT3', '#' %></li>
</ol>
</div>
</div>
<script type="text/javascript">
$(document).ready(function() {
$('#employees_select').change(function() {
$.ajax({
url: "<%= update_employee_movements_path %>",
data: { employee_id : $('#employees_select').val() },
dataType: "script"
});
});
$('#commendations_click').click(function() {
$.ajax({
url: "<%= commendations_path %>",
data: {
employee_id : $('#employees_select').val(),
employee_movement_id : $('#employee_movements_select').val()
},
dataType: "script"
});
});
});
</script>
app/controllers/reports_controller
class ReportsController < ApplicationController
before_filter :authenticate_user!
# GET /reports
def index
#employees = Employee.all
#employeemovements = EmployeeMovement.distinct_positions
end
def update_employee_movements
if params[:employee_id]
#employeemovements = [].insert(0, "Select Employee Movement")
else
employee = Employee.find(params[:employee_id])
#employeemovements = employee.employee_movements.map{ |a| [a.position, a.id] }.insert(0, "Select Employee Movement")
end
end
def commendations
emdates = EmployeeMovement.last_2_dates_obtained(params[:employee_movement_id])
date_from = emdates[0].date_obtained
date_to = emdates.length == 1 ? nil : emdates[1].date_obtained
emp = Employee.find(params[:employee_id])
#commendations = case date_to.nil?
when true then emp.commendations.this_day_onwards(date_from)
else emp.commendations.within(date_from, date_to)
end
end
end
What I'm trying to do here is, I'm creating a page filled with links and drop down lists that will serve as a Reports center. The idea is, each link will be catered by a controller. Each controller will be responsible in showing my PDF in the browser (through ThinReports, if you're curious).
The #employees_select change event is used for changing the value of the #employee_movements_select collection_select.
Now my problem is, how can i capture the value of both #employees_select and #employee_movements_select and pass them to my commendations action?
I tested link_to by hardcoding values, and it works (code below)
<%= link_to 'COMMENDATION', commendations_path(employee_id: 1, employee_movement_id: 12, format: 'pdf') %>
However, If I use javascript to push the values to my commendations action through the 'click' event, my commendations action will be called twice, thus an error occurs because the params[:employee_id] in the action is now blank.
By the way, I need those values because my commendations action needs it so I can populate my PDF report template.
Please help. Thanks a lot in advance!
UPDATE 1
-> Updated link_to:
<%= link_to 'COMMENDATION', '#', { id: 'commendations_click' } %>
-> Removed dataType: "script" in #commendations_click event handler
-> Updated url: in #commendations_click event handler
url: <%= commendations_path(format: 'pdf') %>
UPDATE 2 (RESOLUTION)
I tweaked my javascript to look something like this:
$('#commendations_click').click(function() {
event.preventdefault();
window.location = "<%=j commendations_path(format: 'pdf') %>" + "?employee_id=" + $('#employees_select').val() + "&employee_movement_id=" + $('#employee_movements_select').val();
});
Works perfect now.
Two things come to mind. You can wrap the two select lists within a form element and just do a submit. Everything inside the form will be submitted to your server and you can process the request and handle the redirect on the server side. The other thing you can do is to handle the commendations click event on the client side using jquery or something. Just bind to the click event of that link, grab the values of the two select lists and do whatever you want with it. Remember, link_to just gets rendered as plain old html links on the view. For e.g.
link_to "Profile", profile_path(#profile) gets rendered as Profile
I'm trying to build a RoR app, with three models:
Games that can be classified in a Sector(called GameSector) and in a subsector (called GameSubsector)
A sector is made up of many subsectors.
a Subsector.
Here are my basic models relationships:
models/game.rb
belongs_to :game_sector, :foreign_key => 'game_sector_id', :counter_cache => true
belongs_to :game_subsector, :foreign_key => 'game_subsector_id',:counter_cache => true
I use Active Admin to input the Games, Sectors or subsectors information.
I have a very basic form when I create a game and I'd just like to make the second select drop down (game_subsector) adjust on the choice of the first select (gamesector) so that I don't the the whole (very long) list of game_subsectors but only those that belong to the game_sector I choose.
After dozens of tests and techniques tried but failing, I've finally used this dev's advice that appeared relevant to me: http://samuelmullen.com/2011/02/dynamic-dropdowns-with-rails-jquery-and-ajax/.
But it still does not work.
Here is the form on Active Admin which is located on admin/game.rb
ActiveAdmin.register Game do
menu :parent => "Campaigns", :priority => 1
controller do
with_role :admin_user
def game_subsectors_by_game_sector
if params[:id].present?
#game_subsectors = GameSector.find(params[:id]).game_subsectors
else
#game_subsectors = []
end
respond_to do |format|
format.js
end
end
end
form do |f|
f.inputs "Details" do
f.input :name
f.input :game_sector_id,
:label => "Select industry:",
:as => :select, :collection => GameSector.all(:order => :name),
:input_html => { :rel => "/game_sectors/game_subsectors_by_game_sector" }
f.input :game_subsector_id, :as => :select, :collection => GameSubsector.all(:order => :name)
f.actions
end
I feel the javascript is even maybe not fired.
The jquery I use is located on app/assets/javascript/admin/active_admin.js (I changed config so it loads this javascript when loading active admin pages)
jQuery.ajaxSetup({
'beforeSend': function(xhr) { xhr.setRequestHeader("Accept", "text/javascript"); }
});
$.fn.subSelectWithAjax = function() {
var that = this;
this.change(function() {
$.post(that.attr('rel'), {id: that.val()}, null, "script");
});
};
$("#game_game_sector_id").subSelectWithAjax(); //it it found in my view???
Finally I created a view as this expert adviced: in app/views/layout/ game_subsectors_by_game_sector.js.erb
$("#game_game_subsector_id").html('<%= options_for_select(#game_subsectors.map {|sc| [sc.name, sc.id]}).gsub(/n/, '') %>');
I'm not sure I have out it in the right place though...
What you need is:
Inspect with your web browser console your selects, and use a CSS selector to create a jQuery object for the sector select, something like:
$('#sector_select')
Append to this object a handler, so when it changes AJAX request is fired:
$('#sector_select').change(function(){
$.ajax('/subsectors/for_select', {sector_id: $(this).val()})
.done(function(response){ // 3. populate subsector select
$('#subsector_select').html(response);
});
});
See 3 in code, you need to inspect to get the right CSS selector. Be sure you are getting the expected response in the Network tab of your web browser inspector(if using Chrome).
You need a controller that answers in /subsectors/for_select, in the file app/controllers/subsectors_controller.rb:
class SubsectorsController < ApplicationController
def for_select
#subsectors = Subsector.where sector_id: params[:sector_id]
end
end
You need a view that returns the options to be populated app/views/subsectors/for_select.html.erb:
<% #subsectors.each do |ss| %>
<option value="<%= ss.id %>"><%= ss.name %></option>
<% end %>
You need a route:
get '/subsectors/for_select', to: 'subsectors#for_select'
I have this form that renders a partial for selecting a person's task.
new.html.slim:
= form_for(#person) do |f|
= f.text_field :name
= f.fields_for :assignment do |a|
= a.collection_select :project_id, Project.order(:name), :id, :name
div id="task_list"
= render 'shared/_task_select', a: a
= f.submit 'Save'
shared/_task_select.html.slim:
= a.collection_select :task_id, #tasks, :id, :name
Changing the project triggers a javascript that runs a "create_tasklist"-method in the PersonsController.
new.js:
$(document).ready(function() {
$('#person_assignment_attributes_project_id').change(function() {
var selection = $('#person_assignment_attributes_project_id').val();
$.ajax({
url: "/create_tasklist",
data: {
project_id : selection
},
dataType: "script"
});
});
});
The "create_tasklist"-method triggers a javascript that updates the partial:
create_tasklist.js.erb:
$("#task_list").html("<%= escape_javascript(render 'shared/task_list', a: a) %>");
Now this raises the error:
undefined local variable or method `a' for #<#<Class:0x42cd770>:0x4213ef0>
The same form works well when editing existing persons - until changing the project. Thus, FormBuilder "a" loses its definition through the javascript actions. I have to use a partial here because I want to do more stuff with it in a later stage. Any ideas how to get that variable to keep its defintion?
Edit 1:
I already tried adding this below the third line of new.html.slim:
javascript:
var a = "#{a}";
and then adding: a: a in the "data" declaration of new.js.
Edit 2:
With this the FormBuilder seems to pass through until the "create_tasklist"-method, but I do not know how to access it properly there. If I declare ´#a = params[:a]´ in the "create_tasklist"-method and then use (in create_tasklist.js.erb):
$("#task_list").html("<%= escape_javascript(render 'shared/task_list', a: #a) %>");
I recieve the error:
undefined method `collection_select' for "#<ActionView::Helpers::FormBuilder:0x4760400>":String
So the FormBuilder has become a string but a least it "got through" somehow. How can I leave it intact and is a more efficent way to achieve this?
I have an ajax mail form like
- form_remote_tag :url=>mails_path,:condition=>"validate_mail()", :html => {:id=>"mailform",:method => :post, :class => 'ajax',:style=>"padding:15px;" } do |form|
.gimmespace
Naam
%br
= text_field_tag :name,params[:name],:class=>"title required"
.gimmespace
Telefoonnummber
%br
= text_field_tag :phone,params[:phone],:size=>25,:class=>"title"
.gimmespace
Mailadres
%br
= text_field_tag :email,params[:email],:size=>30,:class=>"title required"
.gimmespace
Onderwerp
%br
= text_field_tag :subject,params[:subject],:class=>"title required"
.gimmespace
Boodschap
%br
= text_area_tag :message,params[:message],:rows=>10,:cols=>45,:class=>"title required"
.gimmespace
= submit_tag "Verstuur",:id=>"mailsubmit",:class=>"sendBtn"
%button{:onclick=>"$.fn.colorbox.close();"} Annuleer
The above code is in HAML. It makes an ajax form submit to a controller. I have to validate the fields before it makes a submit. So, I tried several stuff. I read this article http://hillemania.wordpress.com/2006/09/18/rails-ajax-pre-submit-form-validation/ and made a before callback to a test javascript function to validate. Here is the javascript validating function.
function validate_mail() {
alert("Your Name, Email, Subject and Body Content are Required !");
return false;
}
As per the above function, it returns false any way and the form should not get submitted but, it submits well ajaxically. Is there any other way, please help.
I think you want to use the :condition option instead of the :before option. Something like this:
- form_remote_tag :url=> mails_path, :condition => "validate_mail()", ...
Then, if your condition function returns false, the form shouldn't be submitted.
Of course, you'll need to modify your validate_mail() function actually test that each form field isn't blank:
if ($('name').value == '' || $('phone').value == '' || ... ) {
alert('Something was blank...');
return false;
} else {
return true;
}
My Prototype syntax is rusty - that should get you on the right track though.