Monday 30 April 2012

Tutorial – Ruby on Rails hosted on Amazon cloud

Enough said about RoR
Enough said about Amazon EC2
This tutorial is about deploying an ROR app over Amazon Cloud infrastructure. It will give a walk through on commands and concepts so that you can integrate Github, Amazon production env and your local development env for your ROR app. It assumes you already have an Amazon web services account and will finish up with having ROR server up and running on EC2.
  • Get Familiar – You need to know about most of the amazon products listed on their site. Each of the product has a specific functionality and you need to know them to understand the machinery. Here is the minimum set of products that you need to know: https://www.amazon.com/ec2. Make sure you understand the dashboard before you start playing around.
  • Install command line tools – Either you play around with the dashboard or use command line tools for better efficiency. There are numerous tutorials to learn them, I followed this one:
  • Create your instance - You need to choose an ami (amazon instance image) and deploy on EC2. There are lot of good tutorials that show how to do this. At the end of this step, you should have a running instance on amazon EC2 and should appear in the dashboard. Here are some pointers:
  • SSH to your instance – You will get a private key from amazon and you will have to use it to ssh to your instance.  Before you can ssh to your instance, you will need to open up security permissions at amazon side. For that, go to dashboard -> security groups -> default. Add another entry allowing ssh from all the IPs (0.0.0.0/0). Your command to ssh from your terminal will be something like this
    • ssh -i <path_to_private_key> ubuntu@domain-name
    • domain-name is the ‘public dns’ of your instance. You can read it on your dashboard -> Instances or by executing API command: ec2-describe-instances
    • I prefer to run ssh-add <path_to_priavte_key> which tells ssh to add the key permanently in its db and you can then simply run: ssh ubuntu@domain-name without worrying about private key option. (ssh-add -t 99999999 <path_to_priavte_key> to add it for long enough time)
  • Prepare the instance – Now you can access to your crude VM which has nothing but ubuntu (or OS as per your ami). Let us install the basic packages needed. There are lots of tutorials again. I referred following tutorials to prepare the VM and install rails, ruby and gem.
  • Clone source code – Now we will get our source code from git repository.
    • Get code: git clone https://gitUser:gitPasswd@github.com/repoUser/repo.git
    • Install dependencies: bundle install
    • README: Start other services such as sphinx, etc. mentioned in app’s READMEs
    • db initialization: rake db:create; rake db:migrate; rake db:seed
    • Git settings:
      • git config –global user.name “username”
      • git config –global user.email “emailid@xyz.com”
      • git config –global core.autocrlf input
  • Connect your development env to ec2 – I prefer to directly push my code from local environment to production environment. To achieve this, add production environment repository as a remote repository in your local development box.
    • git remote add ec2 ssh://<user>@<amazon-public-dns>/~<user>/<repo-path>
    • Now you can run git push ec2 master to push your code from your local environment to amazon production.
  • Start the server – Start your rails server on amazon VM (rails server) and test out if you can open http://public-dns-of-instance.com:3000 from your browser. Here are the next steps:
    • You will need to change the port from 3000 to 80. But 80 port (in fact any port < 1024) can only be opened by root. In this case, I do not want to run “sudo rails server” and hence I prefer configuring IPtables on amazon VM so that they forward all request at port 80 to port 3000. Here is the command:
    • sudo iptables -t nat -A PREROUTING -p tcp –dport 80 -j REDIRECT –to-port 3000
  • Set the Domain – Last step is to add your own domain name so that customers can open your application by the domain name you like. This is a little tricky part and you should understand what is elastic IP. After you understand the idea behind elastic IP, here is what you need to do.
    • Generate an elastic IP from your dashboard -> Elastic IPs. Bind that IP to your instance ID which is running your server. This maps your VM to a static IP (or elastic IP) that you just generated.
    • Go to your dns provider (e.g. godaddy.com) and configure your DNS settings there. Add this elastic IP as A name and allow 24 hours for your domain to get bound to the elastic IP. After that your web server is all configured.
  • Snapshot - Create a snapshot of your volume in the dashboard. You can create volumes out of this snapshot if anything goes wrong with your current one.
I will add more details on this. For now, have fun. Feel free to pour in questions, suggestions or comments.

http://www.golygon.com/2010/11/tutorial-ruby-on-rails-hosted-on-amazon-cloud/

Thursday 26 April 2012

Rails: Power to the filters


Rails: Power to the filters

Rails before_filters in controllers can help you keep your code DRY.
I have coded cases where all action functionality was included in 2-3 before_filters.
I’ll try to showcase some of the methods that work for me.

Authentication

The most commonly used before_filter should be that of authentication, and since this is global you can place it in you ApplicationController.
01.class ApplicationController < ActionController::Base
02.session :session_key => '_fortytwo_session_id'
03. 
04.before_filter :fetch_logged_user
05. 
06.def authenticate
07.unless @logged_user
08.#unauthorized access
09.redirect_to login_url, :status => 401
10.return false
11.end
12.end
13. 
14.def fetch_logged_user
15. 
16.unless session[:user_id].blank?
17.@logged_user = User.find(session[:user_id])
18.end
19. 
20.rescue ActiveRecord::RecordNotFound
21.end
22. 
23.end
Now, in every action, in every controller we have a @logged_user object. If it’s not nil , then we have an authenticated user.
So if we want to restrict access to authenticated users in a certain controller for some actions, we just need a before_filter for the authenticate function.
1.class UsersController < ApplicationController
2.before_filter :authenticate:except => :login
3.endre

CRUD Operations

Models usually have the common CRUD actions (new, edit, update, delete, create), and some other actions that operate on a specific model record. If you add authentication and probably authorization (only the owner of a blog post can change his content for example), things can get complicated. Unless…
01.class BlogController < ApplicationController
02.#authenticate is in our ApplicationController
03.before_filter :authenticate:except => :show
04.before_filter :fetch_post:only => [:show:edit:update:delete]
05.before_filter :authorise_as_owner:only => [:edit:update:delete]
06. 
07.private
08. 
09.def fetch_post
10.@post = Post.find(params[:id])
11.rescue ActiveRecord::RecordNotFound
12.#there is no such post
13.flash[:alert] = "Got lost?"
14.redirect_to error_url, :status => 404
15.return false
16.end
17. 
18.def authorise_as_owner
19.unless @post.user_id == @logged_user.id
20.#You don't belong here. Go away.
21.flash[:alert]  = "Mind your own business"
22.redirect_to error_url, :status => 401
23.end
24.end
25. 
26.end
If you are using roles, you can extend the authorisation behaviour (so that admins can edit any post) like this:
1.def authorise
2.unless @post.user_id == @logged_user.id || @logged_user.is_admin?
3.#You don't belong here. Go away.
4.flash[:alert]  = "Mind your own business"
5.redirect_to error_url, :status => 401
6.end
7.end
http://www.fortytwo.gr/blog/6/Rails-Power-to-the-filters