Tag Archives: rails

Setting up Nginx with Unicorn for Rails

I have moved away from using Thin to using Unicorn in production for a number of reasons

Some articles to convince you of the same thing.

  1. Unicorn is Unix
  2. Unicorn Power
  3. Most important for me was the ability of Unicorn master and worker processes to respond to Unix signals. This means, zero downtime deployments.

You need more convincing? Let me know and we can talk!

So with that out of the way, let’s see how you can configure nginx to work with unicorn.

  1. Install nginx via the package manager. (For AMI Ec2:sudo yum install nginx, For Ubuntu : sudo apt-get install nginx)
  2. Use this template for nginx unicorn configuration and then fill in only the required details.
  3. Note that the way it differs from thin configuration is by giving the server value as a location to the socket.
worker_processes 1;
user nobody nogroup;

pid /tmp/nginx.pid;
error_log /tmp/nginx.error.log;

events {
  worker_connections 1024; # increase if you have lots of clients
  # Set this to on if you have more than 1 working processes
  # This will allow only one child to watch the pollset and accept
  # a connection to a socket
  accept_mutex off; # "on" if nginx worker_processes > 1
}

http {
  include mime.types;
  default_type application/octet-stream;
  access_log /tmp/nginx.access.log combined;

  # This tells Nginx to ignore the contents of a file it is sending
  # and uses the kernel sendfile instead
  sendfile on;

  # Set this to on if you have sendfile on
  # It will prepend the HTTP response headers before
  # calling sendfile()
  tcp_nopush on;

  # This disables the "Nagle buffering algorithm" (Nginx Docs)
  # Good for websites that send a lot of small requests that
  # don't need a response
  tcp_nodelay off;

  gzip on;
  gzip_http_version 1.0;
  gzip_proxied any;
  gzip_min_length 500;
  gzip_disable "MSIE [1-6]\.";
  gzip_types text/plain text/html text/xml text/css
             text/comma-separated-values
             text/javascript application/x-javascript
             application/atom+xml;

  upstream unicorn_server {
   # This is the socket we configured in unicorn.rb
   server unix:/var/rails/testapp/tmp/sockets/unicorn.sock »
   fail_timeout=0;
  }

  server {
    listen 80;
    client_max_body_size 4G;
    server_name _;
    keepalive_timeout 5;

    # Location of our static files
    root /home/ec2-user/testapp/public;

    location / {
      proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
      proxy_set_header Host $http_host;
      proxy_redirect off;

      # If you don't find the filename in the static files
      # Then request it from the unicorn server
      if (!-f $request_filename) {
        proxy_pass http://unicorn_server;
        break;
      }
    }    error_page 500 502 503 504 /500.html;
    location = /500.html {
      root /home/ec2-user/testapp/public;
    }
  }
}

If you have unicorn correctly configured then start unicorn, restart nginx and you should be set.

Advertisements

Image upload to the PageDown (markdown) editor via AJAX in Rails

I have been using the updated version of the WMD markdown editor called as Pagedown for a blog engine, and wanted to have an Image Upload functionality.

If you take a look at Pagedown wiki, you will realize it has a very limited set of API’s – but has the one we need , a hook for ‘insert Image button’ called as insertImageDialog.

I had the following requirements for achieving Image Upload

  1. Markdown Editor (Pagedown)
  2. Bootstrap
  3. Rails + AJAX Uploads of Images.
  4. Preview of the image + ability to select size, before inserting into post.

Markdown Hook for Image Button.

The example from the Pagedown wiki, shows how the insertImageDialog.hook can be used.

editor.hooks.set("insertImageDialog", function (callback) {
      alert("Please click okay to start scanning your brain...");
      setTimeout(function () {
          var prompt = "We have detected that you like cats. Do you want to insert an image of a cat?";
          if (confirm(prompt))
              callback("http://icanhascheezburger.files.wordpress.com/2007/06/schrodingers-lolcat1.jpg")
          else
              callback(null);
      }, 2000);
     return true; // tell the editor that we'll take care of getting the image url
    });

This tells us to register a plugin on the insertImageDialog hook that returns true (which tells the editor not to create its own dialog). so the callback method is the one which returns the actual URL of the uploaded images.

I recommend you try the above code, so that you know how the hooks are working within your editor.

Twitter Boostrap Markdown

This project is a pagedown (markdown) editor, styled for bootstrap. Take a look at the demo. I have made use of these pagedown code.

I would advice you to take a look at the source of this demo, to understand how all components tie-up.

RAILS + AJAX Uploads of Images + Image Preview and Re-sizing.

For doing AJAX uploads using a jQuery plugin and carrier-wave turned out to be easier because I went ahead with ‘jquery-fileupload-rails’ . Though there can be some challenges if you are using nested_forms. (This Rails-casts should help you figuring out the integration http://railscasts.com/episodes/381-jquery-file-upload).

With all the components laid above, I can walk you through the approach I took…

1. First Create a Modal for the dialog to appear on click of the insert Image..

<!-- Modal -->
<div id="fileModal" class="modal hide fade" tabindex="-1" role="dialog" aria-labelledby="fileModalLabel" aria-hidden="true">
 <div class="modal-header">
 <button type="button" class="close" data-dismiss="modal" aria-hidden="true">×</button>
 <h3 id="fileModalLabel">Upload Images</h3>
 </div>
 <div class="modal-form">
 <div class="tabbable tabs-left"> <!-- Only required for left/right tabs -->
 <ul class="nav nav-tabs">
 <li class="active"><a href="#tab1" data-toggle="tab">Upload</a></li>
 <li><a href="#tab2" data-toggle="tab">Enter URL</a></li>
 </ul>
 <div class="tab-content">
 <div class="tab-pane active" id="tab1">
 <%= f.file_field :photo %>
 <div class="preview" id="preview" >
 </div>
 </div>
 <div class="tab-pane" id="tab2">
 <p><input type="text" class="img-url" placeholder="Ex: http://yoursite.com/image.jpg" id="img-url" /></p>
 </div>
 </div>
 </div>
 </div> <!-- End of Modal-Body -->
 <div class="modal-footer">
 <button class="btn" data-dismiss="modal" aria-hidden="true">Close</button>
 <button class="btn" id="insert_image_post">Insert Image</button>
 </div>
</div>
<% end %>

The above modal code would render like this. Image Upload Markdown Bootstrap Rails

2. Bind the Pagedown hook to show the above modal.

This is the easy part, as you saw above how the insertImageDialog hook behaves, we would link these together as.

<script type="text/javascript">
 (function () {
 var converter = new Markdown.Converter();
 var help = function () { window.open('http://stackoverflow.com/editing-help'); }
 var editor = new Markdown.Editor(converter);
 editor.hooks.set("insertImageDialog", function (callback) {
 setTimeout(function () 
{
       $('#fileModal').modal();
        ...
        ...
       $("#insert_image_post").click(function(e) {
          e.preventDefault();
          if($(".upload-photo").length>0)
         {
            var images;
            $(".upload-photo").each(function(){
            images = "" + ($(this).filter("[src]").attr("src"));
          })
         callback(images);
       $('#upload_photo').fileupload();
        }
       else {
          var image=$("#img-url").val();
          callback(image);
        }
      $("#fileModal").modal('hide');
    });
 }, 0);
 return true; // tell the editor that we'll take care of getting the image url
 });
editor.run();
 })();
 </script>

To actually see how Ajax Jquery Uploads and carrierwave would interact you can look at the Railscasts http://railscasts.com/episodes/381-jquery-file-upload .

For the entire working code, look at the following repository.