M - Model - Our objects, Its the object oriented approach to design and it encapsulates the data in the database
V - View - Presentation layer - It is what the user sees and interacts with - pages/html/css/javascript
C - Controller - Process and respond to events such as user actions and envoke changes to the model and view based on that. Its going to make decisions for us and control what happens
Conventional => Browser <-> Page <-> Database <=> Page <=> Browser
Rails => Browser <-> Controller <-> Model <-> Database <=> Model(handles data) <=> Controller(handles decisions) <=> View (handles presentation) <=> Browser
M - Handles Data - Code for data goes here (database related shit) V - Handles Presentation - Code for presentation goes here (html css) C - Handles Decisions - Code for decisions goes here
Rails names for MVC:
Models = ActiveRecord Views = ActionView Controller = ActionController
ActionPack = ActionView & ActionController grouped/packaged together.
##Chapter 2 Notes
###Terminal and Unix
cd = Change directories cd ~ = go back to home directory ls = listing of what is in the directory cd folder/folder to move multiple directories at once cd ../.. go back multiple directories at once -- When space in folder name, \ ie. cd Application\ Support/ ls -la shows list view with hidden files
unimportant
echo $SHELL
/bin/bash
Born again shell unimportant
Setting up MySQL...
Install mysql. Install package/Install preference pane -- Run mysql
COMMANDS:
mysql --version (shows mysql version)
mysql (starts mysql database)
SHOW DATABASES; (shows databases)
mysql -u root (login as root user)
SET PASSWORD FOR root@localhost=PASSWORD('password'); (sets password for root mysql DB)
FLUSH PRIVILEGES; (flushes privileges)
exit (exit DB)
mysql -u root -p (login root user with password)
Different Types of Web Servers ---- Apache 1 or 2 - Ships with OSX / Passenger or mod_rails NginX - Competitor to Apache Lighttpd (lighty) Mongrel WEBrick - Comes preinstalled/preconfigured with rails, Set to default.
Navigate to directory using cd (dirname)
rails new project_name -d mysql
In order to see web project, you need to launch web server.
rails s or rails server to launch WEBrick. View on localhost:3000
Look back to MVC architecture Browser->controller->view (model or data later)
In the root of project folder
rails generate controller (controller name) (view name/names)
ex. rails generate controller demo index
Open demo_controller.rb
DemoController < ApplicationController (demo controller inherits from application controller)
def index (method called index) (OFTEN CALLED ACTIONS INSIDE OF CONTROLLERS!!!!)
Database Terms:
Database = A set of tables
- 1 Application = 1 Database
- Example : simple_cms_development
- All lowercase with underscores
- Grant Access permissions at the database level
Table = Set of columns and rows
- 1 Model = 1 Table
- Represents a single concept (a noun)
- Examples: users, subjects, pages
- All lowercase with underscores, plural
- Relationships between tables
Column = Set of data of a single simple type
- 1 Attribute = 1 column
- Example : first_name, last_name_, email, password
- Column types are strings, integers, etc.
Row: A single record of data
- 1 object or instance = 1 row
- Example: "Kevin", "Skoglung"
Field: The intersection of a column and a row
- Has a single value
- Example: first_name: "Kevin"
- Often used interchangably with "column"
Foreign key: A table column whose values reference rows in another table
- The foundation of relational databases
- Example: pages.subject_id
- Singular foreign table name+"_id"
Index: A data structure on a table to increase lookup speed
- Like the index at the back of a book
Schema: The structural definition of a database
- Defines the tables, columns, and indexes of a database
Strings - Web applications consist of doing "stuff" and returning a string of html back to the browser
"" #empty string
"foo" #non-empty string
"foo" + "bar" => "foobar"
- is the concatanation operator for addition
Local variable - This variable is not defined outside of the method
>>first_name = "James"
=> "James"
>>last_name = "Dullaghan"
=> "Dullaghan"
>> "#{first_name} #{last_name}"
Printing Strings
puts = PRINT STRING
ex
puts "foo"
foo
=> nil
nil = nehil = nothing in latin
puts first_name
James
Double quoted strings and single quoted strings
"foo\n"
outputs "foo\n" (foo with new line)
'foo\n'
outputs "foo\\n" (foo with literal backslash n)
puts "foo\n"
puts 'foo\n'
"#{first_name} #{last_name}"
=> "James Dullaghan"
'#{first_name} #{last_name}'
=> "\#{first_name} \#{last_name}"
Strings are objects. What you do with strings is call methods on them.
ex
"foobar".length
=> 6
"foobar".empty?
=> false
"".empty?
=> true
Any method with a ? at the end (.empty?) is a boolean method. Takes on one of two values. Either true of false
Boolean methods are good for control flow. Sometimes you want to do something in one case, and something else in another case.
s = "foobar" (defining string = foobar)
=> "foobar"
if s.empty?
"The String is empty"
else
"The String is not empty"
end
=> "The String is not empty"
if @instancevariable.nil?
base_instance_variable
else
"#{base_instance_variable} | #{@instance_variable}"
end
Combination using logical operators
x = "foo"
=> "foo"
y = ""
puts "Both strings are empty" if x.empty? && y.empty?
=> nil
Because x.empty? is false, but y.empty? is true, it returns nothing, as both need to be true to return "Both strings are empty"
puts "One of the strings is empty" if x.empty? || y.empty? (double pipe character is OR statement.)
One of the strings is empty
=> nil
same as
if x.empty? || y.empty?
puts "One of the strings is empty"
end
One of the strings is empty
=> nil
Not operator = !
puts "x is not empty" if !x.empty?
x is not empty
=> nil
puts "x is not empty" unless x.empty?
The empty method can be called on more than just strings. Arrays respond to the empty method
nil.empty?
(to see if nothing is in fact empty) Returns 'NoMethodError: You have a nil object when you didn't expect it! You might have expected an instance of an array. This is a Ruby Exception. (nil is neither not empty or not not empty.)
nil can be read as a string though. To convert to a string:
nil.to_s
""
nil.to_s.empty?
=> true
Check is nil is in fact empty. This is called method chaining or putting multiple methods together.
false belongs to the false class
false.class
=> FalseClass
nil is false (nothing should be false) 0 is true (0 is something so it is true although it is zero) only false and nil are false in ruby
if nil
"hello"
else
"goodbye"
end
=> "goodbye"
if 0
"hello"
else
"goodbye"
end
=> "hello"
!!nil
=> false (to force boolean)
!!0
=> true
def title
base_title = "Ruby On Rails Tutorials Sample App"
if @title.nil?
base_title
else
"#{base_title} | #{@title}"
end
end
Reading through these lines...
- Method is named title
- the base_title string is set.
- if @title.nil? (if the variable is not defined (nil) return true or false)
- if true return base_title
- else return base_title | @title variable
Each method in whichever controller can have an @title variable defined, for example, to make the page names display which page youre actually on.
In ruby methods and functions are the same things.
"".length
=> 0
def string_message(something_crazy)
if something_crazy.nil?
"It's nil!"
else
"It's something!"
end
end
if we call something_crazy() with something in it, it will return out method/function
string_message(nil)
=> "it's nil!"
string_message("")
=> "it's something"
Understanding the title helper we wrote
function definition:
def string_message(arguement_goes_here)
base_title = "Ruby on Rails Tutorial Sample App" #setting a local variable
if @title.nil? #@title we set in controller, if @title is nothing, return the base_title we set locally above
base_title
else #otherwise
"#{base_title} | #{@title}" #interpolate the base title we set locally above, with pipe character, and return @title variable set in controller
end
end
interpolation has to be a double quoted string, otherwise it returns the literal #{base_title} | #{@title}
###Other data structures
<%= stylesheet_link_tag 'blueprint/screen', :media => 'screen' %=>
this is a hash
a = [42, 8, 17]
a[0]
=> 42
a.last
a.second
a.length
a.empty?
=> false
a == [42, 8, 17]
=> true
###Other methods on Arrays
enumerability or enumerable
-
running through EACH element in turn
(1..5).to_a => [ 1, 2, 3, 4, 5 ] (1..5).each => <Enumerator: 1..5:each>
Goes through each element 1 - 5 in turn.
(1..5).each { |i| puts 2**i }
2
4
8
16
32
=> 1..5 #not important, the evaluation
define block with any variable, print with puts, 2 to the power of i
###print to an array long way to do it...
a = []
=> []
(1..5).each { |i| a << 2**i } #same as above, only a is appending the values of 2**i
=> 1..5
a
=> [2, 4, 8, 16, 32]
real way to do it
(1..5).map { |i| 2**i }
[2, 4, 8, 16, 32]
accumulate is called inject in the ruby api
second notation for blocks
(1..5).map do |i|
2**i
end
=> [2, 4, 8, 16, 32]
3.times do
puts "Hello!"
end
Symbols are weird colon things in rails
"foo".class
=> String
:foo.class
=> Symbol
Strings and symbols can be used as labels
user = {}
user.class
=> Hash
hashes are like arrays, but instead of having integers, they can have more general things
-
arrays are indexed by integers
-
hashes are used for more general things
user["first_name"] = "Michael" => "Michael" user["last_name"] = "Hartle" => "Hartle"
difference between arrays and hashes are order:
- Arrays know what order
- Hashes don't.
Hashes are key value pairs, which are a key, that has a corresponding name.
user["first_name"] = "James"
####Almost never use strings as keys!
user = { "first_name" => "Michael", "last_name" => "Hartle" }
####Almost always use symbols as keys!
user = { :first_name => "James", :last_name => "Dullaghan" }
###Symbols - (Most programming languages use strings)
Symbols are more powerful because strings are looked up by each individual character. This is less efficient when you're trying to index.
string is 4 characters long. set s equal to "name". Does s equal name? True
"name".length
=> 4
s = "name"
=> "name"
s == "name"
=> true
symbol is also 4 characters long. Old ruby used to throw error, because it didn't keep track of symbol length.
:name.length
=> 4
split a string into it's individual characters, it creates an array of the different letters
"name".split('')
=> ["n","a","m","e"]
split a symbol into it's individual characters, and you can't because symbols are not indexed by their seperate characters. They are indexed as their symbol. Throws a NoMethodError
:name.split('')
NoMethodError
user[:first_name]
=> "first_name"
##FASTER
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
=> {:success=>"It worked!", :error=>"It failed."}
Key :success has value "It worked!" Key :error has value "It failed."
inspect method on key calls .to_s on a symbol
"#{:success}"
=> "success"
:success.to_s
=> "success"
"#{:success.inspect}"
=> ":success"
:success.inspect
=> ":success"
puts :success
=> success
puts :success.inspect
=> :success
it is more convenient to puts an array with the inspect method
puts [1, 7, 18]
1
7
18
=> nil
more convenient this way
puts [1, 7, 18].inspect
[1, 7, 18]
=> nil
alias in console is p
p [1, 7, 18].inspect
options hash - in ruby curly brackets and parens are optional
###RUBY CLASSES
s = "foobar"
=> "foobar"
s.class
=> String
A class is a way of describing an abstract quality of a bunch of objects. Any particular string is a concrete object, but all strings belong to the string class.
s = "foobar"
Constructed an object, which is an instance of the string class.
- this is what is known as a constructor.
- in this case it's an implicit constructor because we use literal double quotes to construct the string
we could write it out as a literal string
s = String.new("foobar")
=> "foobar"
>> s
=> "foobar"
write out a literal array
>> a = Array.new([1, 2, 3])
=> [1, 3, 2]
write out a literal hash
>> h = Hash.new
=> {}
>> h[:foo]
=> nil
write out a literal hash that returns something other than nil
>> h = Hash.new(0)
=> {}
>> h[:foo]
=> 0
###INHERITANCE
string s
>> s
=> "foobar"
# s's class
>> s.class
=> String
#one class above s's class of string
>> s.class.superclass
=> Object
>> s.class.superclass.superclass
can keep going and going.
=> BasicObject
>> s.class.superclass.superclass.superclass
Creating a class
>class Word
> def palindrome?(string)
> string == string.reverse
> end
>end
=> nil
>w = Word.new
>w.palindrome?("foobar")
=> false
>w.palindrome?("level")
=> true
Restart rails console
> class Word < String
> def palindrome?
> self == self.reverse
> end
> end
=> nil
> w = Word.new("foobar")
=> "foobar"
> w.class
=> Word
> w.palindrome?
=> false
> w = Word.new("deified")
=> "deified"
> w.palindrome?
=> true
> class String
> def palindrome?
> self == reverse
> end
> end
=> nil
> "deified".palindrome?
=> true
extremely poor form to add classes to ruby base design by adding to base classes
string with nothing in it is empty
> "".empty?
=> true
string with whitespace is empty, as in nothing visible is in it, but it's not empty, because whitespace is something
> " ".empty?
=> false
rails introduces blank method to deal with empty strings that have whitespace
> " ".blank?
=> true
#not just for strings
nil.blank?
pc = PagesController.new
pc.home
=> "Home"
###Creating our own class
class User
attr_accessor :name, :email
end
define user class instance of user has 2 attributes - Getter & Setter methods
def initialize(attributes = {})
@name = attributes[:name]
@email = attributes[:email]
end
def formatted_email
"#{@name} <#{@email}>" # string interpolation
end
end
- we need some method to initialize these objects/ Respond to user.new/ default value is nothing
- define the two instance variables - a variable that is available everywhere inside the class
- Pulling out hashkeys here - No conincedence :name and :email
- attr_accessor given a symbol :name it will create Getter and Setter methods for @name
> require './user'
=> true
> user = User.new(:name => "Michael Hartle", :email => "[email protected]") # define user & give it attributes
=> #<User:0x007fc344dfff98 @name="Michael Hartle", @email="[email protected]">
> user.name # getter method attr_accessor gives us
=> "Michael Hartle"
> user.email # getter method attr_accessor gives us
=> "[email protected]"
> user.email = "[email protected]" # setter method attr_accessor gives us
=> "[email protected]"
> user.formatted_email
=> "Michael Hartle <[email protected]>"
###NESTED HASH!!! - USED AS AN INITIALIZATION
> params = {} # empty hash, as params
=> {}
> params[:user] = { :name => "Michael Hartle", :email => "[email protected]" } # set params[:user] is equal to a hash itself
=> {:name=>"Michael Hartle", :email=>"[email protected]"}
> params
=> {:user=>{:name=>"Michael Hartle", :email=>"[email protected]"}} # params is a nested hash, with a key, :user whos value is another hash. With key :name and key :email
> user = User.new(params[:user]) # We can make another user - pull out that hash by giving params that :user key
=> #<User:0x007fc344e1d8b8 @name="Michael Hartle", @email="[email protected]"> # Exactly the same as above - Very common in rails