Ruby

From Wiki2
Revision as of 11:59, 5 November 2011 by Tim (talk | contribs)

setting up new app

goto /users/tim/code/ruby

Centred text

Block quote

rails new appname
sets up directory system
bundle install
installs gems
.gitignore
installed with rails new
git init
starts new repository
git add .
git status; tells you what branch you are on and if you have stuff to commit
git commit
commits change locally
git log
of commits

on github

new repository

back on local machine

git remote add origin git@github.com
mckennatim/rubyapp2.git: this line is given in github
git push -u origin master
get checkout -b modify-README
creates a new branch
mate README
now in new branch
git mv README README.markdown
mate README.markdown
git commit -am "improve readme"
commit locally all, message
git checkout master
moves back to master branch
git merge modify-README
bringes changes of the modify-README branch into the master branch
git push
all you need to push it back to github

to use hosting site

heroku
heroku keys:add
heroku create
git push heroku master


git

git mergetool
to resolve conflicts

heroku

sometimes heroku logs shows an error To force compile of .css files you add ... config.assets.compile = true to config/environments/production.rb

heroku wouldn't work with ror3
fixed config/application.rb to read..
require File.expand_path('../boot', __FILE__)

# Pick the frameworks you want:
#require "active_record/railtie"
require "action_controller/railtie"
require "action_mailer/railtie"
require "active_resource/railtie"
require "sprockets/railtie"
# require "rails/test_unit/railtie"

if defined?(Bundler)
  # If you precompile assets before deploying to production, use this line
  Bundler.require(*Rails.groups(:assets => %w(development test)))
  # If you want your assets lazily compiled in production, use this line
  # Bundler.require(:default, :assets, Rails.env)
end
require "active_record"

kill rail server

lsof -wni tcp:3000, kill -9 PID

ruby syntax

>> nil.empty?
NoMethodError: You have a nil object when you didn't expect it!
You might have expected an instance of Array.
The error occurred while evaluating nil.empty?
>> nil.to_s.empty?      # Message chaining
=> true

It’s worth noting that the nil object is special, in that it is the only Ruby object that is false in a boolean context, apart from false itself:

>> if nil
>>   true
>> else
>>   false        # nil is false
>> end
=> false

# 0 (and everything other than nil and false itself) is true

>>  "foo bar     baz".split     # Split a string into a three-element array
=> ["foo", "bar", "baz"]
>> "fooxbarxbazx".split('x')
=> ["foo", "bar", "baz"]

arrays

>> a.sort
=> [8, 17, 42]
>> a.reverse
=> [17, 8, 42]
>> a.shuffle
=> [17, 42, 8]
>> a.push(6)                  # Pushing 6 onto an array
=> [42, 8, 17, 6]
>> a << 7                     # Pushing 7 onto an array
=> [42, 8, 17, 6, 7]
>> a << "foo" << "bar"        # Chaining array pushes
=> [42, 8, 17, 6, 7, "foo", "bar"]
>> a
=> [42, 8, 17, 7, "foo", "bar"]
>> a.join                       # Join on nothing
=> "428177foobar"
>> a.join(', ')                 # Join on comma-space
=> "42, 8, 17, 7, foo, bar"

ranges

Closely related to arrays are ranges, which can probably most easily be understood by converting them to arrays using the to_a method:

