Showing posts with label Ruby. Show all posts
Showing posts with label Ruby. Show all posts

Friday, August 16, 2013

Common Algorithms - Ruby implementation


puts '-- PALINDROME -- '
# is word a palindrome?
def palindrome(s)
  if s== nil or s.length == 0 or s.length == 1
    ans = 'yes'
  else
    if s[0] == s[s.length-1]
      ans = palindrome s[1..s.length-2]
    else
      ans = 'no'
    end
  end
end

# test
puts '<nil>' + '  ' + palindrome(nil)
puts '' + '  ' + palindrome('')
puts 'm' + '  ' + palindrome('m')
puts 'mm' + '  ' + palindrome('mm')
puts 'mom' + '  ' + palindrome('mom')
puts 'racecar' + '  ' + palindrome('racecar')
puts 'notapalindrome' + '  ' + palindrome('notapalindrome')


puts '-- FIBONACCI -- '
# fibonacci series
def fib(n)
  if n == 0 or n == 1 then
    1
  else
    fib(n-1) + fib(n-2)
  end
end

#test
(0..20).each do  |n| 
  puts 'n=' + n.to_s + ' fib=' + fib(n).to_s
end


puts '-- FACTORIAL - RECURSIVE -- '
# factorial
def fac(n)
 if (n == 1 || n == 0) then
  1
 else
  n * fac(n.abs-1)
 end
end

#test
puts '-5' + '! = ' + fac(-5).to_s
puts '-4' + '! = ' + fac(-4).to_s
puts '0' + '! = ' + fac(0).to_s
puts '1' + '! = ' + fac(1).to_s
puts '3' + '! = ' + fac(3).to_s
puts '4' + '! = ' + fac(4).to_s
puts '5' + '! = ' + fac(5).to_s


puts '-- SQRT - BISCECTOR METHOD -- '
def sqrt_bisectormethod(n, epsilon)
 ans = "Unable compute within " + epsilon.to_s
 low = 0.0
 high = [n, 1.0].max

 guess = (low + high) / 2.0
 100.times do
  candidate = (guess ** 2)
  if  (candidate - n).abs < epsilon then
   ans = guess
   return ans
  end
  if  candidate < n
   low = guess
  else
   high = guess
  end
  guess = (low + high) / 2.0 
 end
 ans
end

# test
[0.25, 0.5, 1,2,3,4,5,6,7,8].each  do |n|
 puts 'sqrt of ' + n.to_s + ' = ' + sqrt_bisectormethod(n, 0.0001).to_s + " (Math.sqrt =" + Math.sqrt(n).to_s + ')'
end

puts '-- SQRT - NEWTON RAPHSON METHOD -- '
def sqrt_newton_raphson(n, epsilon)
 # equation: x^2 = 16  => y = x^2 - 16
 #           Find roots at y intercept: f(x) = y  
 #           Find slope using derivatives at various points

  ans = "Unable compute within " + epsilon.to_s
 guess = n / 2.0
 100.times do
  diff = guess ** 2 - n
  if  diff.abs <= epsilon then
   ans = guess
   return ans
  end
  guess = guess - diff / (2.0 * guess)
 end
 ans
end

# test
[0.25, 0.5, 1,2,3,4,5,6,7,8].each  do |n|
 puts 'sqrt of ' + n.to_s + ' = ' + sqrt_newton_raphson(n, 0.0001).to_s + " (Math.sqrt =" + Math.sqrt(n).to_s + ')'

end

puts '-- EXPONENT - LINEAR -- '
def exp_linear(x, y)
ans = 1
1.upto(y) do |i|
ans *= x;
end
return ans
end
#test
puts '2^0=' + exp_linear(2, 0).to_s
puts '2^1=' + exp_linear(2, 1).to_s
puts '2^8=' + exp_linear(2, 8).to_s

puts '-- EXPONENT - RECURSIVE -- '
def exp_rec(x, y)
if y < 1
return 1
end
if y <= 1
   return x
else
return x * exp_rec(x, y - 1)
end
end
#test
puts '2^0=' + exp_rec(2, 0).to_s
puts '2^1=' + exp_rec(2, 1).to_s
puts '2^8=' + exp_rec(2, 8).to_s

