IT Staff

Blog về chuyên ngành IT

Introduction Ruby and Ruby On Rails

leave a comment »

Châu Hng Lĩnh

 About this introduction

• This is an introduction at high level of Ruby and Ruby On Rails, with introduction to some features that make Ruby and Ruby On Rails become powerful and fun to work with.

• This is not a Tutorial about Ruby or Ruby On Rails. So the list of features and functionalities in this introduction is not completed as a Tutorial’s list should be. And there is no coding details.

What Ruby is …

• Pure OOP language

• Dynamic language

• Interpreter language

• Multi-platform language

What Ruby is not …

• Script language.

• Perfect language for everything.

Ruby features

  • Everything is object.
  • Single inheritance.
  • Very Expressive.
  • Symbol.
  • Dynamic typing: Class of object is not its type.
  • Behavior can be added to a class without modify the file contains the class.
  • Behavior can be different between different instances of the same class.
  • Code block feature.
  • Mixin.
  • Duck typing.
  • Truly object oriented, not class oriented.
  • Built-in security.
  • Reflection: Metadata of object.
  • Powerful built-in Regular Expression functionalities (not present here)
  • Coding at run-time (not present here)
  • Aspect Oriented Programming (not present here)

Every thing is object

  •  In Ruby, there is no primitive type.
  •  Number, Boolean … are also objects.
  • Examples:

From irb or rails console, type in the followings:

7.public_methods: Display all the method of the class Fixnum

7.class: Display the class name of 7 => Fixnum

In Ruby, a number will be converted automatically from Fixnum to Bignum if its value is too big for a Fixnum.

Single Inheritance

• In Ruby, a class can extend only one class.

• There is no interface and abstract class.

• There is no concept about static binding vs. dynamic binding.

Example:

class A

  def run

    puts “A run”

  end

end

class B < A

  def run

    puts “B run”

  end

end

Ruby’s Expressiveness

• Must write only what must be done.

Examples:

Code to print “Hello, World!”

Ruby:

puts “Hello, World!”

Java:

public class HelloWorld {

            public static void main (String[] args) {

           System.out.println(“Hello, World!”

      }

}

Ruby’s Expressiveness (next)

• There are many ways to tell the same things.

Ten different ways to write loops for, while, each, until …

Different ways to write conditions if-else, case-when, unless, (cond)? act 1 : act 2

• Use naming conventions over definitions

@@ is class variable

@     is instance variable

ALL CAPITAL LETTERS is global constant

• Many shortcuts and operations for Array, Hash, Set …

Symbols

  •  A symbol is something that Ruby uses to represent names and strings. It is a way to efficiently have descriptive names while saving the space one would use to generate a string for each naming instance.

Examples:

Instead of defining a constant SUCCESS = “success” and returning it whenever an operation is success, we can say “return :success

It is not only useful for saving memory, it is also an elegant way to specify about meanings of values for parameters.

For example in Rails, in routes.rb, if we define:

map.connect ‘form/submit/:user_id‘, :controller => ‘order_form’, :action => ‘form_submit’

Whenever the order_from_controller sees the URL like this:
http://myserver.com/form/submit/12345

It will translate “12345” as params[:user_id]

This is a very clean and simple way to define meaning for a value.

Dynamic typing

• Type of a Ruby object depends on what it refers to.

Example:

myVar = 7    => type of myVar is Fixnum

myVar = “Hello” => type of myVar is String.

• Object type is more about what it can do than about its (initial) class. There is type checking at Runtime to see what an object can do.

Example:

7.say_my_value

Error: undefined method `say_my_value’ for 7:Fixnum (NoMethodError)

Add behaviors to a class …

• In ruby, we can add new methods to a class without having to modify the file that contains the original definition of the class.

Example:

Anywhere in a program, we can write:

class String

   def greetings(name)

            self + “, ” + name

   end

end

So we will have a new method called greetings for every String.

str = “Greetings”

puts str.greetings(“World!”)   => “Greetings, World!”

str.respond_to? “greetings”   => true

Add behaviors to an instance …

• In Ruby, we can add methods to specific instances of a class that need certain behaviors in certain situations, but not adding to the whole class.

Example:

st = “Hello“

st2 = “Hi”

def st.say_hello(name)

            self + “, ” + name

end

puts st.say_hello(“World!”)    => “Hello, World!”

puts st2.say_hello(“World!”)  => NoMethodError: undefined method `say_hello’ for “Hi”:String

Code block feature

