How to make a dead link reporter?
I want to make a button on my website that a user can click on to report at external dead link. The link do I have in my link column that is in my item table.
I want to create an simple email notice that have the ID of the item and the link. I was thinking creating an form and some sort of controller that could handle the form.
My view should look something like this:
<% for items in @items %>
<%= simple_form_for @items] do |f| %>
<%= f.hidden field :id, :value => 'item.id' %>
<%= f.hidden field :url, :value => 'item.link %>
<%= f.button :submit, :value => 'report broken link' %>
<% end %>
<% end %>
The id and the url inputs should not be viewable just a link like "report broken开发者_运维知识库 link". A controller should take the two params and send me an email.
How do I create a simple dead external links reporter?
Your question could be a bit more specific, but you probably want to use something like Net:HTTP
and something similar to this:
uri = URI.parse(url)
response = nil
begin
Net::HTTP.start(uri.host, uri.port) do |http|
response = http.head(uri.path.size > 0 ? uri.path : "/")
end
rescue => e
...
end
# handle redirects if you need to
if response.is_a?(Net::HTTPRedirection)
...
end
if response.code == '404'
...
end
For a simple broken link reporter I would just utilize a helper for dry code, like the following :
module ApplicationHelper
def report_broken_link_for( id )
link_to "report broken link", {:controller => "reporting", :action => "report_broken_link", :id => id}, :class => "broken_link_reporter_link", :remote => true
end
I suggest that you wouldn't need to use a form, but if you feel so inclined you can modify the helper. Add/remove parameters as you see fit, but the item id would probably be simple enough, you can lookup the actual link in the back end. Simply use it in your views :
<% @items.each do |item| %>
<%= link_to item.url %>
<%= report_broken_link_for item.id %><br/>
<% end %>
Use some ujs to make sure they don't repost it :
$('.broken_link_reporter_link')
.live('ajax:success', function(evt, data, status, xhr){
$(this).replaceWith("thanks!");
});
Hope this helps.
It seems that you simply want your users to be able to report dead links without doing the actual check. You do not need a form for that, a
link_to "text", :controller=>ctrl, :action=>actname, :id=>item_id, :method=>:post
should be sufficient, not to mention that it would look nicer and cause less problems with styling, etc. In Rails 3 this would look different, I think :remote=>true
instead of :method=>:post
.
The controller/action you call with this link_to
should construct and send mail (read about ActionMailer
). In fact, this controller can actually check whether the link is dead or not, as M. Kohl suggested.
Note that you can pass more than :controller
, :action
and :id
. All of what you pass will be available in the params
array in the controller/action.
As you are explaining it, you just need a mailer that sends user reported broken links, nothing unusual.
Other options include creating a rake task which iterates over your links, and reports broken ones, with code similar to Michael Kohl. This doesn't require a user triggered mailer:
# In lib/tasks/ (rake links:test)
require 'net/http'
namespace :links do
desc "Test for broken links in DB."
task :test => :environment do |t, args|
count = 0
Entries.all.each do |e|
count += 1
# is_live? implementation is similar to Michael's
puts "ERR: #{e.url} (Entry id: #{e.id})" unless is_live?(e.url)
end
puts "#{count} tested links."
end
end
精彩评论