Thursday, 11 October 2012

Has Many Through Relationship

Many-to-Many



There are two ways to build a many-to-many relationship.

The first way uses a has_many association with the :through option and a join model, so there are two stages of associations.

A has_many :through association is often used to set up a many-to-many connection with another model. This association indicates that the declaring model can be matched with zero or more instances of another model by proceeding through a third model.

For example, consider a medical practice where patients make appointments to see physicians. The relevant association declarations could look like this:


class Physician < ActiveRecord::Base
  has_many :appointments
  has_many :patients, :through => :appointments
end

class Appointment < ActiveRecord::Base
  belongs_to :physician
  belongs_to :patient
end

class Patient < ActiveRecord::Base
  has_many :appointments
  has_many :physicians, :through => :appointments
end

has_many :through

The collection of join models can be managed via the API.  for example, if you assign

physician.patients = patients

new join models are created for newly associated objects, and if some are gone their rows are deleted.

Automatic deletion of join models is direct, no destroy callbacks are triggered.

The has_many :through association is also useful for setting up "shortcuts" through nested has_many associations. For example, if a document has many sections, and a section has many paragraphs, you may sometimes want to get a simple collection of all paragraphs in the document. You could set that up this way:

class Document < ActiveRecord::Base
  has_many :sections
  has_many :paragraphs, :through => :sections
end

class Section < ActiveRecord::Base
  belongs_to :document
  has_many :paragraphs
end

class Paragraph < ActiveRecord::Base
  belongs_to :section
end

With :through => :sections specified, Rails will now understand:

@document.paragraphs


Friday, 5 October 2012

Understand Rails Authenticity Token!


Understand Rails Authenticity Token!


What happens:
When the user views a form to create, update, or destroy a resource, the rails app would create a random authenticity_token, store this token in the session, and place it in a hidden field in the form. When the user submits the form, rails would look for the authenticity_token, compare it to the one stored in the session, and if they match the request is allowed to continue.
Why this happens:
Since the authenticity token is stored in the session, the client can not know its value. This prevents people from submitting forms to a rails app without viewing the form within that app itself. Imagine that you are using service A, you logged into the service and everything is ok. Now imagine that you went to use service B, and you saw a picture you like, and pressed on the picture to view a larger size of it. Now, if some evil code was there at service B, it might send a request to service A (which you are logged into), and ask to delete your account, by sending a request to http://serviceA.com/close_account. This is what is known as CSRF (Cross Site Request Forgery).

If service A is using authenticity tokens, this attack vector is no longer applicable, since the request from service B would not contain the correct authenticity token, and will not be allowed to continue.
Notes: Keep in mind, rails only checks POST, PUT, and DELETE requests. GET request are not checked for authenticity token. Why? because the HTTP specification states that GET requests should NOT create, alter, or destroy resources at the server, and the request should be idempotent (if you run the same command multiple times, you should get the same result every time).
Lessons: Use authenticity_token to protect your POST, PUT, and DELETE requests. Also make sure not to make any GET requests that could potentially modify resources on the server.


Thursday, 4 October 2012

Evil Twin Controllers

Evil Twin Controllers


As an application grows and matures, the number of things that occur in its controllers increases. Even if you remain diligent and move as much functionality from the controllers into the models as possible, there will inevitably be functionality that remains in the controllers, such as alternative formats available for APIs (JSON, XML, and so on).

For Example, examine the following controller for Songs, which exposes an XML API:

