over 4 years ago

Rails 指令介紹

rails 新增前,新增後,請愛用 --help 去問它,server 與 console,

rails --help #Give different outputs inside and outside rails project

(new 時直接開好 mysql 支援,而非用預設的 sqlite )

rails new project1 --database=mysql

Use help to query

rails generate --help
rails generate scaffold --help

gem list rails* See gem list with "rails" prefix

database.yml => yaml格式很重視縮排,不可多打或少打空白

bundle 指令, Gemfile 與 Gemfile.lock 的關係

vi Gemfile
bundle install  #This will collect Gemfile into Gemfile.lock

Gemfile.lock為此一專案的所有gem的版本及其相依性的快照

rake 指令, Rakefile ,使用 -T 來取得可用列表

rakehelp you do something, not in rails only
rake -Tsee all rake commands

資料夾分佈與作用概觀(簡述)

log:記錄,tail 的使用

lib:資源庫

test:測試

public:檔案庫

config:route / initializers / database / environment / locales

app下的:models , controllers , views , helpers , mailers , assets

vender => seldom use
temp => cache, garbage
public => '/' you can see 404.html here
log => log
lib => ruby lib you wrote
db => migrate, schema(資料庫現況快照)
bin => exe (dont touch)
config.ru => rack header?? (don't touch)

mysql的view可以用操作table的方式操作sql

config/initializers => 開啟rails時會跑此資料夾下所有rb檔

啟動執行順序,與其作用(大略)

environment.rb > application.rb(Bundler) > environments/RAILS_ENV.rb > initializers

重大功能介紹(需繪圖+解釋)

route > controller + model > view + helper

session ( request ) 生存範圍(以 #5.a 圖解釋)

migration實作:

change / up / down

與 schema_migrations 版本對應(直接打 mysql 來做說明+圖 #5.b )

部分 magic_column( created_at / updated_at / type 為保留字 )

rails g migration --help
rails g migration add_book
dont use 'change'...use 'up' and 'down' method instead...
in database.yml modify sql password, databse

in add_book...

def up
    create_table :books do |t|
    t.string :isbn
    t.string :title
  end
end
def down
  drop_table :books
end

Create database and do migration
rake db:create construct database
rake db:migrate migrate database

rails g migration add_book_age

def up
    add_column :books, :age, :timestamp
end
def down
    remove_column :books, :age
end

rake db:migrate
rake db:rollback
回到某個版本
rake db:migrate VERSION=xxxx

資料庫所以知道現在的版本,是因為rails會migrate一個schema_migrations
In mysql

mysql -u root -p
use database_name;
show tables;
> schema_migrations
SELECT * FROM schema_migrations;

這裡面放的就是流水號,升板的是取沒有流水號的,從小的開始做,降版是從有的最大的開始往下做
現在的資料庫架構快照在shema.rb

rails g migration add_book_pages

def change
    add_column (:books, :page_count, :integer, {:limit => 2(byte), :defualt=> 0, :unsigned=>true, :null=>false})        #學習一次給詳盡完整
end

rake db:migrate

model 與 relation

callback( before / after系列,自訂 )

基本 relation:belongs_to / has_many / has_one / has_many :through(穿過)(繪圖說明)

rails下的一些methods

rails c
123.days-22.days

rake db:drop db:create
後重建migration(可連寫)

class InitTable < ActiveRecord::Migration
    def change
    create_table :users do |t|
        t.string :name
    end
    create_table :profiles do |t|
        t.integer :user_id, :null => :false # 不可為空
    end
    add_index :profiles, [:user_id], :unigue => :true    # 增加取值效率,並同時限制此:user_id欄位值不可重複,第一參數可為array
    
    # 以下為一對多準備
    create_table :items do |t|
        t.integer :user_id, :null => :false
      t.string :title
    end
    
    # 以下為多對多準備
    create_table :book_owners do |t|
        t.integer :user_id
      t.integer :book_id
      t.integer :level
    end
    create_talbe :books do |t|
        t.string :owner_type    #polymorphic association,解決一個table只能對應一個class的終極解法
      t.integer :owner_id   #polymorphic association,任何東西都可以當它的owner
        t.string :title
    end
    
    # For STI (single table inheritance)
    create_table :animals do |t|
        t.string :type  # type為特殊關鍵字,除STI不能用
      t.string :name
    end
  end
end

建model
user.rb

class User < ActiveRecord::Base
    has_one :profile
  has_many :item    #JC建議進了model後都不要加s
  has_many :book_owner
  has_many :book, :through => :book_owner
end

profile.rb

class Profile > ActiveRecord::Base
    belongs_to :user
end

item.rb

class Item < ActiveRecord::Base
    belongs_to :user
end

book_owener.rb

class BookOwner < ActiveRecord::Base
    belongs_to :user
  belongs_to :book
end

book.rb

class Book < ActiveRecord::Base
    has_many :book_owner
  has_many :user, :through => :book_owner
  belongs_to :owner, :polymorphic => true
end

animal.rb

class Animal < ActiveRecord::Base
end
class Cat < Animal
end
class Dog < Animal
end
class Kitty < Cat
end

開始玩~

rails c
user.create(name: "hello kitty")
User.find(1)    # 有的話會傳回User.id=1的物件,無的話會噴錯
User.find_by(id: 1) #有的話會傳回User.id=1的物件,無的話會傳nil

profile = Profile.create(:user => user)  #物件存入資料庫並同時賦值給profile
profile.user    #belongs_to和has_many生出此method,可抓到user並回傳
User.find(profile.user_id)  #全等於上一個指令,而且如果沒有打belongs_to和has_many,一樣可以用這個指令找到

#用此法可存到全世界任何一個table(model)
book = Book.create(:owner => user, :title => "hihi")
=>#<Book id: 1, owner_type: "User", owner_id: 1, title: "hihi">
book.owner  #會給出class為user的model
=>#<User id: 1, name: "hello kitty">

#多對多,有三個user,三本book,讓第一個user擁有全部的book
User.create(name:"hihi")
User.create(name:"nono")
Book.create(title:"book1")
Book.create(title:"book2")
user = User.find(1)
Book.all.each do |book|
    BookOwner.create(:user => user, :book => book)
end; true   #加true避免印出
user.book
SELECT `books`.* FROM `books` INNER JOIN `book_owners` ON `books.`id` = `book_owners`.`book_id` WHERE `book_owners`.`user_id` = 1
# 自動做有一點點高級的sql, inner join
# 做到多對多就好,不要做多對多對多(用到表示有問題),盡可能用一對多或多對一就好,join會拖慢

#讓第三個user擁有第一本書
user = User.find(3)
BookOwner.create(:user => user, :book => Book.first)
user.book_owner
user.book

#polymorphic可以讓所有ActiveRecord成為其owner
book = Book.find(1)
book.owner
book.owner = book

# STI
Animal.create(name: "animal")
Animal.first
=>#<Animal id: 1, type: nil, name: "animal">   #注意type為nil
Cat.create(name: "cat")
=>#<Cat id: 2, type: "Cat", name: "cat">
Dog.create(name: "dog")
=>#<Dog id: 3, type: "Dog", name: "dog">
Kitty.create(name: "hello")
=>#<Kitty id: 3, type: "Kitty", name: "hello">
Animal.all
Cat.all
Kitty.all

# 自幹所有Relation,就跟ruby蓋code一樣
User.methods.class
=>Array
old_methods = User.methods  #把所有method存起來
class User
    has_many :food  #可以給一個完全不相干的東西
end
new_methods = User.methods #把新的所有method存起來
new_methods - old_methods   #差集,可以看到rails加了哪些新的method進去
#可以看到這些方法都是蓋出來的,rails蓋了很多這些method讓你很好用,換句話說,其實不用它幫你蓋,你也可以自建relation

#舉例
user = User.first
user.profile    #為has_one給的method
Profile.find_by_user_id(user.id)    #不用用他給的relation也可以找到
#不要太仰賴relation!

#ORM可以打純sql,檢查下列的關係,可以隨意調動,rails會自動重組
User.from('profiles AS p').joins('INNER JOIN users AS u ON p.user_id = u.id').where('p.id = 1').order('u.id DESC').limit(1).select('u.*')

sql injection

User.where("name = ?", 'myname')

Pure sql
ActiveRecord::Base.connection.execute('SELECT 1;')

mysql is slow because parsing and latency
reduce the query times

scaffold的全盤介紹與使用( route > controller > action ( callback ) > view )組成原因

path的使用與實作( 可附加“原因”:Ruby : method_missing 的範例)

routes

rake routes

resoureces :sheeps do
    collection do
    get :gogo
  end
  member do 
    get :hihi
  end
end

rake routes
gogo doesnt need id
可自幹命名路由,多個命名路由可用member或collection組合而成,也可以一個一個自幹

action callback( before / after_filter : only , except )

提醒 jquery_ujs:讓傳統 http 支援 RESTful

在http header加入一些東西使得http可以完整支援CRUD

我們來寫個 lib(於 lib/ 下,並用 application.rb 引入)

寄封 mail 吧(遠端場會碰到 smtp 問題,此教學可先略過)

多層 controller 製作(對外頁面 / 使用者後台 / 網站後台)

render
redirect_to :action => 'index'
in sheepscontroller

before_action :test1
...
...
...
private
def test1
    @gogo = 0000
end

in model

before_save :merge_address


private
def merge_address
    self.full_address = "#{self.city}#{self.area}#{self.road_number}"
end

in application template <%= yield :top %>

<% content_for :top do %>
yooo at top
<% end %>

in applicationhelper

def sheep_go(input)
    return input *3
end

in view
<%= sheep_go(99) %>

view 的幹法,好用的 helper
預設為 h( ),解除為 raw( )( 黑白名單機制 [ 版本提醒 ] )
helper 來寫 view 的 methods
partial( 底線開頭檔名 & local var 傳入 )

t.timestamps = 
t.timestamp :updated_at
t.timestampe :created_at
← RailsFun 1st class (Ruby 1) RailsFun 3rd class →
 
comments powered by Disqus