Saturday, March 26, 2011

ROR - Ruby on Rails

"Ruby-On-Rails" when I heard the title, thought it would be some alien language/framework which is more complex. Got chance to work on proposal to create Catalogue using the PHP, for that proposal started exploring the framework called CakePHP (which is another interesting framework in PHP); which has borrowed ideas from the Ruby-On-Rails (RoR) framework. RoR is an rapid WEB development framework used in http://www.37signals.com/ site, they where developing the their projects using this in-house framework developed by "David Heinemeier Hansson" http://www.loudthinking.com/about.html 37signals employee and in 2003 Rails framework made available to the OpenSource world.


Rails

Rails is a web development framework written in the Ruby language. It is designed to make programming web applications easier by making several assumptions about what every developer needs to get started. It allows you to write less code while accomplishing more than many other languages and frameworks. Long-time Rails developers also report that it makes web application development more fun.

Rails is opinionated software. That is, it assumes that there is a best way to do things, and it’s designed to encourage that best way – and in some cases to discourage alternatives. If you learn “The Rails Way” you’ll probably discover a tremendous increase in productivity. If you persist in bringing old habits from other languages to your Rails development, and trying to use patterns you learned elsewhere, you may have a less happy experience.

The Rails philosophy includes several guiding principles:

* DRY – “Don’t Repeat Yourself” – suggests that writing the same code over and over again is a bad thing.
* Convention Over Configuration – means that Rails makes assumptions about what you want to do and how you’re going to do it, rather than letting you tweak every little thing through endless configuration files.
* REST is the best pattern for web applications – organizing your application around resources and standard HTTP verbs is the fastest way to go.

Rails is organized around the Model, View, Controller architecture, usually just called MVC.

MVC benefits include:

* Isolation of business logic from the user interface
* Ease of keeping code DRY
* Making it clear where different types of code belong for easier maintenance

Models

A model represents the information (data) of the application and the rules to manipulate that data. In the case of Rails, models are primarily used for managing the rules of interaction with a corresponding database table. In most cases, one table in your database will correspond to one model in your application. The bulk of your application’s business logic will be concentrated in the models.

Views

Views represent the user interface of your application. In Rails, views are often HTML files with embedded Ruby code that performs tasks related solely to the presentation of the data. Views handle the job of providing data to the web browser or other tool that is used to make requests from your application.

Controllers

Controllers provide the “glue” between models and views. In Rails, controllers are responsible for processing the incoming requests from the web browser, interrogating the models for data, and passing that data on to the views for presentation.

Playing With Rails

We will try to create a small web application in the Rails framework, Rails are its dependent gems (jar file equivalent in ruby world).

Example Web Application Creation

Follow below steps to create a small blog application with CRUD (Create, Read, Update and Delete) operations.

Language : Ruby
Server : Mongrel
Database : MySQL

Steps

* WebApp Creation
o Login to Server
o Create blog WebApplication

Execute:
[S171015@ctsinnvlvmft1 ~]$ rails blog

Output:

create
create app/controllers
create app/helpers
create app/models
create app/views/layouts
create config/environments
create config/initializers
create config/locales
create db
create doc
create lib
create lib/tasks
create log
create public/images
create public/javascripts
create public/stylesheets
create script/performance
create test/fixtures
create test/functional
create test/integration
create test/performance
create test/unit
create vendor
create vendor/plugins
create tmp/sessions
create tmp/sockets
create tmp/cache
create tmp/pids
create Rakefile
create README
create app/controllers/application_controller.rb
create app/helpers/application_helper.rb
create config/database.yml
create config/routes.rb
create config/locales/en.yml
create config/initializers/backtrace_silencers.rb
create config/initializers/inflections.rb
create config/initializers/mime_types.rb
create config/initializers/new_rails_defaults.rb
create config/initializers/session_store.rb
create config/environment.rb
create config/boot.rb
create config/environments/production.rb
create config/environments/development.rb
create config/environments/test.rb
create script/about
create script/console
create script/dbconsole
create script/destroy
create script/generate
create script/runner
create script/server
create script/plugin
create script/performance/benchmarker
create script/performance/profiler
create test/test_helper.rb
create test/performance/browsing_test.rb
create public/404.html
create public/422.html
create public/500.html
create public/index.html
create public/favicon.ico
create public/robots.txt
create public/images/rails.png
create public/javascripts/prototype.js
create public/javascripts/effects.js
create public/javascripts/dragdrop.js
create public/javascripts/controls.js
create public/javascripts/application.js
create doc/README_FOR_APP
create log/server.log
create log/production.log
create log/development.log
create log/test.log


