prisskreative
5/20/2015 - 6:14 PM

Rails new app

Rails new app

rails new appName

# skip bundle from the gemfile 
rails new address-book --skip-bundle --skip-turbolinks --database=postgresql 

rails new miami-tech-hub --skip-bundle --skip-turbolinks --database=postgresql 
--skip-test-unit

# cd to the folder then modify gem and then
bundle install

# create database
rake db:create


# migrate to create tables
rake db:migrate

# run server
rails s
rails server -p 4000

# Create 

MVC


# This create a model and controller

rails g resource User name:string email:string

rails g resource Task name:string date_completion:date

# First, route, then controller, and finally view.


# put this on the route
get '/' => 'site#home'

# controllers help
rails generate controller --help

# generate a controller for site
rails g controller site

# generate api controller
rails generate controller api/Matches

# destroy controller
rails destroy controller site

# destroy model or controller
rails d model task

# create an action to render the view on the site_controller.rb
 def home
        render 'home'
 end

# create a view inside views folder call home.html.erb
<h1> Welcome to our Homepage </h1>


# this command line create the controller and the action at the same time
rails g controller project home


#----------#

Model

# It is the intermediate between a controller and persistent data

# Models name should be singular but the table ruby created plural
# Model generate project - table created tables


# Create our project model -create two files
rails g model Project

# 1 rails model file where we can put validate and reltionships
app/models/project.rb 

class Project < ActiveRecord::Base
end

# 2 is the migration file contains configurations to apply to our database
db/migrate/20140719003104_create_projects.rb

class CreateProjects < ActiveRecord::Migration
  def change
    create_table :projects do |t|

      t.timestamps
    end
  end
end

# We want to add name and description to our table before we run the migration
class CreateProjects < ActiveRecord::Migration
      def change
        create_table :projects do |t|
            t.string :name
            t.text :description

              t.timestamps
        end
      end
end

# run rake db:migrate to create Projects table -  (rake -T db more db commands)
rake db:migrate

# add colums - check schema
rails g migration add_attributes_to_items 

rails g migration add_attributes_to_players email:string password_digest:string

# migrate again
rake db:migrate


# This is a shorthand to create project model with name and description
rails g model Project name:string address:string


# --------

CRUD

# create, read, update, delete
# the four basis functions of persistent storage, 
# and let us interact with our database to create dynamic webpages


# Rails Console
rails c

# Create
p = Project.new name="IronHack"
p.save

p = Project.create name "IronHack"


# Read 

# One Element
  p = Project.find(1)
  p = Project.first   	 
  p = Project.last	    
  p = Project.find_by name:"IronHack"	



# Multiple Elements
  p = Project.where "name='IronHack'"                                                    
  # (string)
  p = Project.where name:"IronHack"                                                    
  # (hash)
  p = Project.where["name=?", 'IronHack']                                             
  # (string with placeholders)
  p = Project.where(name:'IronHack').where("created_at<?", Date.yesterday)            
  # (concatenation)
  p = Project.where.not("id<?", 4)                                                     
  # (negation)

# Limit the number of retrieved elements
  Project.limit(3).where("name like 'Iron%'")

# Offset
  Project.limit(3).offset(2).where("name like 'Iron%'")

# Order
  Project.limit(10).order("created_at DESC")


# Update
  p.name = "IronHack Updated"
  p.save
  
  p.update_attribute :name, "IronHack rules"
  
  p.updated_attributes name: "IronHack rules" description: "The most awesome bootcamp"


# Delete  
  p.destroy


# ---------

Seed the Database
# Rails have a special way to fill our database to have testing data for development

# add this to the db/seeds.rb file
Project.create name: 'Ironhack', description: 'Ironhack is awesome' 
Project.create name: 'SportsApp', description: 'Tracks my sport sessions' 
Project.create name: 'Recipes', description: 'List of my favourite recipes' 
Project.create name: 'Teacher Assistant rules!', description: 'App to buy icecreams for my TA' 
Project.create name: 'Meetup', description:'App to check latest developers meetups and hackathons'


# run
rake db:seed 

# To check 
rails c

Project.count


# This are the option to start from zero? (delete seed database)
$ rake db:drop db:create db:migrate db:seed

$ rake db:drop db:setup
:setup implies :create, :migrate, and :seed

$ rake db:reset
:reset implies :drop and :setup


# ----------

A request using the DB

# Now we know create models, interact with our database[CRUD], and 
# fill it with testing values(seeds). 
# Let's do our first request using the database


# open routes.rb

AppExample::Aplication.routes.draw do
    get '/' => 'site#home'
    get '/projects' => 'projects#index'    
end


# As we type 'projects#index', 
# we need a project controller 
# with an index action.


# run 
rails g controller projects



# app/controllers/projects_controller.rb (check the last 10 projects)
class ProjectsController < ApplicationController
    def index
        @projects = Project.order(created_at: :desc).limit(10)
    end
end
	    

# create and html called index.html.erb
<ul> 
  <% @projects.each do |project| %> 
    <h3><%= project.name %></h3> 
    <li><%= project.description %></li> 
  <% end %> 
</ul> 

# erb, Embedded RuBy, a templating system that embeds Ruby 


# <% RubyCode %> Executed but not displayed

# <%= RubyCode %> Executed and displayed


# ERB also let us use variables in our html, as @project for example, 
# but to use them, they must be instance variables in our controller

def index
   @projects = # ...
end


# --------

A request with parameters
# How to load a single project? How do we identify it in an URL?

# We use parameters!

 /projects/384 [id attribute]
 /projects/ironhack-introduction [name attribute]
 twitter.com/theironhack [login attribute]