puts '-- EXPONENT - Log N -- '
def exp_logn(x, y)
if y < 1
return 1
end
if y == 1
return x
end
if ((y / 2) * 2) == y # even y
exp_logn(x*x, y/2)
else # odd y
x * exp_logn(x*x, y-1)
end
end
#test
puts '2^0=' + exp_logn(2, 0).to_s
puts '2^1=' + exp_logn(2, 1).to_s
puts '2^8=' + exp_logn(2, 8).to_s


puts '-- TOWERS OF HANOI -- '
def towers(size, fromTower, toTower, spareTower)
if (size == 1)
puts "Move disk from " + fromTower.to_s + " to " + toTower.to_s
else
towers size - 1, fromTower, spareTower, toTower
towers 1, fromTower, toTower, spareTower
towers size - 1, spareTower, toTower, fromTower
end
end
#test
puts "1 Disk"
towers 1, 1, 2, 3
puts "2 Disks"
towers 2, 1, 2, 3
puts "3 Disks"
towers 3, 1, 2, 3
puts "4 Disks"
towers 4, 1, 2, 3

puts '-- BINARY SEARCH -- '
# An example of "Divide and Conquer" algorithm
# Split problem into several sub-problems of the same type
# Solve each problem independently
# Combine intermediate results to arrive at the solution
#  The INPUT must be PRE-SORTED
def bsearch(s, e, first, last)
if (last - first) < 2
return (s[first] == e or s[last] == e)
end
mid = first + (last - first) / 2
if s[mid] == e 
return true
end
if s[mid] > e
return bsearch(s, e, first, mid - 1)
end
return bsearch(s, e, mid + 1, last)
end

def bsearchMain(s, e)
  bsearch(s, e, 0, s.length - 1)
end
#test
puts '100 in []: ' + bsearchMain([], 100).to_s
puts '100 in [100]: ' + bsearchMain([100], 100).to_s
puts '1 in [1,2,3,4,100]: ' + bsearchMain([1,2,3,4,100], 1).to_s
puts '100 in [1,2,3,4,100]: ' + bsearchMain([1,2,3,4,100], 100).to_s
puts '3 in [1,2,3,4,100]: ' + bsearchMain([1,2,3,4,100], 3).to_s
puts '2 in [1,2,3,4,100]: ' + bsearchMain([1,2,3,4,100], 2).to_s
puts '4 in [1,2,3,4,100]: ' + bsearchMain([1,2,3,4,100], 2).to_s
puts '20 in [1,2,3,4,100]: ' + bsearchMain([1,2,3,4,100], 20).to_s

puts '-- BUBBLE SORT -- '
# O(n^2)
# Bubble the largest values to the end
def bubble_sort(l)
l.length.times do
0.upto(l.length - 2) do |i|
if l[i] > l[i+1]
temp = l[i]
l[i] = l[i+1]
l[i+1] = temp
end
end
end
l
end
#test
puts (bubble_sort []).inspect
puts (bubble_sort [1]).inspect
puts (bubble_sort [2,1]).inspect
puts (bubble_sort [2,1,6,4,3,5]).inspect

puts '-- BUBBLE SORT OPTIMIZED -- '
# still O(n^2)
def bubble_sort_opt(l)
swapped = true
while swapped
swapped = false # optimization - if no swapping happened, the rest of the list is already in order
0.upto(l.length - 2) do |i|
if l[i] > l[i+1]
temp = l[i]
l[i] = l[i+1]
l[i+1] = temp
swapped = true
end
end
end
l
end
#test
puts (bubble_sort_opt []).inspect
puts (bubble_sort_opt [1]).inspect
puts (bubble_sort_opt [2,1]).inspect
puts (bubble_sort_opt [2,1,6,4,3,5]).inspect

puts '-- SELECTION SORT -- '
# o(n^2) 
# Keep track of minimum index and minimum value
# more efficient than bubble sort which has more swaps
def sel_sort(l)
0.upto(l.length - 1) do |i|
minIndex = i
minVal = l[i]
j = i + 1
while j < l.length
if minVal > l[j]
minIndex = j
minVal = l[j]
end
j += 1
end
temp = l[i]
l[i] = l[minIndex]
l[minIndex] = temp
end
l
end
#test
puts (sel_sort []).inspect
puts (sel_sort [1]).inspect
puts (sel_sort [2,1]).inspect
puts (sel_sort [2,1,6,4,3,5]).inspect

puts '-- MERGE TWO SORTED ARRAYS OF EQUAL SIZE -- '
def merge_sorted_arrays (l, r)
# l and r sorted lists
result = []
i=0
j=0
while i < l.length and j < r.length
if l[i] <= r[j]
result << l[i]
i = i + 1
else
result << r[j]
j = j + 1
end
end
# left over elements - i, j values incremented previously
while i < l.length
result << l[i]
i += 1
end
while j < r.length
result << r[j]
j += 1
end
result
end
#test
puts (merge_sorted_arrays [1, 3, 5], [2, 4, 6]).inspect

puts '-- MERGE SORT -- '
# Divide list into half
# Continue the list is a singleton
# Combine singleton lists in sorted order
#     O
#    /   \
#   O      O
#  / \    / \
# O   O  O   O
# O(n) items to merge items each level
# There are O(log n) levels
# Total Complexity: O( n log n)
# Compared to Merge Sort,Hashing provides O(1)
def merge_sort(l)
if l.length < 2
return l
else
middle = l.length / 2
left = merge_sort l[0..middle-1]
right = merge_sort l[middle..l.length-1]
together = merge_sorted_arrays left, right
end
end
#test
puts (merge_sort [1]).inspect
puts (merge_sort []).inspect
puts (merge_sort [2,1]).inspect
puts (merge_sort [2,1,3]).inspect
puts (merge_sort [2,1,3,6,4,5]).inspect

# puts [1,2,3,4,5][0..2].inspect

puts '-- DECIMAL TO BINARY -- '
def dec_to_bin (dec)
continue = true
l = []
div = dec
while continue
remainder = div % 2
div = div / 2
l << remainder
if div < 1 
continue = false
end
end
l.reverse.join
end
#test
puts 'dec 0 = ' + (dec_to_bin 0)
puts 'dec 1 = ' + (dec_to_bin 1)
puts 'dec 2 = ' + (dec_to_bin 2)
puts 'dec 4 = ' + (dec_to_bin 4)
puts 'dec 8 = ' + (dec_to_bin 8)
puts 'dec 29 = ' + (dec_to_bin 29)
puts 'dec 100 = ' + (dec_to_bin 100)

puts '-- BINARY TO DECIMAL -- '
def bin_to_dec(bin)
dec = 0
pos = bin.length - 1
bin.split("").each do |i|
dec += 2**pos * i.to_i
pos -= 1
end
dec
end
#test
puts 'bin 0 = ' + bin_to_dec("0").to_s
puts 'bin 1 = ' + bin_to_dec("1").to_s
puts 'bin 10 = ' + bin_to_dec("10").to_s
puts 'bin 100 = ' + bin_to_dec("100").to_s
puts 'bin 1000 = ' + bin_to_dec("1000").to_s
puts 'bin 11101 = ' + bin_to_dec("11101").to_s
puts 'bin 1100100 = ' + bin_to_dec("1100100").to_s

puts'bin_to_dec(dec_to_bin(12345345)) = ' + bin_to_dec(dec_to_bin(12345345)).to_s

Thursday, July 11, 2013

Ruby

What is it?

  • Ruby is high-level programming language
  • It is an interpreted language
  • It is a general purpose programming language
  • Provides functional programming features (function closures - blocks and procs)
  • Supports object-oriented programming (classes and inheritance)
  • Strongly typed
  • Inspired by Perl, Smalltalk, Lisp, Python

Installation

http://rubyinstaller.org/

Documentation

Docs - http://www.ruby-doc.org/docs/ProgrammingRuby/