* Database Configuration
o Modify the config/database.yml configuration

development:
adapter: mysql
encoding: utf8
reconnect: false
database: blog_development
pool: 5
username: S171015
password: password-1
socket: /var/lib/mysql/mysql.sock

test:
adapter: mysql
encoding: utf8
reconnect: false
database: blog_test
pool: 5
username: S171015
password: password-1
socket: /var/lib/mysql/mysql.sock

production:
adapter: mysql
encoding: utf8
reconnect: false
database: blog_production
pool: 5
username: S171015
password: password-1
socket: /var/lib/mysql/mysql.sock


* Create Database

[S171015@ctsinnvlvmft1 blog]$ rake db:create


Above command rake is general-purpose command-runner, which creates the database called 'blog_development.

* Create Resources

Execute:
[S171015@ctsinnvlvmft1 blog]$ script/generate scaffold Post name:string title:string content:text

Output:

exists app/models/
exists app/controllers/
exists app/helpers/
create app/views/posts
exists app/views/layouts/
exists test/functional/
exists test/unit/
create test/unit/helpers/
exists public/stylesheets/
create app/views/posts/index.html.erb
create app/views/posts/show.html.erb
create app/views/posts/new.html.erb
create app/views/posts/edit.html.erb
create app/views/layouts/posts.html.erb
create public/stylesheets/scaffold.css
create app/controllers/posts_controller.rb
create test/functional/posts_controller_test.rb
create app/helpers/posts_helper.rb
create test/unit/helpers/posts_helper_test.rb
route map.resources :posts
dependency model
exists app/models/
exists test/unit/
exists test/fixtures/
create app/models/post.rb
create test/unit/post_test.rb
create test/fixtures/posts.yml
create db/migrate
create db/migrate/20090703064638_create_posts.rb

Command 'script/generate' used to generate files required by the rails, scaffold command will get you up and running quickly, it generates “one size fits all” code for quick development. In this example database table named 'Posts' will be created and associated MVC files for the same.

Controller File

file: app/controller/posts_controller.rb

class PostsController < ApplicationController
# GET /posts
# GET /posts.xml
def index # INDEX Action
...
end
# GET /posts/1
# GET /posts/1.xml
def show # Action to SHOW the post
...
end
# GET /posts/new
# GET /posts/new.xml
def new # Action to ADD new post
...
end
# GET /posts/1/edit
def edit # Action to EDIT post
...
end
# POST /posts
# POST /posts.xml
def create # Action to CREATE post
...
end
# PUT /posts/1
# PUT /posts/1.xml
def update # Action to UPDATE post
...
end
# DELETE /posts/1
# DELETE /posts/1.xml
def destroy # Action to DELETE post
@post = Post.find(params[:id])
...
end


Model File

file: app/models/post.rb

class Post < ActiveRecord::Base
...
end


View Files Contains minimal html code to render the content in the browser.

file: app/views/posts/edit.html.erb
file: app/views/posts/index.html.erb
file: app/views/posts/new.html.erb
file: app/views/posts/show.html.erb

Starting the Server


[S171015@ctsinnvlvmft1 blog]$ script/server
=> Booting Mongrel
=> Rails 2.3.2 application starting on http://localhost:3000
=> Call with -d to detach
=> Ctrl-C to shutdown server




Access the Blog Application

http://localhost:3000/posts



Add new Post


Listing all Posts

Friday, March 25, 2011

DOJO - My old friend

Dojo, I learnt this RIA framework in my earlier career to prepare GUI for one of my project tool. Now framework has evolved lot with stunning features, I decided to use this framework for my new editorial software "Guide For Web - source collection", for which I need User Interface to categorize the websites with screen-shots and reviews.

Dojo (Interface) --> Apache + PHP + CakePHP (Core) --> Postgresql (Backend)

