Ruby Sinatra URL keeps appending - ruby

I have four buttons, and everytime I click the button it should send a post request (I'll show my code below).
This is my books controller.rb
post '/all?' do
#books = # Books here
haml :'books/index', locals: {books: #books}
end
post '/fantasy?' do
#fantasy = # Fantasy books here
haml :'books/index', locals: {fantasy: #fantasy}
end
And this is my index.haml file:
%form{method: 'POST', action: "books/all"}
%input.btn.btn-md{type: 'submit', value: 'All Books'}
%form{method: 'POST', action: "books/fantasy"}
%input.btn.btn-md{type: 'submit', value: 'Fantasy'}
However, what happens is the following:
(1) URL: localhost:8080/books
(2) I click on the all button
(3) URL: localhost:8080/books/all
(4) I click on the fantasy button
(5) URL: localhost:8080/books/books/fantasy
This is the problem - how can I get it so on the second button click, it goes to localhost:8080/books/fantasy instead? I'm sure its a simple fix just not sure how. Thanks.

I think the recommended way is to use absolute paths with the addition of the url helper. This should better future-proof your code in case it is mounted in a sub folder or behind a reverse proxy.
%form{method: 'POST', action: url("/books/fantasy")}

Related

Ruby Sinatra Routes Not Being Recognized

I'm having some issues with Sinatra not recognizing my routes (all other routes work fine, it is just this specific set of 4 routes). The layout is: in my views, the user clicks on a filter button which corresponds to the route of /all /inactive /active or /expired, and should filter out based on this selection.
Here is the index.haml filters:
%form{method: 'GET', action: "/showings/all"}
%input#all.btn.btn-md.btn-secondary{type: 'submit', value: 'All'}
%form{method: 'GET', action: "/showings/active"}
%input#active.btn.btn-md.btn-secondary{type: 'submit', value: 'Active'}
%form{method: 'GET', action: "/showings/inactive"}
%input#inactive.btn.btn-md.btn-secondary{type: 'submit', value: 'Inactive'}
%form{method: 'GET', action: "/showings/expired"}
%input#expired.btn.btn-md.btn-secondary{type: 'submit', value: 'Expired'}
%form{method: 'DELETE', action: "/showings/delete", style: "padding-left: 45%"}
%input#delete.btn.btn-md.btn-danger{type: 'submit', value: 'Delete Expired Hosted Screenings'}
However, in my showings_routes.rb file in my controllers folder, I tried these route but they never get registered (I've tried restarting the web app):
get '/all' do
p "ALL ROUTES"
haml :'showings/index'
end
get '/active' do
p "ACTIVE ROUTES"
haml :'showings/index'
end
get '/inactive' do
p "INACTIVE ROUTES"
haml :'showings/index'
end
get '/expired' do
p "EXPIRED ROUTES"
haml :'showings/index'
end
delete '/delete' do
p "DELETE ROUTES"
redirect '/showings'
end
I'm planning on adding the filter logic later, the routes are just not being recognized when I click one of the buttons or navigate to localhost:3000/showings/all. I'm just confused because this is a built web app, so all the other routes in the showings_routes.rb file work fine (like /create /submit etc.)
Is there a thing that I'm missing when I'm handling my routes here in my application?

How redirect from controller side after Ajax call in Rails 6?

I want to know if it's possible to redirect with controller from an ajax request in Rails 6 ?
I tried to use
redirect_to "url"; return and render :js => "window.location.reload" don't work for me :(
Thank you for your help :)
This works for me:
window.location.href = '/path'
Example:
$.ajax({
url: uri,
type: "POST",
data: form,
dataType: 'json',
processData: false,
contentType: false
}).done(function(e) {
window.location.href = '/project_proposals'
})
Do it in your controller.
render js: "window.location='#{goal_path(#goal)}';"
Ideally you'll want to keep as much business logic out of your JS as possible for rails apps. You also can't cleanly use your route helper methods in js. You can however setup your "redirect" in your controller.
app/view/controllers/goals/adopt_controller.rb
# :nodoc:
class Goals::AdoptController < ApplicationController
def update
# business logic....
# "redirect" the client
render js: "window.location='#{goal_path(#goal)}';"
# or make a reusable js view. this will search a wide variety of possible file names. In this case it'll match /app/view/appliation/redirect.js.erb
# #to = goal_path(#goal)
# render 'redirect'
# the above lets rails guess what you want to do. this is a bit more explicit to only render this view is the client can accept a js response. Other scenarios will throw an error
# #to = goal_path(#goal)
# respond_to do |format|
# format.js { render 'redirect' }
# end
end
end
/app/view/appliation/redirect.js.erb
window.location='<%= escape_javascript to %>';

Rails 3 Image upload form submitting with http instead of AJAX

I am working on a form to submit it by AJAX instead of http.
This is the form :
<%= form_for(:image, :remote => true, :url => {:controller=> 'questions',:action => 'upload'},:multipart => true) do |f| %>
<%= f.file_field :image, :onchange => "$(this).parents('form').submit();" %>
<% end %>
I have set the :remote => true option above and submitting the form with an onchange event . I have the following code in controller :
def upload
if request.xhr?
#image = Image.new(params[:image])
#image.save
respond_to do |format|
format.js { render :layout=>false }
end
else
render :text => 'Request Wasnt AJAX'
end
end
My action renders the text everytime , the request does not seem to be AJAX style despite the remote tag being set (it appears correctly even in the final HTML). I can't figure out where I am going wrong with this . I have tested it in the latest browser version of FF and Chrome , so I don't think it's a browser issue. Any ideas ?
Update : I did some more debugging attempts . The issue is with the file field , if I replace the file field with text field , the request is AJAX (everything else remaining same) . But with a file field it always sends a non AJAX request.
Note : Overall objective is to upload an image via AJAX request, with the response rendering nothing, no HTML, no redirection, no reload of the page.
Got it to work by installing the Remotipart gem . To upload image files using ajax form submission , this is the only way . Find the git here :https://github.com/JangoSteve/remotipart
JQuery form.sumbit() submits a form the normal way (Not Ajax). You have to do it differently:
$('#submitButton').click( function() {
$.ajax({
url: 'some-url',
type: 'post',
dataType: 'json',
data: $('#myForm').serialize(),
success: function(data) {
// ... do something with the data...
}
});
});

How to debug the ajax request in django

I know that for example:
def home(request):
if request.method == 'POST':
k = 'p' % 1
return HttpResponse(simplejson.dumps(dict()), mimetype='application/javascript')
else:
k = 'p' % 1
return render_to_response('index.html',locals());
url(r'^$', 'app.home'),
If I use the browser to visit the home page, django will return a debug page to me and show that there is an error in k = 'p' % 1
But if I use the $.ajax() to send a post to this view, the console of chrome only show POST http://(some url here):8000/ 500 (INTERNAL SERVER ERROR)
so is there any good way to debug the second case?
I have no idea about debug the django, is there anybody have better way to debug the django?
thanks
have a look at sentry (and the corresponding raven)
(the Network tab should be able to show you the request and the corresponding response. i believe newer django versions even give you a more bare-bones version of the stacktrace if the request was ajax)
There is an error CallBack in ajax. It will spew out the actual error.
$.ajax({
type: 'POST',
url: '{% url 'url_name_for_your_view_here' %}',
data: {'csrfmiddlewaretoken': '{{csrf_token}}'},
dataType: "text",
success: function(response) {
//do something here if everything goes well
},
error: function(rs, e) {
alert(rs.responseText); //throw actual error, just for debugging purpose
alert('Oops! something went worng..'); // alert user that something goes wrong
}
});
There are a number of third party apps make debugging ajax easier. I've used this in the past with success: https://github.com/yaniv-aknin/django-ajaxerrors
Or if you prefer not use an app, chrome developer tools will likely be enough, as is suggested in this thread: Django: Are there any tools/tricks to use on debugging AJAX response?

Devise + Rails 3.0.4 ends session after AJAX request

I have an action triggered by an AJAX request generated by Ajax.InPlaceEditor or InPlaceCollectionEditor like this:
new Ajax.InPlaceCollectionEditor('agent_email', 'inspections/<%= #inspection.id %>/update_field',
{
collection: [<% #agents.each do |agent| %>
'<%= agent.email %>',
<% end %>],
okText: 'Update',
cancelText: 'Never mind',
savingText: 'Updating...'
});
At the other end, the action contains this:
def update_field
--some code here--
if success
puts "stored change"
render :text => result
else
puts "did note change store"
render :text => inspection.errors.to_json, :status => 500
end
end
Once any of the render methods are reached, the session expires, and next time the user send a request, Devise sends them to the logon on page.
Even though I am exempting update_field from authentication (before_filter :authenticate_user!, :except => :update_field), the session is still getting reset.
I have looked at the answer at a very similar question at Devise session immediately expiring on .js call [AJAX], but it is not solving my particular problem.
Any ideas?
I got this to work by getting the code from http://weblog.rubyonrails.org/2011/2/8/csrf-protection-bypass-in-ruby-on-rails (prototype-snippet.js):
/*
* Registers a callback which copies the csrf token into the
* X-CSRF-Token header with each ajax request. Necessary to
* work with rails applications which have fixed
* CVE-2011-0447
*/
Ajax.Responders.register({
onCreate: function(request) {
var csrf_meta_tag = $$('meta[name=csrf-token]')[0];
if (csrf_meta_tag) {
var header = 'X-CSRF-Token',
token = csrf_meta_tag.readAttribute('content');
if (!request.options.requestHeaders) {
request.options.requestHeaders = {};
}
request.options.requestHeaders[header] = token;
}
}
});
... within a Javascript block in my application.html.erb:
<script type="text/javascript">
(... the code from above)
</script>
Also don't forget to add:
<%= csrf_meta_tag %>
in the same file towards the top (if not already there).
The document "CSRF Protection Bypass in Ruby on Rails" explains why this works.

Resources