Language Nuances

  • Parenthesis are not required when calling methods
  • Semicolons not required at the end of each line unless placing multiple statements on a single line
  • No abstract classes
  • No interfaces. 
  • Classes allow single class inheritance. However, using mixins, code from another module can be mixed-in and becomes part of the class using the include statement. All the module's instance methods are suddenly available as methods in the class as well.
  • Modules define pieces of reusable code (cannot be instantiated)
  • Modules have a namespace (to avoid name clashes)
  • Variable declaration is not required
  • All classes are derived from base class called Class
  • No structs
  • Supports symbols. :someValue is not a string but rather a symbol. If you are using a string over and over, use a symbol. Uses less memory.
  • There is no main method. Ruby code is placed in a text file with extension .rb and is run as a script
  • Code can be placed in separate files and included in the main script using require (require 'filename') or load (load 'filename.rb' ) directive. require loads the file once, load loads the file as many times as specified.
  • require_relative complements the built-in method require by allowing you to load a file that is relative to the file containing the require_relative statement.

Reflection

  • var.class - tells the class of variable (object)
  • v.methods - tells the methods of an object
  • puts "Type of self = #{self.type}"
  • puts "Name of self = #{self.name}"
def who_am_i?  
    "#{self.class.name} (\##{self.object_id}): #{self.to_s}"  
end

Naming

  • localVariable
  • @instanceVariable
  • @@classVariable
  • $globalVariable
  • Constant
  • ClassName
  • method_name
  • By convention, methods that return a boolean (or answer a question) have a '?' at the end of the method name
  • By convention, methods that change the contents of passed in arguments have an '!' at the end of the method name

Comments

Single line start with #

Multiline comments
=begin
my comments
my comments
=end

Running Ruby

  • To run interactive Ruby (console), enter irb at OS command prompt
  • To run Ruby script, enter ruby filename.rb at at OS command prompt

puts

 # add 2 and 3, get 5, apply to_s and print to screen
puts 2 + 3  # outputs 5
put 1 > 2   # outputs false

gets

Retrieves a string from keyboard until enter key is pressed

puts 'your name please'
name = gets.chomp  # chomp removes the carriage return
puts 'hello ' + name

self

self is a special variable which points to whatever object you are in.
# we generally omit self when writing puts
self.puts 'some string'      

Variables

  • All things in Ruby are objects, even puts and gets are part of an implicit class object
  • A variable can point to any object
  • First letter of var name must be lowercase
  • someVar = "abc"
  • someVar = 5 * (2 + 1)  # holds 15
  • var cannot point to other vars; when on variable is assigned to another, the variable being assigned to points to the value of the other variable (i.e. vars point to the value of the first var)

Literals

  • even literals are objects. "AnyString­".reverse
  • "str" * 3 yields "strstrstr"
  • 10.reverse yields an error
  • "10".to_s.re­verse yields "01"

Operators

  • = for assignment
  • == for testing equality
  • != not equal
  • >  >=
  • <  <=
  • For string comparison, uses lexicographical ordering (upcase or downcase before comparing)
  • and
  • or
  • not

Strings

  • buffer['stringtofind'] = 'newstringreplacement'
  • buffer.lines.to_a.reverse - turns the buffer into a list of lines. lines decides what to split on and to_a puts the lines into an array. We can use byte and chars instead of lines.
  • buffer.lines.to_a.reverse.join collates the array back into a single string
  • buffer.include? "somestring" - returns bool whether "somestring" exists. By convention, methods that return a boolean have a '?' at the end
  • x.upcase
  • concatenation: someStringVar + 'string literal'
  • "some string".reverse makes a reversed copy of a string
  • "somestring".length
  • upcase
  • downcase
  • capitalize - make first letter upper case
  • swapcase - switch case of every letter
  • center(lineWidth) - Center the given text within lineWidth
  • ljust lineWidth - pad string on left
  • rjust (lineWidth) - pad string on right
  • to escape single-quote use \'
  • variables can be used within quoted string to output their values
str = "Literal #{someVar} #{someConst} other literal #{@someClassInstanceVar}"

Arithematic

  • ** exponentiation. 5**2 (five squared), 5**0.5 (square root of 5)
  • % modulus
  • abs
  • rand - a float between 0.0 and 1.0
  • rand(100) - an integer between 0 and 99
  • to get same sequence of random numbers, seed with a certain value
seed = 400
srand seed
puts (rand(100))
seed = 0  # reset seed