>> 0..9
=> 0..9
>> 0..9.to_a              # Oops, call to_a on 9
NoMethodError: undefined method `to_a' for 9:Fixnum
>> (0..9).to_a            # Use parentheses to call to_a on the range
=> [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]

>> a = %w[foo bar baz quux]         # Use %w to make a string array.
=> ["foo", "bar", "baz", "quux"]
>> a[0..2]
=> ["foo", "bar", "baz"]

Ranges also work with characters:

>> ('a'..'e').to_a
=> ["a", "b", "c", "d", "e"]

>> 3.times { puts "Betelgeuse!" }   # 3.times takes a block with no variables.
"Betelgeuse!"
"Betelgeuse!"
"Betelgeuse!"
=> 3
>> (1..5).map { |i| i**2 }          # The ** notation is for 'power'.
=> [1, 4, 9, 16, 25]
>> %w[a b c]                        # Recall that %w makes string arrays.
=> ["a", "b", "c"]
>> %w[a b c].map { |char| char.upcase }
=> ["A", "B", "C"]

>> ('a'..'z').to_a.shuffle[0..7]       # Pull out the first eight elements.
=> ["f", "w", "i", "a", "h", "p", "c", "x"]
>> ('a'..'z').to_a.shuffle[0..7].join  # Join them together to make one string.
=> "mznpybuj"
>> ('a'..'z').to_a[0..7]
=> ["a", "b", "c", "d", "e", "f", "g", "h"]


params

>> params[:user] = { :name => "Michael Hartl", :email => "mhartl@example.com" }
=> {:name=>"Michael Hartl", :email=>"mhartl@example.com"}
>> params
=> {:user=>{:name=>"Michael Hartl", :email=>"mhartl@example.com"}}
>>  params[:user][:email]
=> "mhartl@example.com"

foreach

>> flash = { :success => "It worked!", :error => "It failed. :-(" }
=> {:success=>"It worked!", :error=>"It failed. :-("}
>> flash.each do |key, value|
?>   puts "Key #{key.inspect} has value #{value.inspect}"
>> end
Key :success has value "It worked!"
Key :error has value "It failed. :-("

print

>> p :name             # Same as 'puts :name.inspect'
:name

function calls

Parentheses on function calls are optional.

stylesheet_link_tag('blueprint/screen', :media => 'screen')
stylesheet_link_tag 'blueprint/screen', :media => 'screen'

classes

Let’s make a Word class with a palindrome? method that returns true if the word is the same spelled forward and backward:

 >> class Word
 >>   def palindrome?(string)
 >>     string == string.reverse
 >>   end
 >> end
 => nil

We can use it as follows:

 >> w = Word.new              # Make a new Word object.
 => #<Word:0x22d0b20>
 >> w.palindrome?("foobar")
 => false
 >> w.palindrome?("level")
 => true

self and inheritence

Word could inherit from String instead

>> class Word < String             # Word inherits from String.
>>   # Return true if the string is its own reverse.
>>   def palindrome?
>>     self == self.reverse        # self is the string itself.
>>   end
>> end
=> nil

Then word would also have all the same methods as strings:

>> s = Word.new("level")    # Make a new Word, initialized with "level".
=> "level"                  
>> s.palindrome?            # Words have the palindrome? method.
=> true                     
>> s.length                 # Words also inherit all the normal string methods.
=> 5

Somewhat amazingly, Ruby lets you add methods to built in classes; Ruby classes can be opened and modified, allowing ordinary mortals such as ourselves to add methods to them:17

>> class String
>>   # Return true if the string is its own reverse.
>>   def palindrome?
>>     self == self.reverse
>>   end
>> end
=> nil
>> "deified".palindrome?
=> true

=example_user.rb

class User
  attr_accessor :name, :email

  def initialize(attributes = {})
    @name  = attributes[:name]
    @email = attributes[:email]
  end

  def formatted_email
    "#{@name} <#{@email}>"
  end
end


attr_accessor :name, :email

creates “getter” and “setter” methods that allow us to retrieve (get) and assign (set) @name and @email instance variables.

The first method, initialize, is special in Ruby: it’s the method called when we execute User.new. This particular initialize takes one argument, attributes:

 def initialize(attributes = {})
   @name  = attributes[:name]
   @email = attributes[:email]
 end

Here the attributes variable has a default value equal to the empty hash, so that we can define a user with no name or email address (recall from Section 4.3.3 that hashes return nil for nonexistent keys, so attributes[:name] will be nil if there is no :name key, and similarly for attributes[:email]).

Finally, our class defines a method called formatted_email that uses the values of the assigned @name and @email variables to build up a nicely formatted version of the user’s email address using string interpolation (Section 4.2.2):

 def formatted_email
   "#{@name} <#{@email}>"
 end

Let’s fire up the console, require the example user code, and take our User class out for a spin:

>> require './example_user'     # This is how you load the example_user code.
=> ["User"]
>> example = User.new
=> #<User:0x224ceec @email=nil, @name=nil>
>> example.name                 # nil since attributes[:name] is nil
=> nil
>> example.name = "Example User"           # Assign a non-nil name
=> "Example User"
>> example.email = "user@example.com"      # and a non-nil email address
=> "user@example.com"
>> example.formatted_email
=> "Example User <user@example.com>"

We can omit the curly braces for final hash arguments, we can create another user by passing a hash to the initialize method to create a user with pre-defined attributes:

>> user = User.new(:name => "Michael Hartl", :email => "mhartl@example.com")
=> #<User:0x225167c @email="mhartl@example.com", @name="Michael Hartl">
>> user.formatted_email
=> "Michael Hartl <mhartl@example.com>"