# so
 /projects => Get all the projects [#INDEX Action]
 /projects/484 => Get projects with id=484 [#SHOW Action]


# MVC First, route, then controller, and finally view.


# Route 
AppExample::Aplication.routes.draw do
    get '/' => 'site#home'
    get '/projects' => 'projects#index'    
    get '/projects/:id' => 'projects#show'
end


# Controller
# The params object is where every request with dynamic parameters stores them. 
# It's a HASH, where the key is the name of the parameter and the value is the value of the parameter. 

 #/projects/484 => params[:id] = 482
 #/projects/27 => params[:id] = 27


class ProjectsController < ApplicationController
    def index
        @projects = Project.order(created_at: :desc).limit(10)
    end

    def show
        @project = Project.find params[:id]
    end
end


# View
# Create  views/projects/show.html.erb (remember the naming rules)
<h1><%= @project.name %></h1> 
<p><%= @project.description %></p> 


# -------

Exceptions #(404)

# Exceptions are errors if the project doesn't exist
# Rescuing exceptions - (There are two ways to do it)

# Using rescue
  def show
      @project = Project.find params[:id]
  rescue ActiveRecord::RecordNotFound
      render 'no_projects_found'
  end

  #or


# Avoiding the exception
    def show
        if @project = Project.find_by (id: params[:id])
            render 'home'
        else
            render 'no_projects_found'
    end


# ---------

Views and layouts

# This file will include the html structure with a 
# <%=yield%> that insert our views
layouts/application.html.erb


# It can be ovewritten at control level and at action level

# Controller level
  class ProjectController < ApplicationController
      layout 'admin'

      def index
          @projects = Project.order('created_at DESC').limit(10)
      end

      def show
          @project = Project.find params[:id]
      end
  end

# Action level
  class ProjectController < ApplicationController

      def index
          @projects = Project.order('created_at DESC').limit(10)
          render 'index', layout 'admin'
      end

      def show
          @project = Project.find params[:id]
      end
  end

# Changing template and layout
  class ProjectController < ApplicationController

      def index
          @projects = Project.order('created_at DESC').limit(10)
          render 'projects', layout 'admin'
      end

      def show
          @project = Project.find params[:id]
      end
  end

# ---------

# ActiveRecord Associations

# Why do we need associations between models? 
# Because they make common operations simpler and easier in your code.

# consider a simple Rails application that includes a model for 
# customers and a model for orders. Each customer can have many orders
# With Active Record associations we can tell Rails that there is a connection between the two models


class Customer < ActiveRecord::Base
  has_many :orders, dependent: :destroy
end

class Order < ActiveRecord::Base
  belongs_to :customer
end


# creating a new order for a particular customer is easier
@order = @customer.orders.create(order_date: Time.now)


# Deleting a customer and all of its orders is much easier:
@customer.destroy


# Types of asscociations

# In Rails, an association is a connection between two Active Record models. 
# Rails supports six types of associations:

belongs_to
has_one
has_many
has_many :through
has_one :through
has_and_belongs_to_many


belongs_to association
# sets up a one-to-one connection with another model
# such that each instance of the declaring model "belongs to" one instance of the other model. 
# If your application includes customers and orders, 
# and each order can be assigned to exactly one customer

class Order < ActiveRecord::Base
  belongs_to :customer
end


# The corresponding migration might look like this:
class CreateOrders < ActiveRecord::Migration
  def change
    create_table :customers do |t|
      t.string :name
      t.timestamps
    end

    create_table :orders do |t|
      t.belongs_to :customer
      t.datetime :order_date
      t.timestamps
    end
  end
end


has_one association
# also sets up a one-to-one connection with another model
# but with somewhat different semantics (and consequences). 
# This association indicates that each instance of a model contains one instance of another model. 
# If each supplier in your application has only one account, you'd declare the supplier model like this:

class Supplier < ActiveRecord::Base
  has_one :account
end

# The corresponding migration might look like this:
class CreateSuppliers < ActiveRecord::Migration
  def change
    create_table :suppliers do |t|
      t.string :name
      t.timestamps
    end

    create_table :accounts do |t|
      t.belongs_to :supplier
      t.string :account_number
      t.timestamps
    end
  end
end


has_many association
# indicates a one-to-many connection with another model. 
# You'll often find this association on the "other side" of a belongs_to association. 
# This association indicates that each instance of the model has zero or more instances of another model. 
# In an application containing customers and orders, the customer model could be declared like this:

class Customer < ActiveRecord::Base
  has_many :orders
end

# The corresponding migration might look like this:
class CreateCustomers < ActiveRecord::Migration
  def change
    create_table :customers do |t|
      t.string :name
      t.timestamps
    end

    create_table :orders do |t|
      t.belongs_to :customer
      t.datetime :order_date
      t.timestamps
    end
  end
end


has_many :through association
# Is often used to set up a many-to-many connection with another model. 
# This association indicates that the declaring model can be matched with zero or more instances of another model by proceeding through a third model. 
# For example, consider a medical practice where patients make appointments to see physicians. 

# The relevant association declarations could look like this:

class Physician < ActiveRecord::Base
  has_many :appointments
  has_many :patients, through: :appointments
end

class Appointment < ActiveRecord::Base
  belongs_to :physician
  belongs_to :patient
end

class Patient < ActiveRecord::Base
  has_many :appointments
  has_many :physicians, through: :appointments
end


# The corresponding migration might look like this:
class CreateAppointments < ActiveRecord::Migration
  def change
    create_table :physicians do |t|
      t.string :name
      t.timestamps
    end

    create_table :patients do |t|
      t.string :name
      t.timestamps
    end

    create_table :appointments do |t|
      t.belongs_to :physician
      t.belongs_to :patient
      t.datetime :appointment_date
      t.timestamps
    end
  end
end


# another example with collection of all paragraphs in the document
class Document < ActiveRecord::Base
  has_many :sections
  has_many :paragraphs, through: :sections
end

class Section < ActiveRecord::Base
  belongs_to :document
  has_many :paragraphs
end

class Paragraph < ActiveRecord::Base
  belongs_to :section
end

# With through: :sections specified, Rails will now understand: @document.paragraphs



has_one :through association
# sets up a one-to-one connection with another model. 
# This association indicates that the declaring model can be matched with one instance of another model by proceeding through a third model. 
# If each supplier has one account, and each account is associated with one account history

class Supplier < ActiveRecord::Base
  has_one :account
  has_one :account_history, through: :account
end

class Account < ActiveRecord::Base
  belongs_to :supplier
  has_one :account_history
end

class AccountHistory < ActiveRecord::Base
  belongs_to :account
end


# The corresponding migration might look like this:

class CreateAccountHistories < ActiveRecord::Migration
  def change
    create_table :suppliers do |t|
      t.string :name
      t.timestamps
    end

    create_table :accounts do |t|
      t.belongs_to :supplier
      t.string :account_number
      t.timestamps
    end

    create_table :account_histories do |t|
      t.belongs_to :account
      t.integer :credit_rating
      t.timestamps
    end
  end
end

# Now we're going to implement a new feature to our projects list app that tells us 
# how much time we spent developing each of them. It will be our TimeTracking tool.

# To do this we need to implement a new model, the entries model.

Entry model:

   project_id
   hours
   minutes
   comment
   date

# It will be linked to our Projects model with N-1 relationship. 
# A project could have many entries, but an entry only have a project.


# First generate an entry model
rails g model Entry

# Generate Entry model 
rails g model Entry project:references hours:integer minutes:integer comment:text


# On its migration, add the list of above fields:
# Migration is the field created on the db 28873482749734939

class CreateEntries < ActiveRecord::Migration
  def change
    create_table :entries do |t|
        t.integer :project_id
        t.integer :hours
        t.integer :minutes
        t.text :comments
        t.datetime :date

          t.timestamps
    end
  end
end


# run 
rake db:migrate


# relationship between Projects and Entries will be N-1 relationship
# so our models should look like this:

class Project < ActiveRecord::Base 
  has_many :entries 
end


class Entry < ActiveRecord::Base 
  belongs_to :project 
end

# To check if our code works
rails c

# project = Project.first - project.entries - project.entries.empty?
project = Project.first
Project Load (62.5ms)  SELECT "projects".* FROM "projects" ORDER BY "projects"."id" ASC LIMIT 1
 => #<Project id: 1, name: "Ironhack", description: "Ironhack is awesome", created_at: "2014-07-19 03:05:33", 
updated_at: "2014-07-19 03:05:33">

project.entries
  Entry Load (21.6ms)  SELECT "entries".* FROM "entries" WHERE "entries"."project_id" = $1  [["project_id", 1]]
 => #<ActiveRecord::Associations::CollectionProxy []>


project.entries.empty?
=> true

#-

Create our first entry on rails console

# entry = Entry.new 
# entry.hours = 0
# entry.minutes = 45
# entry.project = project
# entry.save

# project.entries.count

entry = Entry.new
 => #<Entry id: nil, project_id: nil, hours: nil, minutes: nil, comments: nil, date: nil, created_at: nil, updated_at: nil>
entry.hours = 0
 => 0
entry.minutes = 45
 => 45
entry.project = project
 => #<Project id: 1, name: "Ironhack", description: "Ironhack is awesome", created_at: "2014-07-19 03:05:33", updated_at: "2014-07-19 03:05:33">
entry.save
   (1.1ms)  BEGIN
  SQL (55.0ms)  INSERT INTO "entries" ("created_at", "hours", "minutes", "project_id", "updated_at") VALUES ($1, $2, $3, $4, $5) RETURNING "id"  [["created_at", Mon, 21 Jul 2014 00:56:56 UTC +00:00], ["hours", 0], ["minutes", 45], ["project_id", 1], ["updated_at", Mon, 21 Jul 2014 00:56:56 UTC +00:00]]
   (0.6ms)  COMMIT
 => true


#And now, check again:

project.entries.count
(2.2ms)  SELECT COUNT(*) FROM "entries" WHERE "entries"."project_id" = $1  [["project_id", 1]]
 => 1


# Our project-entries association works and now you can select entries from project and vice versa.


# -------

Displaying ActiveRecord Associations
# Imagine you want to display the entries of a project
# How do you identify it in an URL? Using params!


# the use of params let us routing a single project from its [:id]
projects/1

# Now its the same, just adding entries after
projects/1/entries


# Now follow the MVC pattern, it is: Routing-Controller-View

Route
# Open config/routes.rb and add it

AppExample::Aplication.routes.draw do
    get '/' => 'site#home'
    get '/projects' => 'projects#index'    
    get '/projects/:id' => 'projects#show'
    get '/projects/:id/entries' => 'entries#index'
end


Controller
# Why a new controller?

# It’s a good practice to leave controllers the CRUD responsibility of only one resource
# Although the path of request is in the projects resource, 
# it’s representing a nested relation Controller

# create a new controller running
rails g controller entries


# Open app/controllers/entries_controller.rb and first write the code to identify our project
class EntriesController < ApplicationController
    def index
        @project = Project.find params[:id]
        @entries = @project.entries
    end
end


View
# create a new file app/views/entries/index.html.erb and display project with entries
<h1><%= @project.name %></h1> 
<ul> 
  <% @entries.each do |entry| %> 
    <li> 
      <%= entry.hours %> h 
      <%= entry.minutes %> m 
    </li> 
  <% end %> 
</ul> 

# Ironhack
#   0 h 45 m
#   2 h 33 m


---------

Devise

git clone git@github.com:khalifenizar/bbq.git

cd directory

bundle install

rails generate devise:install

# to change devise views
rails g devise:views

rake db:create

rails g devise User

rake db:migrate

rake db:seed

rake db:migrate

# add name attribute
rails g migration add_attributes_to_users name:string