Math object

  • Math::PI
  • Math::E
  • Math.Cos
  • Math.tan
  • Math.log
  • Math.sqrt

Conversion Functions

  • to_s
  • to_i
  • to_f (to float)
  • to_a  // arrays example: (1..7).to_a returns an array of 1 through 7
var1=2
var2='10'
puts var1.to_s + var2 # 210
puts var1 + var2.to_i # 12

puts 'some string'.to_f   # 0.0 since string is not valid float

Arrays

Ruby arrays are zero-based
[]  # empty array
anArray = [1, 3, 5, 7]
puts anArray # puts all members
[1, 3, 5, 7].min

someAr= [1, 9, 5, 7]
someAr.sort # yields sorted list

# arrays can contained mixed types and can contain other arrays
[1, 'New York', [true, false]]

# array iteration using iterator
cities = ['Chicago', 'New York', 'Los Angeles']
cities.each do |city|
  puts 'City: ' + city
end

Array Methods
  • length
  • reverse
  • +
  • *
  • join
  • sort
  • push, pop, last
join
cities.join(', ') # flatten to string using comma as delimiter

cities.push ' San Diego'  # add to city list, changes actual list
cities.pop   # get and remove the first element in the array
citites.last  # get the last element in the array

# map changes value of the array
str = ["AA", "BB"].map do |s|
   s.downcase
end
puts str

#output
#aa
#bb

# does not change the value of original array str = ["AA", "BB"].each do |s|
   s.downcase
end
puts str
#output
#AA
#BB

# changes the value of original array
str = ["AA", "BB"].each do |s|
   s.downcase!
end
puts str
#output
#aa
#bb

Hash

Can use any object to refer to a slot
aCityDict  = {}  #  same as Hash.new
aCityDict["Chicago"] = "Illinois"
aCityDict["Los Angeles"] = "California"

# iterating through hash
aCityDict.each do |city, state|
  puts city + ' is located in the state of ' + state
end

We can even use symbols as keys
  • dictionary["key"] = :someValue# note the colon before someValue, which is a symbol
  • dictionary.length
  • dictionary.keys
# creating a hash with multiple entries
fred = {:name => "Fred", :age => 76, : occupation => :janitor }

Conditionals

if condition  # parenthesis not required in condition
   # statements
else
   # statements
end

# Executes code if conditional is false. If the conditional is true,
# code specified in the else clause is executed.
unless conditional [then]
   code
[else
   code ]
end

Loops

3.times do
   # statements
end

5.times { <statements to execute 5 times> }
5.times do
  <statements to execute 5 times>
end

dictionary.values.each {<statements to execute> }

# %w(foo bar) is a shortcut for ["foo", "bar"]
names= %w(Fred Bert Laura Gus Waldo)
names.each { |name| puts name}

# same as above
names.each do |name|
  puts name
end

1.upto(8) do |i|
  puts i
end

[1, 2, 3, 4, 5].map do |number|
   number *2
end
=> [2,4,6,8,10]

[1, 2, 3, 4, 5].map do |number|
   number.to_s * 2
end
=> ["11","22","33","44","55"]

while <condition>
  # statements
end

Methods

# declaring a method
# method is still associated with an 
#   object (the entire program object)
def method_name <args>
  <local vars>
  # statements
  # will return nil
  # OR whatever is the last line of the method
  "some value"  # this is returned as the value of the method call
  aVar              # or return a value held by the variable
end

# invoking
aMethodName <arg1> <arg2>

Method names start with lower case except for operator methods (e.g. +, ==)

def load_data(path)
   city_dict = {}
   File.foreach(path) do |line|
     city, state = line.split(': ')
     city_dict [:city] = city
     city_dict [:state] = state
  end
  lines
end

# call method
city_dict = load_data(path)
  • Method calls can be chained
  • Method call with exclamation mark at the end changes the object (i.e. the content of the object) it is applied to
  • Method with a ? at the end returns a boolean or answer to a question

Object Orientation

Operators are object methods
# Fixnum is derived from Integer class
class Fixnum < Integer
  def + numeric
    # + operator for Fixnum can be redefined
  end
end