Completed initial step in creating the Dojo view, hope this weekend will integrate with CakePHP to get this up and running.

Dojo View

Friday, February 25, 2011

Step1:1 - ".emu" file format without policy

I want to structure the ".emu" file more simple and easy to process, decided to use the JSON format (as Amazon) and came up with following formats for Buckets and Object. Right now this format is more theoretical, it will be updated iteratively.

Once this format is applied for the Buckets and Objects, planning to include Policy also.


Bucket Format


|- myBucket
|- .emu -> Json file represents bucket properties

{ "bucketname": {
"accessControlList": [
{ "ID": "a9a7b886d6fd24a52fe8ca5bef65f89a64e0193f23000e241bf9b1c61be666e9", "DisplayName":"chriscustomer", "Permission": "FULL_CONTROL"},
{ "ID": "a9a7b886d6fd24a52fe8ca5bef65f89a64e0193f23000e241bf9b1c61be666e9", "DisplayName":"chriscustomer", "Permission": "FULL_CONTROL"},
{ "ID": "a9a7b886d6fd24a52fe8ca5bef65f89a64e0193f23000e241bf9b1c61be666e9", "DisplayName":"chriscustomer", "Permission": "FULL_CONTROL"},
],
"AWSAccessKeyId": "AWS87289288929829kkjkhS88",
"timestamp": "2010-10-02 11:00:00",
"signature": "AAAAAAAAAAAAAAAAAAAAAAAAAAA",
"objectCount": "0"
}
}

Object Format


|- Object1
|- Object2
|- Key1/Object3
|- Key2/Object4
|- ".emu"

