Learning Ruby

Resourse

  • start with ruby on rails
    http://railsapps.github.io/installrubyonrails-mac.html

  • change ruby version
    https://rvm.io/rubies/default

  • tutorial: https://www.railstutorial.org/

    Command Lines

  • rails _4.2.2_ new sample_app

  • bundle install

  • bundle install –without production

  • bundle update

  • heroku create

  • bundle exec rake db:migrate

  • bundle exec rake db:rollback

  • heroku run rake db:migrate

  • git push heroku master

  • rails console

  • rails generate scaffold …

  • rails generate model User name:string email:string

  • rails destroy model User

  • rails generate controller StaticPages home help

  • rails destroy controller StaticPages home help

  • bundle exec rake test (3)

  • bundle exec guard init (3.7.3)

  • bundle exec guard

  • ps aux | grep spring

Testing

Add this into

1
2
3
4
5
6
7
8
9
10
11
ENV['RAILS_ENV'] ||= 'test'
require File.expand_path('../../config/environment', __FILE__)
require 'rails/test_help'
require "minitest/reporters"
Minitest::Reporters.use!
class ActiveSupport::TestCase
# Setup all fixtures in test/fixtures/*.yml for all tests in alphabetical
# order.
fixtures :all
# Add more helper methods to be used by all tests here...
end
  • git checkout master
  • git checkout -b static-pages
  • git checkout master
  • git merge static-pages

Shortcut of Commands

Full command Shortcut
$ rails server $ rails s
$ rails console $ rails c
$ rails generate $ rails g
$ bundle install $ bundle
$ rake test $ rake

Because Ruby uses CamelCase for class names (Section 4.4), my preference is to refer to controllers using their CamelCase names, but this is a matter of taste. (Since Ruby filenames typically use snake case, the Rails generator converts CamelCase to snake case using the underscore method.)

ruby

  • Single-quoted strings are often useful because they are truly literal, and contain exactly the characters you type, like ‘\n’.
1
2
3
4
5
6
7
8
9
>> s = "foobar"
>> if s.nil?
>> "The variable is nil"
>> elsif s.empty?
>> "The string is empty"
>> elsif s.include?("foo")
>> "The string includes 'foo'"
>> end
=> "The string includes 'foo'"

Since everything in Ruby is an object, it follows that nil is an object, so it too can respond to methods. One example is the to_s method that can convert virtually any object to a string:

1
2
>> nil.to_s.empty?      # Message chaining
=> true

Blocks

1
2
3
4
>> (1..5).each do |number|
?> puts 2 * number
>> puts '--'
>> end

the map method returns the result of applying the given block to each element in the array or range.

1
2
3
4
>> %w[A B C].map { |char| char.downcase }
=> ["a", "b", "c"]
>> %w[A B C].map(&:downcase)
=> ["a", "b", "c"] #shorthand
1
2
3
4
5
6
7
8
9
10
>> ('a'..'z').to_a                     # An alphabet array
=> ["a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m", "n", "o",
"p", "q", "r", "s", "t", "u", "v", "w", "x", "y", "z"]
>> ('a'..'z').to_a.shuffle # Shuffle it.
=> ["c", "g", "l", "k", "h", "z", "s", "i", "n", "d", "y", "u", "t", "j", "q",
"b", "r", "o", "f", "e", "w", "v", "m", "a", "x", "p"]
>> ('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"

Array and Hash

[] for Array, {} for Hash

1
>> a = [42, 8, 17]

Instead of defining hashes one item at a time using square brackets, it’s easy to use a literal representation with keys and values separated by =>, called a “hashrocket”:

1
2
>> user = { "first_name" => "Michael", "last_name" => "Hartl" }
=> {"last_name"=>"Hartl", "first_name"=>"Michael"}

Symbol

in Rails it is much more common to use symbols instead. Symbols look kind of like strings, but prefixed with a colon instead of surrounded by quotes. For example, :name is a symbol. You can think of symbols as basically strings without all the extra baggage

1
2
3
4
5
6
>> user = { :name => "Michael Hartl", :email => "michael@example.com" }
=> {:name=>"Michael Hartl", :email=>"michael@example.com"}
>> user[:name] # Access the value corresponding to :name.
=> "Michael Hartl"
>> user[:password] # Access the value of an undefined key.
=> nil

new syntax for defining hash

1
2
3
4
5
6
>> h1 = { :name => "Michael Hartl", :email => "michael@example.com" }
=> {:name=>"Michael Hartl", :email=>"michael@example.com"}
>> h2 = { name: "Michael Hartl", email: "michael@example.com" }
=> {:name=>"Michael Hartl", :email=>"michael@example.com"}
>> h1 == h2
=> true

inspect

inspect returns a string with a literal representation of the object it’s called on

1
2
3
4
5
6
>> puts (1..5).to_a.inspect    # Put a literal array.
[1, 2, 3, 4, 5]
>> puts :name, :name.inspect
name
>> p :name # Same output as 'puts :name.inspect'
:name

class

1
2
3
4
5
6
7
8
9
10
11
12
13
>> class Word < String             # Word inherits from String.
>> # Returns true if the string is its own reverse.
>> def palindrome?
>> self == reverse # self is the string itself. equals to self == self.reverse
>> end
>> end
=> nil
>> 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

Integration Test

  • rails generate integration_test site_layout
  • bundle exec rake test:integration
  • bundle exec rake test TEST=test/integration/users_login_test.rb
  • bundle exec rake test TEST=test/integration/users_login_test.rb TESTOPTS=”–name test_login_with_valid_information”

Model

  • rails generate model User name:string email:string
  • rails generate migration add_remember_digest_to_users remember_digest:string
  • rails generate migration add_admin_to_users admin:boolean
  • bundle exec rake db:migrate
  • rails generate migration add_activation_to_users activation_digest:string activated:boolean activated_at:datetime
  • bundle exec rake db:rollback
  • rails console –sandbox
  • bundle exec rake test:models
  • rails generate migration add_index_to_users_email
    This uses a Rails method called add_index to add an index on the email column of the users table. The index by itself doesn’t enforce uniqueness, but the option unique: true does.

Sessions

  • bundle exec rake routes

There are four main ways to steal cookies:

  1. using a packet sniffer to detect cookies being passed over insecure networks
  2. compromising a database containing remember tokens
  3. using cross-site scripting (XSS)
  4. gaining physical access to a machine with a logged-in user.

Rails preventes the first problem by using Secure Sockets Layer (SSL) site-wide, which protects network data from packet sniffers.
It prevents the second problem by storing a hash digest of the remember token instead of the token itself, in much the same way that we stored password digests instead of raw passwords.
Rails automatically prevents the third problem by escaping any content inserted into view templates.
Finally, although there’s no iron-clad way to stop attackers who have physical access to a logged-in computer, rails will minimize the fourth problem by changing tokens every time a user logs out and by taking care to cryptographically sign any potentially sensitive information we place on the browser.

Heroku

  • heroku rename rails-tutorial-hello

Note that the application will briefly be in an invalid state after pushing but before the migration is finished. On a production site with significant traffic, it is a good idea to turn maintenance mode on before making the changes:

1
2
3
4
$ heroku maintenance:on
$ git push heroku
$ heroku run rake db:migrate
$ heroku maintenance:off