Existing classes can be extended
# Add a new methods square and cube to Numeric class
class Numeric
  def square
    return self ** 2
  end
  alias :sqr :square   # define another name (alias) for square

   def cube
     return self ** 3
   end

 end

2.sqr # 4

Class

  • The :: is a unary operator that allows: constants, instance methods and class methods defined within a class or module, to be accessed from anywhere outside the class or module.
# creating objects
anArray = Array.new  # or anArray = []
aString = String.new   # or aString =''
aTime = Time.new
someTime = Time.makeTime(2013, 8, 8)

# declare a class
class <classname> < <superclass>
  # attr_accessor  is method to define attributes of a class
  attr_accessor :title, :time, :fulltext, :mood

def initialize( title, mood, fulltext )
    # use @ to access instance vars
    @time = Time.now
    @title, @mood, @fulltext = title, mood, fulltext
  end
end

# using a class
class_instance= <classname>.new

# use with initialize method
class_instance= <class_name>.new(<args>")

# Extending an existing class
class Integer
  def to_BinaryStr
      # Convert to binary representation given an integer
      # logic to calculate binStr
      puts self  # self refers to the integer object
      binStr  # return value
  end
end

# overriding methods
can redefine to_s to do different formatting for Integer class

# create our own class
class MyClass < <superclass>
  CONST = "some const"

  # getter and #setter
   attr_accessor :accVar1, : accVar2
 
   # getter only
   attr_reader : accVar3

   #setter only
   attr_writer :accVar4

  # instance variable get accessor (old school)
  def ClassIntanceVariableAccessor
     @myClassInstanceVariable
  end

  # instance variable setter (old school)
  def accVar5= accVar5
     @accVar5 = accVar5
  end

  def initialize
    #  Initialize state of the object
  end

  def classMethod
    # statements
      @myClassInstanceVariable = someValue
      exit # exit/return immediately
  end

  # invoked using MyCall.class_method
  def MyClass.class_method     # class method
    # code for class method
  end

 # cannot be called with an explicit receiver. Because you cannot
 # specify an object when using them, private methods can be 
 # called only in the defining class and by direct 
 # descendents within that same object.
private
  def privateClassMethod
    # statements
      @myClassInstanceVariable = someValue
  end
# Can be invoked only by objects of the 
# defining class and its subclasses. 
# Access is kept within the family.
protected

end

Closures - Blocks and Procs

  • Given a block of code (do.. end)
  • Wrap it in a proc object
  • Can stored into a variable or passed as method argument
  • Execute proc object at will
  • Block of code is an object
  • Method cannot be passed to another method but proc can be passed as an argument
  • Methods cannot be returned from another method but proc can be
aVar = Proc.new do |arg|
  # statements
end

# to execute
aVar.call <arg>

# passing proc into a method
def receiverMethod aProc
   # statements
   aProc.call
   #statements
end

# define the proc
aProc = Proc.new do
  # statements
  puts 'hello'
end

# execute the receiver method
receiverMethod aProc 

# currying - using proc returned to compose methods
# proc that composes the passed in methods on the argument supplied
def compose p1, p2
  # return a proc (i.e. do not execute the code below immediately)
  # lazy evaluation
  Proc.new do |x| # the returned proc will accept on arg
     p2.call(p1.call(x))
  end
end

# first proc
p1 = Proc.new do |x|
  x - 100
end

# second proc
p2 = Proc.new do |x|
  x.abs
end

# variable to store the composed proc
composeProc = compose p1 p2

# execute the proc
composeProc.call 50


# passing a block into a method for execution without have to assign to a variable
class Array
  def eachNonNil(blockOfCodeToExecute)
     # iterate through all members
     self.each do |object|
        if (object != nil)
          blockOfCodeToExecute.call object
        end
     end
  end
end # class

print = Proc.new do |x|
  puts x.to_s
end

# print out non-nil members
x = [1, nil, 2, 3, nil]
x.eachNonNil print


# Code profiling, &codeBlock accepts a do..end code block
def profileCode codeBlockName, &codeBlock
  startTime = Time.now
  codeBlock.call
  duration = Time.now - startTime
  puts codeBlockName+':  '+duration.to_s+' seconds'
end

profileCode "Factorial of 6" do   6.dow­nto(1).inj­ect(:*) end

Modules

  • Act as namespaces
  • Allow sharing of code amongst classes
You call a module method by preceding its name with the module's name and a period (.), and you reference a constant using the module name and two colons (::). Modules are not class; they are merely a libraries of code.

module Mycompany
  module AppName
    module LibName
         def LibName.MethodName arg
           # code
         end
         class <classname>
            #code
        end
    end
  end
end

To use:
include Mycompany::AppName
LibName.MethodName arg

Example:
### citymodule.rb
module CityModule
    def CityModule.load_city_data
  # code
  puts 'hello from module'
    end
end

### main 
require_relative 'CityModule'
city_dict = CityModule.load_city_data

Mixins

  • Include a module within a class definition
  • All the module's instance methods are suddenly available as methods in the class as well
  • Mixed-in modules effectively behave as superclasses
  • Include takes the name of a module, in the form of a constant, include method accepts any number of Module objects to mix
class <class_name>
  include modulename
  # ...  
end  

File System

Dir.entries "/" 
"/" is an argument to the method; in Ruby argument is called an attachment

List only text files ([ ] below is like entries method above)
Dir["/*.txt"]

print File.read("/data/x.txt")
FileUtils.­cp('/data/x.txt', '/Hom­e/x.t­xt')

# open file in append mode
File.open("/Home/data.txt", "a") do |f|

# add data to file
f << "News  http://cnn.com/"

# read file content
print File.read("/Home/data.txt")

# file change time
 File.mtime("/Home/data.txt")
File.mtime("/Home/data.txt").hour

Wednesday, July 10, 2013

Languages: Ruby on Rails

What is it?

Ruby on Rails is framework for building Web applications. The framework uses the Model-View-Controller (MVC) design pattern and uses convention over configuration when defining the application source structure. For persistence, Rails uses the ActiveRecord pattern and object-relational mapping for storing data. 

Installation

Create an Application

To create an application, change to the directory to where you would like to store the source code. Issue the following command:
> rails new <appname>

The command creates file and folders for the application.

Application Structure

  • Uses models, controls, and views (MVC)
  • Uses routes to map Urls to controller methods

Creating a Controller

> rails generate controller <controller-name-in-plural-form> <nameofview1> <nameofview2>
  • _controller is appended to controller file name
  • derives from ApplicationController which in turn derives from ActionController::Base

Adding an Action to Controller

  • Action is a method inside the controller
  • Method "index" is the default page for a controller
class MyController < ApplicationController
  def index
  end
end

Add a View for the Controller Method

  • A subfolder with the same name as controller is created under view folder to hold views for the controller
  • Name the view file same is as the controller method
  • Named <controllermethodname>.html.erb - contains html, embedded ruby, js, css in the view

Add Routes to the Controller

In config folder, there is routes.rb. Define routes for the controller.

# define routes for controller
resources :<controllername>

7 routes are automatically generated:
  • index
  • show
  • new
  • create (normally, no associated view)
  • edit
  • update (normally, no associated view)
  • destroy (normally, no associated view)

Running the Web Application

From the source folder, run:
> rails server
  • Starts WEBrick server
  • Application is available on the echoed port (Url)
  • Browse to the Url
  • Shows the application page (app development environment can be inspected)
  • To access the application: url/<appName>

Creating a model

rails generate model <controller-name>
  • Creates a migration code that can be run to creates table for the model. Use rake (Ruby's build system) to run the script. rake db:migrate
  • Model file is created under models folder with the same name as the <controllername>
  • <controllername> (singular) can be used to access the table
rails console
  • Starts ruby dev environment
  • Can create database rows
  • Can use <controllername>.new, <controllername>.find, <controllername>.<membername>, <controllername>.save, <controllername>.update_attribute, <controllername>.destroy
<controllername>.update_attributes(:membername => "val", member2name => num)

Controller Actions

class PersonsController < ApplicationController
def index
  @persons= Persons.all
end

def show
end

def new
end

def create
end

def edit
end

def update
end

def destroy
end

end

View

Using embedded Ruby.

<h1>All People</h1>
<%  persons.each do |person| %>
  <p><%= person.name %>
<% end %>