class SongsController < ApplicationController
  before_filter :grab_album_from_album_id

  def index
    @songs = songs.all
    respond_to do |format|
      format.html
      format.xml { render :xml => @songs }
    end
 end

  def show
    @song = songs.find(params[:id])
    respond_to do |format|
      format.html
      format.xml { render :xml => @song }
    end
  end  

  def new
    @song = songs.new
    respond_to do |format|
      format.html
      format.xml { render :xml => @song }
    end
  end 

  def edit
    @song = songs.find(params[:id])
  end 

  def create
    @song = songs.new(params[:song])
    respond_to do |format|
      if @song.save
         format.html do
            redirect_to(@song, :notice => 'Song was successfully created.')
         end
         format.xml do 
           render :xml => @song, :status => :created, :location => @song
         end
       else
         format.html { render :action => "new"}
         format.xml do
           render :xml => @song.errors, :status => :unprocessable_entity
         end
       end
    end
  end

  def update
    @song = songs.find(params[:id])
    respond_to do |format|
      if @song.update_attributes(params[:song])
        format.html do
           redirect_to(@song, :notice => "Song was successfully updated.")
        end
       format.xml { head :ok }
      else
         format.html {render :action => "edit" }
         format.xml do
           render :xml => @song.errors, :status => :unprocessable_entity
         end
      end
    end
  end

  def destroy
    Song.find(params[:id]).destroy
    respond_to do |format|
     format.html { redirect_to(songs_url)}
     format.xml { head :ok}
    end
  end

  private

  def songs
   @album? @album.songs : Song
  end

  def grab_album_from_album_id
    @album = Album.find(params[:album_id]) if params[:album_id]
  end
end


Rails 3 introduced a new set of methods called responders that abstract the boilerplate responding code so that the controller becomes much simpler. In the following example, the preceding Songs controller is rewritten using responders:

class SongsController < ApplicationController
  respond_to :html, :xml
  before_filter :grab_album_from_album_id

  def index
    @songs = songs.all
    respond_with(@song)
  end

  def show
    @song = songs.find(params[:id])
    respond_with(@song)
  end

  def new
    @song = songs.new
     respond_with(@song)
  end

  def edit
    @song = songs.find(params[:id])
    respond_with(@song)
  end  

  def create
    @song = songs.new(params[:song])
     if @song.save
        flash[:notice] = "Song was successfully created."
     end
     respond_with(@song)
  end

  def update
    @song  = songs.find(params[:id])
     if @song.update_attributes(params[:song])
      flash[:notice] = "Song was successfully updated."
     end
     respond_with(@song)
  end

  def destroy
    @song = Song.find(params[:id])
    @song.destroy
    respond_with(@song)
  end

  private

   def songs
     @album ? @album.songs : Song
   end

   def grab_album_from_album_id
     @album = Album.find(params[:album_id]) if params[:album_id]
   end
end


Paperclip Sample App


Paperclip Sample App

Step : 1
Lets First Set Your RVM

Step: 2
Let's get started by creating a new Rails application:

$ rails new paperclip-sample-app -d mysql
create create README.rdoc create Rakefile create config.ru create .gitignore create Gemfile create app create app/assets/images/rails.png create app/assets/javascripts/application.js create app/assets/stylesheets/application.css create app/controllers/application_controller.rb create app/helpers/application_helper.rb create app/mailers create app/models create app/views/layouts/application.html.erb create app/mailers/.gitkeep create app/models/.gitkeep create config create config/routes.rb create config/application.rb create config/environment.rb create config/environments create config/environments/development.rb create config/environments/production.rb create config/environments/test.rb create config/initializers create config/initializers/backtrace_silencers.rb create config/initializers/inflections.rb create config/initializers/mime_types.rb create config/initializers/secret_token.rb create config/initializers/session_store.rb create config/initializers/wrap_parameters.rb create config/locales create config/locales/en.yml create config/boot.rb create config/database.yml create db create db/seeds.rb create doc create doc/README_FOR_APP create lib create lib/tasks create lib/tasks/.gitkeep create lib/assets create lib/assets/.gitkeep create log create log/.gitkeep create public create public/404.html create public/422.html create public/500.html create public/favicon.ico create public/index.html create public/robots.txt create script create script/rails create test/fixtures create test/fixtures/.gitkeep create test/functional create test/functional/.gitkeep create test/integration create test/integration/.gitkeep create test/unit create test/unit/.gitkeep create test/performance/browsing_test.rb create test/test_helper.rb create tmp/cache create tmp/cache/assets create vendor/assets/javascripts create vendor/assets/javascripts/.gitkeep create vendor/assets/stylesheets create vendor/assets/stylesheets/.gitkeep create vendor/plugins create vendor/plugins/.gitkeep run bundle install


