Using JQuery and Rails to generate preview of link

1.9k views Asked by At

what I am interested in doing is implementing a basic version of a link preview tool in JQuery and RoR (similar to what Facebook has). A user types a url in an input field. A jquery function monitors what is typed (using keyup), and when a valid url is typed (without the user submitting anything), the jquery function calls a rails function, which uses the Nokogiri gem to search and return preview content (such as title, any images, etc). That content is then returned to the jquery function and displayed below the input box.

What I am unclear about in all this is how data is passed from the jquery function to the rails one and back.

To make things concrete, let's say I just want to retrieve the title of the url being typed.

In my JQuery function I am using keyup to monitor for things like spaces, returns, etc. At this point I am not validating the typed url (I can do that later)

var text; 

$("#text").keyup(function(e) {

    if(e.which == 13 || e.which == 32 || e.which == 17 || ) {

        text = $("text").val();
        $.get('/linkPreview', {text: text}, function(answer) {

            $("previewTitle").html(answer);
        }           
            )
    }

This is where I am unsure how to proceed. I am using the .get Jquery method (is this the right one?) to call the rails function, and passing the text as the typed url.

I then match the '/linkPreview' to the linkPreview action in my pages controller, in my routes file:

match '/linkPreview', :to => 'pages#linkPreview'

I am also unsure about reading and passing JSON data in a rails function. I am trying to use respond_to and respond_with functions, but am not sure if this is correct (I use Nokogiri gem to extract title from the url's html):

def linkPreview
    respond_to :json
@url = params[:text]
doc = Nokogiri::HTML(open(@url))
@title = doc.css(title)
respond_with(@title)
end

As I am new to RoR and JQuery, I would greatly appreciate any help with regards to the proper way of calling a rails function from JQuery, passing JSON data from one to the other, and any other resources that my address these topics! I was also wondering if there's any recommended way of debugging a flawed script (my code obviously doesn't work, but I'm not sure where to start in looking for the mistakes).

Thanks a ton!

3

There are 3 answers

1
Adam Albrecht On

I think you're on the right track. Assuming you want to return a title and perhaps an image from the requested page (like Facebook does), I would probably do something like this.

def link_preview
  url = params[:url]
  preview = LinkPreviewParser.parse(url) # returns a Hash
  respond_with(preview) #respond_with converts a hash to JSON
end

Then, for the sake of organizing and testing the code more cleanly, move the parsing code into a separate class

app/models/link_preview_parser.rb

class LinkPreviewParser
  def self.parse(url)
    doc = Nokogiri::HTML(open(@url))
    page_info = {}
    page_info[:title] = doc.css(title) # assuming this is right - I didn't check
    # ... more parsing logic if needed ...
    return page_info
  end
end

This will return a json object that looks like this: {'title': 'Some Webpage'}, which should be fairly easy to handle in your javascript. And you could add other attribute as needed.

I haven't tested this out, but I believe it should work. This is the simplest approach, but if you expect a lot of traffic, there is a serious downside to this. Since the request from the browser would have to wait on another request from the server to the external website, you're going to have a lot of requests simply waiting around doing nothing. So ideally, you'd want to do this in an asynchronous manner. This is quite a bit more work, so choose whatever works best for you at the moment.

0
Daniel Friis On

I know this is an old question, however I managed to get the following code to work:

controller.rb

def linkpreview
    url = params[:url]
    preview = LinkPreviewParser.parse(url) # returns a Hash
    respond_to do |format|
        format.json { render :json => preview }
    end
end

app/models/link_preview_parser.rb

class LinkPreviewParser
  def self.parse(url)
    doc = Nokogiri::HTML(open(url))
    page_info = {}
    page_info[:title] = doc.css('title').text
    return page_info
  end
end

routes.rb

match '/linkpreview', to: 'items#linkpreview'

linkpreview.js

$(document).ready(function() {
  $("#url-submit").on('click', function() {
    var link = $("#url");
    setTimeout(function() {
      var text = $(link).val();
      // send url to service for parsing
      $.ajax('/linkpreview', {
        type: 'POST',
        dataType:'json',
        data: { url: text },
        success: function(data, textStatus, jqXHR) {
          $("#item_title").val(data['title']);
        },
        error: function() { alert("error"); }
      }); 
    }, 100);
  });
});
0
Michael Andrews On

Might want to checkout the link_preview gem we developed at Socialcast: https://github.com/socialcast/link_preview it handles a lot of the backend processing for you