{ "bucketname": {
"objects": [
{"object1": {
"key": "Key1",
"metadata": [
{"metadata_obj": { "name": "Content-Type", "value": "text/plain" }},
{"metadata_obj": { "name": "Content-Type", "value": "text/plain" }},
{"metadata_obj": { "name": "Content-Type", "value": "text/plain" }}
],
"data": "1234567",
"contentlength": "5",
"accessControlList": [
{ "ID": "a9a7b886d6fd24a52fe8ca5bef65f89a64e0193f23000e241bf9b1c61be666e9", "DisplayName":"chriscustomer", "Permission": "FULL_CONTROL"},
{ "ID": "a9a7b886d6fd24a52fe8ca5bef65f89a64e0193f23000e241bf9b1c61be666e9", "DisplayName":"chriscustomer", "Permission": "FULL_CONTROL"},
{ "ID": "a9a7b886d6fd24a52fe8ca5bef65f89a64e0193f23000e241bf9b1c61be666e9", "DisplayName":"chriscustomer", "Permission": "FULL_CONTROL"},
],
"AWSAccessKeyId": "AWS87289288929829kkjkhS88",
"timestamp": "2010-10-02 11:00:00",
"signature": "AAAAAAAAAAAAAAAAAAAAAAAAAAA }},
{"object2": {
"key": "Key2",
"metadata": [
{"metadata_obj": { "name": "Content-Type", "value": "text/plain" }},
{"metadata_obj": { "name": "Content-Type", "value": "text/plain" }},
{"metadata_obj": { "name": "Content-Type", "value": "text/plain" }}
],
"data": "1234567",
"contentlength": "5",
"accessControlList": [
{ "ID": "a9a7b886d6fd24a52fe8ca5bef65f89a64e0193f23000e241bf9b1c61be666e9", "DisplayName":"chriscustomer", "Permission": "FULL_CONTROL"},
{ "ID": "a9a7b886d6fd24a52fe8ca5bef65f89a64e0193f23000e241bf9b1c61be666e9", "DisplayName":"chriscustomer", "Permission": "FULL_CONTROL"},
{ "ID": "a9a7b886d6fd24a52fe8ca5bef65f89a64e0193f23000e241bf9b1c61be666e9", "DisplayName":"chriscustomer", "Permission": "FULL_CONTROL"},
],
"AWSAccessKeyId": "AWS87289288929829kkjkhS88",
"timestamp": "2010-10-02 11:00:00",
"signature": "AAAAAAAAAAAAAAAAAAAAAAAAAAA" }},
{"object3": {
"key": "Key3",
"metadata": [
{"metadata_obj": { "name": "Content-Type", "value": "text/plain" }},
{"metadata_obj": { "name": "Content-Type", "value": "text/plain" }},
{"metadata_obj": { "name": "Content-Type", "value": "text/plain" }}
],
"data": "1234567",
"contentlength": "5",
"accessControlList": [
{ "ID": "a9a7b886d6fd24a52fe8ca5bef65f89a64e0193f23000e241bf9b1c61be666e9", "DisplayName":"chriscustomer", "Permission": "FULL_CONTROL"},
{ "ID": "a9a7b886d6fd24a52fe8ca5bef65f89a64e0193f23000e241bf9b1c61be666e9", "DisplayName":"chriscustomer", "Permission": "FULL_CONTROL"},
{ "ID": "a9a7b886d6fd24a52fe8ca5bef65f89a64e0193f23000e241bf9b1c61be666e9", "DisplayName":"chriscustomer", "Permission": "FULL_CONTROL"},
],
"AWSAccessKeyId": "AWS87289288929829kkjkhS88",
"timestamp": "2010-10-02 11:00:00",
"signature": "AAAAAAAAAAAAAAAAAAAAAAAAAAA" }},
{"object4": {
"key": "Key4",
"metadata": [
{"metadata_obj": { "name": "Content-Type", "value": "text/plain" }},
{"metadata_obj": { "name": "Content-Type", "value": "text/plain" }},
{"metadata_obj": { "name": "Content-Type", "value": "text/plain" }}
],
"data": "1234567",
"contentlength": "5",
"accessControlList": [
{ "ID": "a9a7b886d6fd24a52fe8ca5bef65f89a64e0193f23000e241bf9b1c61be666e9", "DisplayName":"chriscustomer", "Permission": "FULL_CONTROL"},
{ "ID": "a9a7b886d6fd24a52fe8ca5bef65f89a64e0193f23000e241bf9b1c61be666e9", "DisplayName":"chriscustomer", "Permission": "FULL_CONTROL"},
{ "ID": "a9a7b886d6fd24a52fe8ca5bef65f89a64e0193f23000e241bf9b1c61be666e9", "DisplayName":"chriscustomer", "Permission": "FULL_CONTROL"},
],
"AWSAccessKeyId": "AWS87289288929829kkjkhS88",
"timestamp": "2010-10-02 11:00:00",
"signature": "AAAAAAAAAAAAAAAAAAAAAAAAAAA" }}
]
}
}

Saturday, February 19, 2011

Step1:0: Study - Amazon S3 Emulator

There are lot of ways to implement this emulator and lot of existing implementation also available to do this, but purpose of this emulator implementation is to understand the Amazon S3 operations (which I am going to use in upcoming steps). My only requirement is "it should be identical to the Amazon S3 behaviour", way we access the service and all other functionalities. Intern I want to test with Amazon Java/PHP APIs (sorry I am not interested in .Net)

Downloaded the AmazonS3.wsdl & AmazonS3.xsd and generated the Axis implementation for the same. Initially thought of using database with hibernate to store the buckets and objects, but with this option we cannot access the uploaded objects as Amazon S3 provides. Decided to store the objects in the disk as node file, which web server can access. I have planned to use Apache Commons IO and Apache MINA libraries for the same.

Bucket

- Will be like webapps

- Access control, AWSAccessKeyId, timestamp, etc list will be maintained in ".emu" file. (like .svn not folder, but file)

Example:

<webapps>/myBuket/

Can be accessed from outside like, http://localhost:port/myBuket/

Object

- Key will be name of the object (file)

- Access control, AWSAccessKeyId, timestamp, etc list will be maintained in ".emu" file. (like .svn not folder, but file)

Example:

webapps/myBuket/profile.jpg

Can be accessed from outside like, http://localhost:port/myBuket/profile.jpg

Similarly all other operations supported by the Amazon S3 will be provided.

Next

Step1:1 Complete: Amazon S3 Emulator – Policy Implementation, Step1:2 Complete: Amazon S3 Emulator, Step1:3 Study - Amazon S3 with Hadoop,…..

Step 2:0 Study - Apache Jackrabbit - Amazon S3..