Step : 3

In your gem file add paperclip gem for image upload

gem "paperclip", :git => "git://github.com/thoughtbot/paperclip.git"



Step : 4


After write add paperclip in your gem file

$ bundle install


Step : 5

I will just create a new "user" model with string columns for the name and email address:



$ rails g scaffold user name:string email:string

   invoke  active_record
      create    db/migrate/20121004063219_create_users.rb
      create    app/models/user.rb
      invoke    test_unit
      create      test/unit/user_test.rb
      create      test/fixtures/users.yml
      invoke  resource_route
       route    resources :users
      invoke  scaffold_controller
      create    app/controllers/users_controller.rb
      invoke    erb
      create      app/views/users
      create      app/views/users/index.html.erb
      create      app/views/users/edit.html.erb
      create      app/views/users/show.html.erb
      create      app/views/users/new.html.erb
      create      app/views/users/_form.html.erb
      invoke    test_unit
      create      test/functional/users_controller_test.rb
      invoke    helper
      create      app/helpers/users_helper.rb
      invoke      test_unit
      create        test/unit/helpers/users_helper_test.rb
      invoke  assets
      invoke    coffee
      create      app/assets/javascripts/users.js.coffee
      invoke    scss
      create      app/assets/stylesheets/users.css.scss
      invoke  scss
      create    app/assets/stylesheets/scaffolds.css.scss



Step : 6
Now we need to generate the database columns necessary for Paperclip on our new model object using rails


rails g paperclip user avatar
      create  db/migrate/20121004063230_add_attachment_avatar_to_users.rb


Step: 7
create table and run migration

$ rake db:create

$ rake db:migrate


==  CreateUsers: migrating ====================================================
-- create_table(:users)
   -> 0.7840s
==  CreateUsers: migrated (0.7841s) ===========================================

==  AddAttachmentAvatarToUsers: migrating =====================================
-- change_table(:users)
   -> 0.8870s
==  AddAttachmentAvatarToUsers: migrated (0.8872s) ============================




Step: 7

In your user model add attr_accessible of avatar

class User < ActiveRecord::Base
  attr_accessible :email, :name, :avatar
end


Step: 8
You can see that Paperclip generator created columns in the users table called "avatar_file_name", "avatar_content_type", "avatar_file_size", and "avatar_updated_at". Now we have our database schema setup.  The next step is to just modify the code that was generated for us by the scaffolding and make the changes necessary for paperclip.

The first thing to do is to add a line to the user model and indicate that it has a file attachment called "avatar". To do this, open app/models/user.rb and just add this one line:


class User < ActiveRecord::Base
  attr_accessible :email, :name, :avatar
  has_attached_file :avatar
end



And then edit the new user form (app/views/users/new.html.erb) and add a file field to use to upload files. There are actually two code changes you need to make: 

First you need to set the HTML form to encode the uploaded file data (and other fields) using MIME multiple part syntax, and then second you need to actually add the file upload field. Here's the finished new.html.erb file with these two changes in bold:

<%= form_for(@user, :html => {:multipart => true}) do |f| %>


and  second, add this p tag


<div class="field">
   <%= f.label :avatar %><br />
   <%= f.file_field :avatar %>
  </div>



Step: 9

Now if we run our application we can upload an image file and attach it to a user:





if we submit the form, the image file will be uploaded to the server and saved on the file system. By default, paperclip saves files inside a "system" folder it creates in your Rails app's public folder. 



