Figuring out which element triggered request - ruby-on-rails

I am currently working on a large project developed by 5 people.
The problem is that every time I load a particular page, I get a stray POST request along with the GET request for the page. The page contains no forms though a fair amount a jquery has been used.
Started POST "/my_profile" for 127.0.0.1 at 2012-03-06 21:34:23 +0530
ActionController::RoutingError (No route matches "/my_profile"):
Is there a way to find out which element or script triggered this POST request other than going through the entire code which is divided into 20 partials and 2 javascripts ?

If you're using Firefox, check out the Firebug plugin. The net panel will allow you to easily track down any POST / GET requests for a given page load.

You might try [binding_of_caller][1], caller or possibly [set_trace_func][2].
Dzone Snippets offers a robust way of using caller:
def caller_method_name
parse_caller(caller(2).first).last
end
def parse_caller(at)
if /^(.+?):(\d+)(?::in `(.*)')?/ =~ at
file = Regexp.last_match[1]
line = Regexp.last_match[2].to_i
method = Regexp.last_match[3]
[file, line, method]
end
end
Or you could do caller.inspect and just look at the raw output.
Binding_of_caller is a bit more involved and may be overkill for what you want but check it out if caller is not what you need. Same with set_trace_func.

Related

AJAX + Rails: Should I Use a GET or a PUT When Creating a Route?

My question: When using AJAX within Rails, from a best practice standpoint, does the HTML verb that I use (e.g., get) to define a route matter? Is it OK to basically always use get?
Context: In my Rails App, I've built the following:
When a user selects an HTML checkbox, that triggers a JQuery listener that lives in a file inside of /app/assets/javascripts.
This .js file makes an AJAX call to a controller/action: foos#bar. My JS passes an ID into the action.
To route this request, I've added the following to routes.rb: get "/foos/bar" => "foos#bar". This tells my App which controller/action should process the AJAX call.
The controller/action handles this request just fine. The action grabs the ID as a URL parameter, updates the relevant model object, and finally returns back a 200 to the JS AJAX caller.
This all works great! No issues -- nothing to troubleshoot here.
My question is: In the example above, is it appropriate to define a get route within routes.rb to process this AJAX request? Or, is that bad practice? Should I instead be defining a put, since conceptually that is what I'm doing in this workflow (i.e., I'm updating an existing object)? I'm worried that, while this all works perfectly, I'm breaking some fundamental MVC routing standards.
If you are updating a resource it will most likely be a PATCH update, which means you aren't completely replacing the resource but are just updating it (this is why PATCH is the default HTTP method for updates in Rails, instead of PUT).
So, yes, you are violating RESTful conventions by using GET to update a resource. GET is only used to fetch a representation of a resource...without changing it in any way.

RoR Magazine specific category routes

I would like to create routes on RoR for a media website with different sections of articles (ecology, legal, economy, etc...)
I would like my url goes like this
root/magazine/ecology/name-of-articles
(nothing corresponding on rails routing/rails guide, nested and collection routes don't fit for me I think)
here is my try:
get 'magazine/ecology/name-of-article', to: 'articles#name_of_article'
views: folders articles => magazine => ecology => file: name_of_article
controller: articles
But it's not working ...answer from rails below
Thx for your help
ActionController::UnknownFormat at
/magazine/actualite-juridique/legislation-ce-qui-change-en-2017
ArticlesController#legislation_2017 is missing a template for this
request format and variant.
request.formats: ["text/html"] request.variant: []
NOTE! For XHR/Ajax or API requests, this action would normally respond
with 204 No Content: an empty white screen. Since you're loading it in
a web browser, we assume that you expected to actually render a
template, not nothing, so we're showing an error to be extra-clear. If
you expect 204 No Content, carry on. That's what you'll get from an
XHR or API request. Give it a shot.
Although you don't seek a solution and what you trying to do as discussed in the comments, I don't at all recommend that. I would like to suggest a better method. Take it if you like it.
Run a migration add a column to your articles model which will save the name of section it belongs to.
Then, your routes:
get 'magazine/:section/:name' => 'articles#name_of_article' , as: 'sectioned_article'
In your controller:
def name_of_article
#article = Article.where("section iLike '%#{params[:section]}% AND name iLike '%#{params[:name]}%'").first
end
This way, you can create as many sections/articles you want without code changes.
It also gives you customisation option and also reduces your work to great extent which you are ready to do [but now you can utilize that time partying ;)].

Rails 4 routing of partial tacks on to existing path

I am new to writing rails applications. I am using Rails 4.2.0 with Ruby 2.0.0p598.
I have modified the cascading select implementation found here and used it to create new Products (has model and main controller) linked to Productgroups and Productsubgroups (both have their models, but no controllers) as the cascade levels. The implementation employs some javascript which upon a change to the first dropdown select, the second dropdown is cleared of data, and then an AJAX call is made to a specific URL to update the tags for the productsubgroups dropdown using a partial (_productsubgroup.html.erb).
To do this, the following route set up in routes.rb
get '/update_productsubgroups' => 'products#update_productsubgroups'
so that i can map to the appropriate controller and action. This is all quite fine. I can see the AJAX request in the development.log as where it is querying the database for productgroup #2 (ignore the trailing "&_1422575676984"):
Started GET "/products/update_productsubgroups?productgroup_id=2&_=1422575676984"
The problem, occurs when I use the same content from new.html.erb within the context of editing a product in edit.html.erb. Based on the fact that the routes.rb uses the "resouces :products" directive, I end up with a url for editing products in the form /product/:id/edit (e.g. /product/2/edit to edit the product with ID 2). When I try to use my cascading dropdowns, everytime I make a change to the first selection, I don't get a change in the second dropdown. I can see the request going to the development.log file as:
Started GET "/products/1/update_productsubgroups?productgroup_id=2&_=1422578544393"
and the error that comes up immediately after the request is:
ActionController::RoutingError (No route matches [GET] "/products/1/update_productsubgroups"):
Q1 - Why does the partial just tack on to the existing URL rather than simply make a pure request to /products/update_productsubgroups as is the case when I create a product from the product controller's 'new' action?
Q2 - Is there any way for me to create a rule in the routes.rb to map things correctly?
Q3 - When I try to create a new route as
get '/products/:id/update_productsubgroups', as 'products#update_productsubgroups'
I get an error in the webserver log as:
ArgumentError ('products/:id' is not a supported controller name
I have dug around and I am not certain how to interpret this. Can anyone help explain this so that the last couple of hours can prove a useful learning experience? Unfortunately, most pages either discuss routing for Rails 3 or just refer to the 'Routing from the outside in' page and that seems to confuse me even more because I'm specifying things as expected, namely :controller/:id/:action.
DOH!
I had a relative path specified for my AJAX call! I looked everywhere except the coffeescript file.
$.ajax 'update_productsubgroups',
should be
$.ajax '/update_productsubgroups',

Rails Rspec and capybara - using to perform a, um, sort of test

Check edit at bottom of page
My boss has a sitemap up- it's basically just every route as a link, with a button to click that says "valid?" or "ignore" which will mark it valid or ignore it on the page.
He asked me to manually go through and click each link, test that page isn't a 500 or 404, and then mark it valid if it isn't.
This seems silly to me, as it is basically just a user facing test for working routes.
I could, in the same time, write out routing specs in Rspec for all those, but I guess he wants some sort of documentation that this is happening on the front end for himself and users.
I was thinking a fun way to work around this boring clicking would be to do it with some programming WHILE writing the specs. Makes him happy, and also adds actual value and test to the app that can be reused.
Is there a way to, in a spec, write something like:
links = page.all('a.routing-links)
link.each do |link|
link.click
if page status != 404 || 500
Link.find(id).update_attribute("verified", true)
end
end
I tried putting that in my spec, but when link.click hits an incorrect route, it stops the test (which makes sense, as that route is broken and this is a test.
What I'd like is to be able to take that error and use it to update the attribute of my model.
Am I going about this completely wrong? Any better ideas or inspiration?
Thanks
Edit
I agree with the poster who said this is better left to a script or rake task.
I'm a bit lost on how to write a script that will go to a page, find every link, record its status_code, and then find and update a model. Any suggestions or tips? Ideally it would be run within in the application, so that I could have access to my models and controllers.
Thanks
Personally I wouldn't actually put this in a spec since you're not actually expecting anything to fail.
Instead I'd create a quick script, or even rake task to run through the links as you described.
That being said, this article: http://agileleague.com/2012/12/rails-3-2-custom-error-pages-the-exceptions_app-and-testing-with-capybara/ details how to bypass the normal fail in these circumstances, namely:
In your config/environments/test.rb
config.consider_all_requests_local = false
config.action_dispatch.show_exceptions = true
Though this would affect all tests, which is quite possibly not what you want.
Also, a minor thing that you'd probably figure out in no time when testing this - you'll either need to revisit the list page after clicking the link, or rather relying on link clicks, you could visit the href instead which would be a bit quicker.
links = page.all('a.routing-links')
link.each do |link|
visit link[:href]
if page.status != 404 || 500
Link.find(id).update_attribute("verified", true)
end
end
I haven't tested that, so not sure if it would work like that, but you should be able to get the idea.

My web site need to read a slow web site, how to improve the performance

I'm writing a web site with rails, which can let visitors inputing some domains and check if they had been regiestered.
When user clicked "Submit" button, my web site will try to post some data to another web site, and read the result back. But that website is slow for me, each request need 2 or 3 seconds. So I'm worried about the performance.
For example, if my web server allows 100 processes at most, that there are only 30 or 40 users can visit my website at the same time. This is not acceptable, is there any way to improve the performance?
PS:
At first, I want to use ajax reading that web site, but because of the "cross-domain" problem, it doesn't work. So I have to use this "ajax proxy" solution.
It's a bit more work, but you can use something like DelayedJob to process the requests to the other site in the background.
DelayedJob creates separate worker processes that look at a jobs table for stuff to do. When the user clicks submit, such a job is created, and starts running in one of those workers. This off-loads your Rails workers, and keeps your website snappy.
However, you will have to create some sort of polling mechanism in the browser while the job is running. Perhaps using a refresh or some simple AJAX. That way, the visitor could see a message such as “One moment, please...”, and after a while, the actual results.
Rather than posting some data to the websites, you could use an HTTP HEAD request, which (I believe) should return only the header information for that URL.
I found this code by googling around a bit:
require "net/http"
req = Net::HTTP.new('google.com', 80)
p req.request_head('/')
This will probably be faster than a POST request, and you won't have to wait to receive the entire contents of that resource. You should be able to determine whether the site is in use based on the response code.
Try using typhoeus rather than AJAX to get the body. You can POST the domain names for that site to check using typhoeus and can parse the response fetched. Its extremely fast compared to other solutions. A snippet that i ripped from the wiki page from the github repo http://github.com/pauldix/typhoeus shows that you can run requests in parallel (Which is probably what you want considering that it takes 1 to 2 seconds for an ajax request!!) :
hydra = Typhoeus::Hydra.new
first_request = Typhoeus::Request.new("http://localhost:3000/posts/1.json")
first_request.on_complete do |response|
post = JSON.parse(response.body)
third_request = Typhoeus::Request.new(post.links.first) # get the first url in the post
third_request.on_complete do |response|
# do something with that
end
hydra.queue third_request
return post
end
second_request = Typhoeus::Request.new("http://localhost:3000/users/1.json")
second_request.on_complete do |response|
JSON.parse(response.body)
end
hydra.queue first_request
hydra.queue second_request
hydra.run # this is a blocking call that returns once all requests are complete
first_request.handled_response # the value returned from the on_complete block
second_request.handled_response # the value returned from the on_complete block (parsed JSON)
Also Typhoeus + delayed_job = AWESOME!

Resources