I'm just getting started with the Braintree drop-in UI. Client side is javascript, server side is ruby on rails.
My system is very simple right now. The user is given a list of invoices that pertain to them. When the invoices have not yet been paid, they can click 'pay' and be taken to a new page that includes the Braintree Drop-In UI. My issue is this: When the user is taken to the 'pay' page, the drop-in UI does not appear. If the user reloads the page, the drop-in UI appears.
Why?
Here's some relevant code. It's pretty vanilla and not done yet - just roughed in.
From invoices/index.html.erb
<td>
<% if invoice.paid %>
<%= 'Paid' %>
<% else %>
<%= link_to 'Pay', payment_path(invoice.id) %>
<% end %>
</td>
From payments_controller:
class PaymentsController < ApplicationController
skip_before_action :verify_authenticity_token
before_action :set_invoice, only: [:pay, :checkout]
def pay
Braintree::Configuration.environment = :sandbox
Braintree::Configuration.merchant_id = 'merchant id'
Braintree::Configuration.public_key = 'public key'
Braintree::Configuration.private_key = 'private key'
gon.client_token = Braintree::ClientToken.generate()
end
def checkout
nonce = params[:payment_method_nonce]
result = Braintree::Transaction.sale :amount => #invoice.amount, :payment_method_nonce => "nonce-from-the-client"
if result.success?
message='Payment processed successfully. Thank you!'
#invoice.paid=true
#invoice.save
else
message='Unable to process payment. Reason = ' + result.message
end
redirect_to invoices_path, notice: message
end
private
def set_invoice
#invoice = Invoice.find(params[:id])
end
end
pay.html.erb:
<h1>Payments</h1>
<div>
<p>Invoice #: <%= #invoice.id %></p>
<p>Date: <%= #invoice.date %> </p>
<p>Description: <%= #invoice.description %> </p>
<p>Amount: <%= #invoice.amount %> </p>
</div>
<div class="form-container radius-box glassy-bg small-10 small-centered medium-8 large-6 columns">
<h2 class="mbs">New Transaction</h2>
<%= form_tag payments_checkout_path do%>
<%= hidden_field_tag 'id', #invoice.id %>
<p>Please enter your payment details:</p>
<div id="dropin"></div>
<%=submit_tag "Pay #{#invoice.amount}$", class: "button mt1" %>
<%end%>
</div>
and layouts/application.html.erb
<!DOCTYPE html>
<html>
<head>
<title>Actionable Software</title>
<%= include_gon %>
<%= stylesheet_link_tag "application", media: "all", "data-turbolinks-track" => true %>
<%= javascript_include_tag "application", "data-turbolinks-track" => true %>
<%= csrf_meta_tags %>
<script src="https://js.braintreegateway.com/v2/braintree.js"></script>
<meta name='viewport' content='width=device-width, initial-scale=1.0'>
</head>
<body>
<%= render 'layouts/header' %>
<div class='container'>
<% flash.each do |name, msg| %>
<%= content_tag(:div, msg, class: "alert alert-info") %>
<% end %>
<%= yield %>
</div>
</body>
</html>
I'm going to guess the script that populates that element isn't written in a way that works with Turbolinks.
Try opting that page or section out of turbolinks. Or just disable it completely and see if it fixes it.
I ran into the same issue in my app.. change on your index page
<%= link_to 'Pay', payment_path(invoice.id) %>
to
<%= link_to 'Pay', payment_path(invoice.id), data: { no_turbolink: true } %>
This should force the pay page to load completeley when you click through.
Related
In my program one Board can have many Sections. On Boards#show I list all Sections for this Board. A user can create, edit and delete Sections for Boards this user has created.
I use Pundit for my authorizations.
My problem is that after having added AJAX to the create Section action, my policy checks don't work anymore. The AJAX call is working fine in that Sections are added but the "Edit" and "Delete" links are only displayed after I reload the page.
Boards#show
<% if policy(#board).edit? %>
<p><strong>Create a new Section</strong></p>
<%= render 'sections/shared/form', board: #board, section: #section %>
<% end %>
<br>
<p><strong>Sections</strong></p>
<div id="sections">
<% #board.sections.order(id: :asc).each_with_index do |section, index| %>
<span><%= "#{index + 1}. #{section.title}" %></span>
<% if policy(section).edit? %>
<%= link_to "Edit", edit_board_section_path(#board, #board.sections[index]) %>
<% end %>
<% if policy(section).destroy? %>
<%= link_to("Delete", board_section_path(#board, #board.sections[index]), method: :delete) %>
<% end %>
<br>
<% end %>
</div>
Form partial
<%= simple_form_for([#board, #section], remote: true, authenticity_token: true) do |f| %>
<%= f.input :title, id: "section_title" %>
<%= f.submit "Save" %>
<% end %>
AJAX call
var newSection = "<span><%= "#{#board.sections.length}. #{#section.title}" %></span><br>";
var sections = document.getElementById('sections');
sections.insertAdjacentHTML('beforeend', newSection);
var sectionTitle = document.getElementById('section_title');
sectionTitle.value = '';
I think the problem is that the newly created Section isn't inserted into the loop and thus the policy cannot be checked. How could I refactor my code to solve this?
You should be able to render you HTML templates into your js.erb file. See the post from the DHH https://signalvnoise.com/posts/3697-server-generated-javascript-responses how to use this properly. It is an older post so maybe some things changed but you should know what to search for. But if it still works this way, you should be able to do something like this:
Extract section to a partial _section.html.erb
<span><%= "#{index + 1}. #{section.title}" %></span>
<% if policy(section).edit? %>
<%= link_to "Edit", edit_board_section_path(#board, #board.sections[index]) %>
<% end %>
<% if policy(section).destroy? %>
<%= link_to("Delete", board_section_path(#board, #board.sections[index]), method: :delete) %>
<% end %>
<br>
Use this partial also in your Boards#show file.
Render your partial in the js.erb file
var newSection = "<span><%=j render #section %></span><br>";
Something like this should work, but I don't use server generated javascripts so they could have changed some things. But hopefully it will help you at least with the direction.
I'm trying to add a form to a modal and then submit the form via JS format with remote: true but the form seems to be submitted as HTML instead, causing an unknown format issue. Any help would be appreciated.
Started POST "/create_deliv_extra" for 127.0.0.1 at 2014-06-16 20:38:17 -0400
Processing by DeliveriesController#create_deliv_extra as HTML
Completed 406 Not Acceptable in 21ms
ActionController::UnknownFormat
Form:
</br>
<%= form_tag create_deliv_extra_url, remote: true, class:"form-inline mb10 mt5", id:"extra_f_#{order.id}" do %>
<%= text_field_tag :description, #extra.description, placeholder: "Description", "data-provide"=>"typeahead", autocomplete: :off, "data-source"=>"#{Extra.all.pluck(:description).uniq}", class:"span4" %>
<% if order.cod == true || current_user.role == "Billing" || current_user.role == "admin" || current_user.role == "Exec" %>
<div class="input-prepend">
<span class="add-on">Amount $</span>
<%= text_field_tag :amount, #extra.amount, placeholder: "$000.00", class:"input-xs" %>
</div>
<% end %>
<div class="input-prepend">
<span class="add-on">Quantity</span>
<%= text_field_tag :quantity, #extra.quantity.present? ? "%g" % #extra.quantity : 1, class:"input-xxs" %>
</div>
<% next_d = order.deliveries.present? ? order.deliveries.maximum(:delivery_counter) + 1 : 1 %>
<div class="input-prepend">
<span class="add-on">From</span>
<%= text_field_tag :load_start, next_d, class:"input-xxxs" %>
</div>
<div class="input-prepend">
<span class="add-on">To</span>
<%= text_field_tag :load_end, next_d, class:"input-xxxs" %>
</div>
<%= select_tag :extra_type, options_for_select(["Per Yard","Per Load","Flat Fee"], #extra.extra_type), class:"input-small" %>
<%= hidden_field_tag :order_id, order.id %>
<%= hidden_field_tag :truck_id, #id %>
<%= button_tag "Add", class:"btn btn-danger" %>
<% end %>
Controller:
def create_deliv_extra
#order = Order.find(params[:order_id])
#id = params[:truck_id]
#extra = Extra.create(amount: params[:amount], extra_type: params[:extra_type], order_id: params[:order_id], description: params[:description], quantity: params[:quantity], load_start: params[:load_start], load_end: params[:load_end])
#extras = #order.next_deliv_extras.length > 1 ? "Extras: " + #order.next_deliv_extras : "No Extras"
respond_to do |format|
format.js
end
end
I've also tried adding format: :js in the form_tag but still receive the same error.
I know the question is old, but I got the same problem and found out my application.js was not requiring jquery_ujs. I added it to my application.js file:
//=require jquery
//=require jquery_ujs
Now remote links and forms work as expected :)
I believe your problem may stem from a form_tag being with another form (form_tag, form_for, or html form). If this is the case, just find a way within the html for the first form to begin and end and then start the second form after the first ends.
<%= form_for do %>
...
<%= button_tag "#" %>
<% end %>
<%= form_tag create_deliv_extra_url, remote: true, class:"form-inline mb10 mt5", id:"extra_f_#{order.id}" do %>
...
<%= button_tag "Add", class:"btn btn-danger" %>
<% end %>
TLDR: Trying to add a follow/unfollow button to the Users#Index action but when clicking on the button nothing happens.
I have followed Michael Hartl's Rails Tutorial app and now that it's complete I want to add extra functionality for the Follow/Unfollow button. Currently, you can only follow/unfollow a user after visiting their profile page thru the Users Show action. I've attempted to expand this functionality to the Index page of the Users controller so that instead of having to visit each user's profile page in order to follow/unfollow them, a follow button will also appear next to their name in the Index view.
The code that works initially for the follow/unfollow button on the Users Show action:
users_controller.rb
https://gist.github.com/anonymous/9602598
show.htlm.erb for users view
https://gist.github.com/anonymous/9602616
_follow_form.htlm.erb partial for users view
<% unless current_user?(#user) %>
<div id="follow_form">
<% if current_user.following?(#user) %>
<%= render 'unfollow' %>
<% else %>
<%= render 'follow' %>
<% end %>
</div>
<% end %>
_follow.html.erb partial for users view
<%= form_for(current_user.relationships.build(followed_id: #user.id),
remote: true) do |f| %>
<div><%= f.hidden_field :followed_id %></div>
<%= f.submit "Follow", class: "btn btn-large btn-primary" %>
<% end %>
_unfollow.html.erb partial for users view
<%= form_for(current_user.relationships.find_by(followed_id: #user.id),
html: { method: :delete },
remote: true) do |f| %>
<%= f.submit "Unfollow", class: "btn btn-large" %>
<% end %>
create.js.erb inside of my relationships view
$("#follow_form").html("<%= escape_javascript(render('users/unfollow')) %>")
$("#followers").html('<%= #user.followers.count %>')
destroy.js.erb inside of my relationships view
$("#follow_form").html("<%= escape_javascript(render('users/follow')) %>")
$("#followers").html('<%= #user.followers.count %>')
index.html.erb inside of the users view
<%= render #users %>
_user.html.erb partial inside of users view
<li>
<%= gravatar_for user, size: 52 %>
<%= link_to user.name, user %>
<% if current_user.admin? && !current_user?(user) %>
| <%= link_to "delete", user, method: :delete,
data: { confirm: "You sure?" } %>
<% end %>
I've tried a few different approaches that so far have been fruitless
First I tried simply rendering the follow_form partial inside of the _user partial just like it's done for the User Show view
_user.html.erb partial inside of users view
<%= render 'follow_form' if signed_in? %>
this resulted in the following error: NoMethodError in Users#index "undefined method `id' for nil:NilClass" and it hilights the following line of code inside of the follow_form partial
<% if current_user.following?(#user) %>
After mucking around with the variables and the controller for a few hours I finally managed to get the buttons to show properly on the index page with the following code inside of the _user.html.erb partial
<li>
<%= gravatar_for user, size: 52 %>
<%= link_to user.name, user %>
<% if current_user.admin? && !current_user?(user) %>
| <%= link_to "delete", user, method: :delete,
data: { confirm: "You sure?" } %>
<% end %>
<% if current_user.following?(user) %>
<%= form_for(#current_user.relationships.find_by(followed_id: #users),
html: { method: :delete },
remote: true) do |f| %>
<%= f.submit "Unfollow", class: "btn btn-large" %>
<% end %>
<% else %>
<%= form_for(current_user.relationships.build(followed_id: #users),
remote: true) do |f| %>
<div><%= f.hidden_field :followed_id %></div>
<%= f.submit "Follow", class: "btn btn-large btn-primary" %>
<% end %>
<% end %>
</li>
This code however, only shows the correct follow/unfollow buttons for each user but when you click a button nothing happens. I also attempted to edit the JS files with the following code
create.js.erb
$("#follow_form").html("<%= escape_javascript(render('users/unfollow')) %>")
$("#user").html("<%= escape_javascript(render('users/unfollow')) %>")
$("#followers").html('<%= #user.followers.count %>')
destroy.js.erb
$("#follow_form").html("<%= escape_javascript(render('users/follow')) %>")
$("#user").html("<%= escape_javascript(render('users/follow')) %>")
$("#followers").html('<%= #user.followers.count %>')
This didn't have any effect.
The more I tinker with different parts of the code the more it's confusing me. Here is my relationships controller for good measure.
relationships_controller.rb
class RelationshipsController < ApplicationController
before_action :signed_in_user
def create
#user = User.find(params[:relationship][:followed_id])
current_user.follow!(#user)
respond_to do |format|
format.html { redirect_to #user }
format.js
end
end
def destroy
#user = Relationship.find(params[:id]).followed
current_user.unfollow!(#user)
respond_to do |format|
format.html { redirect_to #user }
format.js
end
end
end
I know it's alot but if anyone can help shed some light on my situation I would be very grateful. This is my first venture outside of tutorials and I figured it would be a good idea to try and add features to an already working project instead of start something from scratch.
Just in case anybody was on this question and was still looking for the correct Ajax code. This works with the existing controller and nothing else will have to be changed.
create.js.erb
var indexed_form = "follow_form_<%=#user.id%>"
if ( document.getElementById(indexed_form) ){
var jquery_indexed_form = "#" + indexed_form
$(jquery_indexed_form).html("<%= escape_javascript(render('users/unfollow')) %>");
}
else {
$("#follow_form").html("<%= escape_javascript(render('users/unfollow')) %>");
$("#followers").html('<%= #user.followers.count %>');
}
destory.js.erb
var indexed_form = "follow_form_<%=#user.id%>"
if ( document.getElementById(indexed_form) ){
var jquery_indexed_form = "#" + indexed_form
$(jquery_indexed_form).html("<%= escape_javascript(render('users/follow')) %>");
}
else {
$("#follow_form").html("<%= escape_javascript(render('users/follow')) %>");
$("#followers").html('<%= #user.followers.count %>');
}
_user.html.erb
<div class="col-md-2">
<% unless current_user?(user) %>
<% form_id = user.id.to_s %>
<div id="follow_form_<%= form_id %>">
<% if current_user.following?(user) %>
<%= form_for(current_user.active_relationships.find_by(followed_id: user.id),
html: { method: :delete },
remote: true) do |f| %>
<%= f.submit "Unfollow", class: "btn" %>
<% end %>
<% else %>
<%= form_for(current_user.active_relationships.build, remote: true) do |f| %>
<div><%= hidden_field_tag :followed_id, user.id %></div>
<%= f.submit "Follow", class: "btn btn-primary" %>
<% end %>
<% end %>
</div>
<% end %>
</div>
This is my first post. Yay! Hope it helps someone!
Use the following code in _user.html.erb partial:
<li>
<%= gravatar_for user, size: 52 %>
<%= link_to user.name, user %>
<% if current_user.admin? && !current_user?(user) %>
| <%= link_to "delete", user, method: :delete,
data: { confirm: "You sure?" } %>
<% end %>
<% if current_user.following?(user) %>
<%= form_for(current_user.relationships.find_by(followed_id: user.id),
html: { method: :delete },
remote: true) do |f| %>
<%= f.submit "Unfollow", class: "btn btn-large" %>
<% end %>
<% else %>
<%= form_for(current_user.relationships.build(followed_id: user.id),
remote: true) do |f| %>
<div><%= f.hidden_field :followed_id %></div>
<%= f.submit "Follow", class: "btn btn-large btn-primary" %>
<% end %>
<% end %>
</li>
I made couple of changes to the code in form_for method call in 2 places:
#current_user should be current_user.
Secondly, followed_id: #users should be followed_id: user.id
I have troubles with nicEdit.
Framework is ruby 2.0.0 / rails 4.0.1
When in localhost, works but only if you upload the page twice.
But when deploy in Heroku, it does not work at all.
I followed this example up to the line.
I have a niEdit.js under ../vendor/assets/javascripts
Here is my full form:
<%= javascript_include_tag 'nicEdit' -%>
<%= simple_form_for(#recipe) do |f| %>
<%= f.error_notification %>
<div class="field">
<%= f.label "Elige un cromo" %><br />
<%= f.file_field :chrome %>
</div>
<div class="form-inputs">
<%= f.association :user, label_method: :name, collection: User.where(name: current_user.name), :label => "Cociner#" %>
<%= f.association :category, :label => "CategorÃa", label_method: :plato_category, collection: Category.all %>
<%= f.input :plato %>
<%= f.input :minutos %>
<script type="text/javascript">
bkLib.onDomLoaded(function() { nicEditors.allTextAreas() });
</script>
<div class="well well-small">
<p>Tejemaneje</p>
<%= f.text_area :tejemaneje, :rows => 10, :style => 'width: 700px' %>
</div>
</div>
<p>
</p>
<%= f.button :submit, "Receta", :class => "btn btn-success" %>
<% end %>
What should I do different for it to work fully both on localhost and heroku? Thanks.
PARTIAL SOLUTION:
I moved nicEdit.js under /assets/javascript and the script is now running, but it does not matter if inside NicEdit.js this line is
iconsPath : '/assets/nicEditorIcons.gif' and the icons under /assets/images/nicEditorIcons.gif, they do not display. The same for /assets/nicEditorIcons.gif
I moved the icons under /assets/javascripts and change the line to
iconsPath : '.../nicEditorIcons.gif'
And I also tryed to put the icons under /assets/nicEditorIcons.gif with the icons ther. Nothing works.
Does Heroku have a special place for icons? Do I have to change the script call? Any help?
My comment app works ,but the only problem is whenever i refresh the page the comments disappear.In the log it shows the body is inserted in the comments table(it is saved).What am i doing wrong here?Any help will be appreciated.Thank you in advance.
View#show
<div id="comments"></div>
<%= form_for :comment,:remote => true,:url=> {:controller=>"comments",:action=>"create"},:html => { :id => 'new-comment'} do |f| %>
<%= f.text_area(:body) %>
<div class="errors"></div>
<%= f.submit "post" %>
<% end %>
Comment controller
class CommentsController < ApplicationController
respond_to :js
def create
#deal=Deal.find(1)
#comment =#deal.comments.build(params[:comment])
#comment.save
respond_with( #comment, :layout => !request.xhr? )
end
def show
#comment=Comment.all
#deal=Deal.find(1)
#comment=#deal.comments
end
end
create.js.erb
$('#comments').append("escape_javascript(#comment.body)");
I don't see where your comments are being display in your show template.
How about something like this?
<div id="comments">
<% #comments do |comment| %>
<%= comment.body %>
<% end %>
</div>
<%= form_for :comment,:remote => true,:url=> {:controller=>"comments",:action=>"create"},:html => { :id => 'new-comment'} do |f| %>
<%= f.text_area(:body) %>
<div class="errors"></div>
<%= f.submit "post" %>
<% end %>
Note, you need to set #comments in the controller or use another method of getting comments, e.g. #view = View.find(params[:id]) and <%= #view.comments.each do |comment| %>...
I guess the comment has a belongs_to relationship with the post that is not assigned.
In your form you should add
<%= f.hidden_field :post_id, #post.id %>
If you want to play by the book, post_id should be attr_protected and instead assign it manually in the comments controller
#comment = Comment.new(params[:comment])
#comment.post_id = params[:comment][:post_id]
#comment.save