Step: 10
I'm almost done; now i just need to display the uploaded image somewhere; the simplest thing to do is just to add an image tag to the users show page.


<p>
  <b>Avatar:</b>
  <%= image_tag @user.avatar.url %>
</p>




Step: 11
now we can see the image for our new user










































Wednesday, 26 September 2012

Amazon Web Services


Amazon Web Services

Amazon Web Services (AWS) is a collection of remote computing services (also called web services) that together make up a cloud computing platform.

The AWS gems have been designed to provide a robust, fast, and secure interface to Amazon EC2, EBS, S3, SQS, SDB, and CloudFront.

  • Aws::EC2 -- Interface to Amazon EC2 (Elastic Compute Cloud) and the associated EBS (Elastic Block Store)
  • Aws::S3 and Aws::S3Interface -- interface to Amazon S3 (Simple Storage Service)
  • Aws::Sqs and Aws::SqsInterface -- interface to Amazon SQS (Simple Queue Service)
  • Aws::SdbInterface -- interface to Amazon SDB (SimpleDB).
  • Aws::AcfInterface -- interface to Amazon CloudFront, a content distribution service
  • Aws::ElbInterface 00 interface to Amazon Load Balancing service
  • Aws::MonInterface -- interface to Amazon CloudWatch monitoring service
  • Aws::Iam -- for AWS Identity and Access Management

Getting Started with the AWS SDK for Ruby

Get Set Up

To get set up, you must sign up for Amazon Web Services, get your AWS credentials, and set up your environment.

Sign Up for AWS Products

Before you can begin, you must sign up for each AWS product you want to use. The sample included in the SDK uses Amazon S3, so we'll use that product as an example here.

To sign up for a product

  1. Go to the home page for the product, for example aws.amazon.com/s3
  2. Click the sign-up button on the top right corner of the page.
  3. Follow the on-screen instructions. If you don't already have an AWS account, you are prompted to create one as part of the sign-up process.
AWS sends you a confirmation e-mail after the sign-up process is complete. You can view your current account activity or manage your account at any time, by going to aws.amazon.com and clicking the Account tab.

Get Your Credentials

To use the AWS SDK for Ruby, you need your AWS Access Key ID and Secret Access Key.

To get your AWS Access Key ID and Secret Access Key

  1. Click Account and then click Security Credentials. The Security Credentials page displays ( you might be prompted to log in).
  2. Scroll down to Access Credentials and make sure the Access Keys tab is selected. The AWS Access Key ID appears in the Access Key column.
  3. To view the Secret Access Key, click Show.

Important! Your Secret Access Key is a secret, which only you and AWS should know. It is important to keep it confidential to protect your account. Store it securely in a safe place. Never include it in your requests to AWS, and never e-mail it to anyone. Do not share it outside your organization, even if an inquiry appears to come from AWS or Amazon.com. No one who legitimately represents Amazon will ever ask you for your Secret Access key.

Set Up Your environment

The AWS Ruby gem runs on Ruby 1.8.7 and later. If you have an older version of Ruby, RVM is a great way to get started using the latest version.

Install the SDK

To install the AWS Ruby gem, just enter:
gem install aws-sdk


Run the Samples
Now that you’ve installed the gem, you can run the samples, which you can find in our GitHub repository:
$ git clone git://github.com/amazonwebservices/aws-sdk-for-ruby.git
$ cd aws-sdk-for-ruby/samples/


The subdirectories of the samples directory contain several code samples that you can run. These samples demonstrate basic usage of the SDK features.

To run the Amazon S3 Sample

  1. Create a file named config.yml in the samples directory as follows:
# Fill in your AWS Access Key ID and Secret Access Key
access_key_id : REPLACE_WITH_ACCESS_KEY_ID
secret_access_key: REPLACE_WITH_SECRET_ACCESS_KEY


  1. Run a sample script with the Ruby interpreter. For example, to run the s3/upload_file.rb sample:
$ echo “Hello, World!” > helloworld.txt
$ ruby s3/upload_file.rb unique-bucket-name helloworld.txt



To use the AWS ORM in a Rails 3 application

  1. Install the gem:
$ gem install aws-sdk


  1. Start a new Rails project
$ gem install rails
$ rails new myapp
$ cd myapp/


  1. Add the following line to your Gemfile:
gem ‘aws-sdk’


  1. Install dependencies:
$ bundle install


  1. Now you need to configure AWS with your access credentials. You can use a config initializer script (e.g. config/Initializers/aws.rb) and use Ruby to configure your AWS credentials:
AWS.config({
 :access_key_id => ‘REPLACE_WITH_ACCESS_KEY_ID’
 :secret_access_key => ‘REPLACE_WITH_SECRET_ACCESS_KEY’,
})

or you can create a config/aws.yml file that will also be automatically loaded with Rails:

# Just like the config/database.yml this file requires an entry for each environment

development:
 access_key_id : REPLACE_WITH_ACCESS_KEY_ID
 secret_access_key: REPLACE_WITH_SECRET_ACCESS_KEY
test:
 <<: *development
production:
 <<: *development



  1. Create app/models/my_record.rb as follows:
class MyRecord < AWS::Record::Base
 string_attr :name
end


  1. Create the SimpleDB domain:
$ rails console
> MyRecord.create_domain

Now, you can play around with the model by creating some records and querying them:
> MyRecord.find(:all).to_a
=> []
> MyRecord.new(:name => “The first one”).save
=> true
> MyRecord.new(:name => “The second one”).save
=> true
> MyRecord.where(‘name like ?’, “%first%”).count
=> 1

Exit the rails console before continuing to the next step:
> exit


  1. Generate a scaffold controller for your model:
$ rails generate scaffold_controller MyRecord name:string
$ rails server



  1. Add a route to your scaffold controller in config/routes.rb:
Myapp::Application.routes.draw do
# add this line:
resources :my_records
end


  1. Now, you can create records in the browser at localhost:3000/my_records.



Amazon SimpleDB (beta)

Amazon SimpleDB is a highly available and flexible non-relational data store that offloads the work of database administration. Developers simply store and query data items via web services requests and Amazon SimpleDB does the rest.

Unbound by the strict requirements of a relational database, Amazon SimpleDB is optimized to provide high availability and flexibility, with title or no administrative burden. Behind the scenes, Amazon SimpleDB creates and manages multiple geographically distributed replicas of your data automatically to enable high availability and data durability.

You can change your data model on the fly, and data is automatically indexed for you. With Amazon SimpleDB, you can focus on application development without worrying about infrastructure provisioning, high availability, software maintenance, schema and index management, or performance tuning.

Amazon SimpleDB Functionality

Amazon SimpleDB provides a simple web services interface to create and store multiple data sets, query your data easily, and return the results. your data is automatically indexed, making it easy to quickly find the information that you need. These is no need to predefine a schema or change a schema if new data is added later. And scale-out is as simple as creating new domains, rather than building out new servers.

To use Amazon SimpleDB you:

  1. Build your data set
    • Choose a Region for your Domain(s) to optimize for latency, minimize costs, or address regulatory requirements. Amazon SimpleDB is currently available in the US East (Northern Virginia), US West (Oregon), US West (Northern California), EU (Ireland), Asia Pacific (Singapore), Asia Pacific (tokyo), and South America (Sao Paulo) Regions.
    • Use CreateDomain, DeleteDomain, ListDomains, DomainMetadata to create and manage query domains
    • Use Put,Batch Put, & Delete to create and manage the data set within each query domain
  2. Retrieve your data
    • Use GetAttributes to retrieve a specific item
    • Use Select to query your data set for items that meet specified criteria
  3. Pay only for the resources that you consume












More Info. See  below links