  • Ruby allows developer to pass a block of code in to a method to execute within the method.

Example:

class ArrayUtil

  def traverse_array(elements)

    for element in elements

      yield element

    end

  end

end

ar = [1, 2, 3, 4, 5]

au = ArrayUtil.new

au.traverse_array(ar) {|x| puts x}    => It will print all the values of elements in the array

au.traverse_array(ar) {|x| puts “Delete  #{x}”} => It will print all the values of elements in the array with “Delete “ before the values

Imagine that it is not traversing an array, but it is traversing some complex structures, such as file directory. We can substitute the code in the block with “print file”, “delete file”, “search for text in file” …, without having to repeat the code that walks though the directory structure.

Question: Consider about what it takes in Java or C++ to write code that walks through a structure, then perform different actions (print, delete …) on the elements of the structures, without having to repeat the code that walks through the structure?

Mixin

• Ruby uses modules to provide mixin capability: Allows many classes include modules, to share implementations of certain functionalities, without having to re-implement those functionalities into each class, or make a class hierarchy just to share common implementations.

module Pump

  def pump_air

    puts “Pump air into the damn \’#{self.name}\’ until it is full.”

  end

end

class Car

  include Pump

  def name() @name;   end

  def initialize(name) @name = name; end

end

class Ball

  include Pump

  def name() @name;   end

  def initialize(name) @name = name; end

end

car = Car.new(“BMW”)

car.pump_air

ball = Ball.new(“Soccer ball”)

ball.pump_air

Question: Consider what it takes in Java or C++ for class Car and class Ball share the same implementation of Pump?

Duck typing

  •  Duck typing philosophy: “If something walks like a duck and quacks like a duck, it is a duck”.

Example: Go back to the example about Mixin, we can see that as long as a Car object or a Ball object have a method called “name”, Pump doesn’t give a damn if it is a Car or a Ball.

Implications: Design Patterns such as Abstract Factory and Visitor are not necessary for Ruby.

In Ruby, we can implement better, shorter and more flexible code.

Built-in security

  • Level of execution

0          No checking of the use of externally supplied (tainted) data is performed. This is Ruby’s default mode.

>= 1     Ruby disallows the use of tainted data by potentially dangerous operations.

>= 2     Ruby prohibits the loading of program files from globally writable locations.

>= 3     All newly created objects are considered tainted.

>= 4     Ruby effectively partitions the running program in two. Nontainted objects may not be modified. Typically, this will be used to create a sandbox: the program sets up an environment using a lower $SAFE level, then resets $SAFE to 4 to prevent subsequent changes to that environment.

  • Tainted and Untainted Object

Method taint, untaint and tainted? of objects

Metadata

  •  Ruby uses reflection to allow developer to discover the following information about objects:

–         what objects it contains,

–         the current class hierarchy,

–         the contents and behaviors of objects, and

–         information on methods.

  •  Some useful commands to try from irb or Rails ’s console:

puts obj.public_methods.sort.join(“\n”) => it will print all the public methods of the object obj

Similar, intance_methods, methods, protected_methods, private_methods … will provide corresponding method lists according to scopes.

Go through all the methods in the public method list, try to see what methods we need to discover information about the object.

obj.respond_to? ‘method_name’ : Verify if we can call the method ‘method_name’ on the object obj.

protected: The difference between  ”protected” and  ”private” is fairly subtle, and is different in Ruby than in most common OO languages. If a method is protected, it may be called by any instance of the defining class or its subclasses. If a method is private, it may be called only within the context of the calling object—it is never possible to access another object’s private methods directly, even if the object is of the same class as the caller.

Why Ruby …

  • Expressive: Write less code to archive more things.
  • Easy to maintain: Pseudo-code that runs.
  • Productive: Spend less time to code.
  • Correctness: The less code you write, the less error you make.
  • Rich built-in features: String, Array, Hash, Set, Regular Expression, Network, IO, Thread, XML, Exception handling …
  • Easy to extend.
  • Experts available.
  • Multi-platform support.
  • Many tools available.
  • Fast, short lifecycle of development: don’t have to compile.
  • Fast and Easy to setup

What Ruby is not (yet) good for …

• Low-level system programming.
Need to write C modules and link to Ruby.

• Heavy, intensive computation tasks.

• Learn to programming (???)

What Rails is …

• A framework for Web-based application development in Ruby. Note: The differences between frameworks, components and applications.
• Rails provides full stack for multi-tier application development, from presentation to middle tier to database.

What Rails is not …

• A framework for stand-alone application (although some sub frameworks of Rails can be used outside of  a context of Web-based applications).
• A development environment for everything.

Rails components

• Active Record: A framework based on Active Record design pattern (Martin Fowler): Map database tables to Ruby objects.

• Action Controller: controller for Web applications.

• Action View: view for Web applications.

• Action Mailer: support mail functionalities.

• Action Web Service: support web services programming through xmlrpc calls and REST.

• Test Framework: provides test functionalities for Rails applications.

Rails features

• Prefer convention over configuration.

• Define a set of Domain Specific Language features.

• Take reflection to the fullest.

• Leverage code generators.

• Promote good use of MVC design pattern.

• Different environments for development, test and production.

• Promote test-first and agile development.

• Built-in support for database definition: migration.

• Interactive Console for trying ideas, debugging, testing.

• Built-in support for javascript and AJAX in Ruby language (Prototype and script.aculo.us).

• Wide range of database support: Oracle, PostreSQL, MySQL, SQLite …

• Built-in caching mechanism for pages, components, controllers, partials (not present here.)

Convention vs. Configuration

• Convention in URL. Can be overridden in routes.rb

• Convention in class names and database tables. Can be overridden in ActiveRecord object definition. •Convention in primary keys in database tables. Can be overridden in ActiveRecord object definition. •Convention in foreign keys in database tables. Can be overridden in ActiveRecord object definition.

• Convention about view names and positions: default root is set in template_root,

• default value is app/views. Can be overridden by overriding the method render() of ActionController, or assigning another value to template_root.

• Convention about layout: default layout location is in app/views/layouts. This is controller specific, and can be overridden in the controller.

Domain Specific Language

•Database relationships: belongs_to, has_one, has_many, has_and_belongs_to_many, act_as_list, act_as_tree

•Validation specifications: validates_presence_of, validates_numericality_of, validates_format_of, validates_acceptance_of, validates_confirmation_of, validates_length_of, validates_uniqueness_of

Reflection in Rails

•All ActiveRecord objects don’t have to define the attributes that are in tables in database. Rails will discover the column structure of tables, create attributes according to the columns and assign them to objects automatically.

•Rails allows developer to define attribute_reader, attribute_writer and attribute_accessor for ActiveRecord objects, and automatically generate the getters and setters for all the attributes accordingly.

•Rails uses Mixin and Reflection to add new behaviors into core Ruby objects.

Rails generators

  •  Rails has some built-in generators to generate a skeleton for Rails applications.

Example: From within a directory, in command shell, type

rails my_app

will create a directory named “my_app” with all the directory structure and some basic files for the whole Rails application, including directory for models, views, controllers, helpers, lib, test …

  •  Run the command

ruby script/generate to see all the options of the command “generate”, and see all the installed generators in the system.

  •  Rails allows developer to install or write new custom generators.

MVC in Rails

•Rails enforces the use of MVC Design Pattern using directory structure: dividing components of Rails application into directories “models”, “views”, controllers” and “helpers” under the sub directory “app”.

•Rails enforces the use of MVC Design Pattern using object design: all the models extend ActiveRecord, all the controllers extend ActionController and all the views extend ActionView.

•Rails promotes good use of MVC by using best practices: factoring business logics to models, advocating “Slim Controllers, Fat Models”; factoring out the calculation and logics for presentations in controllers to helpers; using separate views and using controllers to select views instead of putting to much code for dynamic view generation into view templates.

Different environments …

•Every Rails application has (at least) 3 different sets of environment configurations: development, test and production.

•Different configurations have different databases, environment settings. This feature makes it easy to develop, test and deploy Rails applications.

•It is possible to create additional environments configurations, or omit existing one.

•Rails uses YAML format to specify the configurations, which makes it significantly easier than XML configurations, and significantly more powerful than properties configurations.

Test and Agile Development

•Rails provides a set of testing functionalities to test different aspects of Web applications: Functional Tests are used to test controller, view and HTTP requests, responses; Unit Tests are used to test Ruby classes, for example models, helpers and other components. •Rails ’s use of an isolated database to test application makes it clean and reliable for each test or test suit. And it ensures that there is no interference with development and production database. •Rails provides a mechanism to conveniently use a set of specific objects in form of fixtures to do specific tests, which makes sure that we really test out the scenarios we want. •Rails provides a mechanism to use mock objects, just in case it is not convenient to create certain objects in database, or in early development phase when we don’t have much concrete design for database yet.

  •  Rails provides an easy way to create data structure for test database from development database:

rake clone_structure_to_test

  •  Rails provides an easy way to create test fixtures from the live database:

rake db:fixtures:export_using_query SQL=”select * from foo where id=’bar'” FIXTURE_NAME=foo

  •  Rails uses Rake to run all the functional tests and unit tests, so it makes it possible to do the whole application testing in continuous integration.
  •  All of those test features and scaffolding generator allow Rails developer to do development using Agile methods (create simplest things that possibly work, test first, refactor code without fear, continuous integration)

Rails database migration

•Rails migration provides the capability of creating tables, altering tables, columns … in databases using Ruby code.

•Rails migration, via ActiveRecord::Migration #up and #down, allows developer to keep track of changes in databases, and can move databases to a certain version of database schema easily.

•Frankly, I don’t use it😉

Rails console

  •  Rails has a very nice interactive console, which can be called by using the command “ruby script/console”
  •  This console allows developer to

enter Rails commands,

query ActiveRecord in database,

discover meta-information about the Rails application,

try out Ruby code, ideas …

test HTTP functionalities of controllers

This is a very useful tool for Rails development, because it allows developer to try things quickly, which are normally not possible in other languages.

Rails and AJAX

  • Rails uses 2 popular javascript frameworks “Prototype” and “script.aculo.us” to support javascript and AJAX functionalities.
  • Using Rails AJAX functionalities, developer don’t have to write javascript code, but write Ruby code and RJS instead.

Examples:

<%= link_to_remote link,

    :update => ‘tabContent’,

    :url => {

        :controller => ‘post_instructions’,

        :action => ‘toggle_field_instance_post_ajax’,

        :id => @field_instance

    },

    :loading => “$(‘tabContent’).innerHTML = ‘#{centered_spinner_html}'”

%>

will create an AJAX link to the server, with definition for what URL to call, what must be displayed when waiting, where to update content when the call is completed …

Rails development tools

•All text editors that produce plain text files can be used to write Ruby and Rails code.

•Multi-platform IDEs: RadRails, Aptana IDE, Komodo IDE.

•Mac OS X: TextMate.

•Linux KDE: KDeveloper Ruby

•Window only: Edit Plus, Ultra Edit.

Rails deployment

•Rails run on any web server that support CGI and FastCGI.

•Popular production deployments: Apache + FastCGI, lighttpd, mongrel.

•Popular and easy for development: mongrel, WEBrick.

•Caching for performance: memcached.

Why Rails …

•Rapid Web-based application development.

•Good organization and environments for the whole development process.

•Easy to learn.

•Promote good development practices.

•Support by best of the best people in the industry.

•Support by strong player in the industry: Google, Sun, Microsoft, Amazon …

•Cost effective.

•Fast and easy to setup.

What Rails is not (yet) good for …

•Applications that use distributed transactions and multi-phased transactions.

•Applications that have a lot of low-level system management activities, for example hardware and communication device management.

•Some special types of databases, for example Object Relational Database or XML Database.

Ruby and Rails Myths

•Ruby is slow: Yes, Ruby is arguably slower than compiled languages such as C, C++ or hybrid language such as Java.
However, it is not unacceptably slow. And computers become more powerful every year, heavy-duty tasks now are accomplished using Ruby.
Even for some specific cases, Rails performance becomes better than Java counter part. It all comes down to good architecture design and implementation.

  • Ruby and Ruby On Rails are good only for small and medium companies: There are many Ruby and Ruby On Rails applications that are used for heavy traffic web sites with millions of users and terabytes of data in databases.

Who are using Ruby and Rails

•Country: The whole Japan

•Big guys: Google, Amazon, Sun, Microsoft.

•Small and Medium Companies: 37Signals, Washington Post, ThoughtWorks, Second Gear, Odeo, a lot of start-up companies. Even Porn industry in California. •Experts, Individuals: Yukihiro Matsumoto, David Heinemeier Hansson, James Duncan Davidson, Martin Fowler, Bruce Tate, Justin Gehtland, David Black, Zed Shaw, Jamis Buck, David Thomas, Chad Fowler, Andy Hunt …

Some brief comment about other languages

•C: low productive, not OOP

•C++: low productive, not pure OOP.

•Java and J2EE:  low productive.Too complicated now. Too much boiler-plate code. Arguably not pure OOP.

•Perl: Not OOP. No facility for component and layer programming.

•PHP: Same as Perl.

            (Now there are OOP Perl and OOP PHP, but they are just after thought, not design of the language)

•Smalltalk: Beautiful language, but not popular and lack of support of developers.

•C# and Visual Basic: Don’t insult me by asking me about them!😉

Some cool things to look around …

•SOA in Ruby and Rails.

•Web Services and RESTful development.

•Integration using Ruby and Rails.

•JRuby.

•Aspect Oriented Programming in Ruby.

•Using LDAP with Ruby and Rails.

•Some “weird” things: Prototype Programming, Singleton Class.

Some useful links

•Ruby homepage: http://www.ruby-lang.org/en/

•Rails home page: http://www.rubyonrails.org/

•Pragmatic book: http://www.rubycentral.com/book/

•Vietnam Ruby group: http://vnruby.org/

•From links above, there are more useful references to other web sites, manuals, tutorials, blogs …

Thank you and good bye …

•I still don’t understand why the hell I must say “Thank you” here.

•However, I am a nice and modest guy, so “Thank you for your damn time!”

No hard feelings, eh?

Written by Xavier

Tháng Tám 3, 2013 lúc 9:50 sáng

Posted in Staff

Gửi phản hồi

Mời bạn điền thông tin vào ô dưới đây hoặc kích vào một biểu tượng để đăng nhập:

WordPress.com Logo

Bạn đang bình luận bằng tài khoản WordPress.com Log Out / Thay đổi )

Twitter picture

Bạn đang bình luận bằng tài khoản Twitter Log Out / Thay đổi )

Facebook photo

Bạn đang bình luận bằng tài khoản Facebook Log Out / Thay đổi )

Google+ photo

Bạn đang bình luận bằng tài khoản Google+ Log Out / Thay đổi )

Connecting to %s

%d bloggers like this: