├── acid.md
├── index.md
├── transaction.md
├── dil.md
├── assets
└── cc-by-nc-sa.png
├── migration.md
├── find.md
├── include--extend.md
├── proc--lambda.md
├── .gitignore
├── nplusone.md
├── beer_type.md
├── hash.md
├── xss.md
├── symbolstring.md
├── concat.md
├── redirect.md
├── aorequalb.md
├── csrf.md
├── SUMMARY.md
├── poly.md
├── resouce--resources.md
├── instanceeval--classeval.md
├── person.md
└── README.md
/acid.md:
--------------------------------------------------------------------------------
1 | # 資料庫的 ACID 是什麼
--------------------------------------------------------------------------------
/index.md:
--------------------------------------------------------------------------------
1 | # 資料庫的 INDEX 是什麼
--------------------------------------------------------------------------------
/transaction.md:
--------------------------------------------------------------------------------
1 | # Transaction 是什麼
--------------------------------------------------------------------------------
/dil.md:
--------------------------------------------------------------------------------
1 | # 資料庫的 Database Isolation Level 是什麼
--------------------------------------------------------------------------------
/assets/cc-by-nc-sa.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Unayung/ruby-on-rails-developer-interview-questions/HEAD/assets/cc-by-nc-sa.png
--------------------------------------------------------------------------------
/migration.md:
--------------------------------------------------------------------------------
1 | # 為什麼要有 Migration 檔案
2 |
3 | Migration 檔案的用意在於,讓每一次資料庫修改都能夠被記錄進版本控制。以防止多人協作或開發 / 測試 / 正式環境資料庫 schema 的不一致。
4 |
5 | 而另一個較不為人知的優點是,Migration 背後針對不同類型的資料庫 ( 比方 MySQL vs PostgreSQL ) 可以進行相同的處理,減少開發者考慮在 A DB 和 B DB 進行資料庫操作的語法差異。
--------------------------------------------------------------------------------
/find.md:
--------------------------------------------------------------------------------
1 | # Model.find 和 Model.find_by
2 |
3 | 如果我們有一筆記錄例如
4 | ```ruby
5 | Student id = '4' name = 'foobar'
6 | ```
7 | 如果我們把記錄砍了,那 Student.find(4) 和 Student.find_by(:id => 4) 會發生什麼事?
8 |
9 | ```ruby
10 | Student.find(4).delete
11 |
12 | Student.find(4)
13 | ActiveRecord::RecordNotFound: Couldn't find Student with 'id'=4
14 | # 會產生錯誤
15 |
16 | Student.find_by(:id => 4)
17 | nil
18 | # 只會回傳 nil
19 | ```
--------------------------------------------------------------------------------
/include--extend.md:
--------------------------------------------------------------------------------
1 | # Mixin 中 include 和 Extend 的差別
2 |
3 | ```
4 | 基本
5 | include module 會讓 module 內定義的 method 成為 instance method
6 | extend module 會讓 module 內定義的 method 成為 class method
7 |
8 | 進階
9 | 當 Klazz.extend(Mod) 時, Klazz 會擁有 Mod 的 method, 視為 class method
10 | 當 obj.extend(Mod) 時, obj 會擁有 Mod 的 method, 視為 instance method, 並只有此 obj 可以呼叫.
11 | 其它同 class 生出來的 object 是不能呼叫的.
12 | ```
13 |
14 |
15 |
16 |
--------------------------------------------------------------------------------
/proc--lambda.md:
--------------------------------------------------------------------------------
1 | # Proc 和 lambda 的差別
2 |
3 | 簡單來說 Proc 無視傳入的參數是否與 Proc 內定義的參數個數相同,而 lambda 在參數個數不同時會噴錯
4 |
5 | ```ruby
6 | p = Proc.new{|x,y,z| x+y+z}
7 | p.call(1,2,3)
8 | => 6
9 | p.call(1,2,3,4)
10 | => 6 #第四個參數被無視了
11 |
12 | l = lambda{|x,y,z| x+y+z}
13 | l.call(1,2,3)
14 | => 6
15 | l.call(1,2,3,4)
16 | => ArgumentError: wrong number of arguments (given 4, expected 3) #噴錯了
17 | ```
18 |
19 |
20 |
21 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # Node rules:
2 | ## Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files)
3 | .grunt
4 |
5 | ## Dependency directory
6 | ## Commenting this out is preferred by some people, see
7 | ## https://docs.npmjs.com/misc/faq#should-i-check-my-node_modules-folder-into-git
8 | node_modules
9 |
10 | # Book build output
11 | _book
12 |
13 | # eBook build output
14 | *.epub
15 | *.mobi
16 | *.pdf
--------------------------------------------------------------------------------
/nplusone.md:
--------------------------------------------------------------------------------
1 | # N+1 Query 的處理方向
2 |
3 | Post 有很多 Comments 而有時我們會遇到這種情境
4 |
5 | ```ruby
6 | def users_comments
7 | posts = Post.all
8 | comments = posts.map(&:comments).flatten
9 | @user_comments = comments.select do |comment|
10 | comment.author.username == params[:username]
11 | end
12 | end
13 | ```
14 | 這邊在取出每一個 post 之後,又對每一個 post 去 query 關連的 comments。就造成所謂的 N+1 Query 效能問題
15 |
16 | 解決方法最直觀就是用
17 | ```ruby
18 | posts = Post.includes(comments: [:author]).all
19 | ```
20 | 來取代原本的 posts = Post.all
21 |
22 | 可以使用 [bullet](https://github.com/flyerhzm/bullet) 來偵測 N+1 Query
--------------------------------------------------------------------------------
/beer_type.md:
--------------------------------------------------------------------------------
1 | # 如何指定 /beer/(beer_type) 這種 route
2 |
3 | 假定我們有以下幾種 beer type
4 | ```
5 | IPA
6 | brown_ale
7 | pilsner
8 | lager
9 | lambic
10 | hefeweizen
11 | ```
12 | 如何用同一個 controller action 和設定 routes 來達成 /beer/(beer_type) 顯示不同啤酒的資訊,而不在清單內的則顯示 404
13 |
14 | ```ruby
15 | kinds = %w|IPA brown_ale pilsner lager lambic hefweizen|
16 | resources :beer, only: [:show], constraints: {id: Regexp.new(kinds.join('|'))}
17 |
18 | rails routes
19 |
20 | Prefix Verb URI Pattern Controller#Action
21 | beer GET /beer/:id(.:format) beer#show {:id=>/IPA|brown_ale|pilsner|lager|lambic|hefweizen/}
22 | ```
23 |
--------------------------------------------------------------------------------
/hash.md:
--------------------------------------------------------------------------------
1 | # Hash 和 HashWithIndifferentAccess 的差別
2 |
3 | Hash 在 Ruby 內部實作是用 == 來比對 key. 換句話說在 irb (或純 ruby)的情況下會發生這種情形
4 | ```ruby
5 | irb(main):001:0> h = Hash.new
6 | => {}
7 | irb(main):002:0> h[:v] = '123'
8 | => "123"
9 | irb(main):003:0> h[:v]
10 | => "123"
11 | irb(main):004:0> h['v']
12 | => nil
13 | ```
14 | 而在 ActiveSupport 的 HashWithIndifferentAccess 的幫忙之下,我們可以用 :symbol 或 'string' 來取得 Hash 裡的值
15 | ```ruby
16 | irb(main):001:0> hh = HashWithIndifferentAccess.new
17 | => {}
18 | irb(main):002:0> hh[:v] = '456'
19 | => "456"
20 | irb(main):003:0> hh[:v]
21 | => "456"
22 | irb(main):004:0> hh['v']
23 | => "456"
24 | ```
--------------------------------------------------------------------------------
/xss.md:
--------------------------------------------------------------------------------
1 | # XSS 是什麼
2 | XSS - Cross-Site Scripting 是指在輸入資料的欄位輸入惡意程式碼,使資料外洩或惡作劇跳出視窗,如下
3 |
4 | ```javascript
5 |
6 |
7 |
8 |
9 |
10 | ```
11 |
12 | 要解決這個問題最基本的方法就是用 escapeHTML() 或 h() 處理並顯示使用者產生的文字
13 |
14 | 但有時候我們必須讓使用者可以輸入 HTML 怎麼辦?
15 |
16 | 那就使用 Rails 提供的 sanitize() 方法以及建立白名單來過濾輸入的 HTML
17 |
18 | 詳細使用參照 [here](http://api.rubyonrails.org/classes/ActionView/Helpers/SanitizeHelper.html#method-i-sanitize)
--------------------------------------------------------------------------------
/symbolstring.md:
--------------------------------------------------------------------------------
1 | # Symbol 和 String 的不同
2 |
3 | Symbol 是 immutable 物件而 String 是 mutable 物件。而每次呼叫 Symbol 時可由觀察 object_id 得知,是同一個 object,反觀 string 則是不同一個物件。
4 |
5 | 適當使用 Symbol 可以避免 Server 端的記憶體問題,且在物件的比較上來說,使用 Symbol 比較快速。
6 | ```ruby
7 | irb(main):026:0> :a
8 | => :a
9 | irb(main):027:0> :a.object_id
10 | => 722588
11 | irb(main):028:0> :a.object_id
12 | => 722588
13 | irb(main):029:0> :a.object_id
14 | => 722588
15 | irb(main):030:0> 'a'
16 | => "a"
17 | irb(main):031:0> 'a'.object_id
18 | => 70321956133380
19 | irb(main):032:0> 'a'.object_id
20 | => 70321987377060
21 | irb(main):033:0> 'a'.object_id
22 | => 70321987372240
23 | irb(main):041:0> 'a'.equal?('a')
24 | => false
25 | irb(main):042:0> :a.equal?(:a)
26 | => true
27 | ```
--------------------------------------------------------------------------------
/concat.md:
--------------------------------------------------------------------------------
1 | # 請解釋對字串使用 += 和使用 concat 方法有何差異
2 |
3 | 對字串使用 += 方法,例如 a += b。事實上是再產生了一個 a 物件並把 a+b 的結果丟進新的 a 物件。我們可以觀察 object_id 來得知這樣的行為。
4 |
5 | ```ruby
6 | irb(main):041:0> x = "hello"
7 | => "hello"
8 | irb(main):042:0> x.object_id
9 | => 70232477009280
10 | irb(main):043:0> x += " world"
11 | => "hello world"
12 | irb(main):044:0> x
13 | => "hello world"
14 | irb(main):045:0> x.object_id
15 | => 70232475548960
16 | ```
17 |
18 | 而 concat 則是對同一個物件進行操作
19 |
20 | ```ruby
21 | irb(main):049:0> x = "hello"
22 | => "hello"
23 | irb(main):050:0> x.object_id
24 | => 70232488144300
25 | irb(main):051:0> x.concat " world"
26 | => "hello world"
27 | irb(main):052:0> x
28 | => "hello world"
29 | irb(main):053:0> x.object_id
30 | => 70232488144300
31 | ```
--------------------------------------------------------------------------------
/redirect.md:
--------------------------------------------------------------------------------
1 | # redirect_to 和 render 有什麼不同
2 |
3 | redirect_to 可以視為跳轉到別頁。包括跳轉到別的網站也是用 redirect_to 。因此使用 redirect_to 會造成 URL 的改變。
4 |
5 | render 則是用於告訴 Rails "我要顯示什麼樣的畫面 / 資料在 browser 上" 而事實上 Rails 本身在每一個 controller action 都自動進行尋找並 render 對應的 template。所以 render 不會造成 URL 的改變。
6 |
7 | 額外一提的是 render 會把之前在 form 裡填寫的內容一併顯示。對於註冊流程或是使用者體驗上是相當方便的。
8 |
9 | 以實際例子來看
10 |
11 | ```ruby
12 | def create
13 | @user=User.new(params[:user])
14 | if @user.save
15 | redirect_to :index
16 | else
17 | render :new #you should render to fill fields after error message
18 | end
19 | end
20 |
21 | 如果 @user.save 成功了,就跳轉到 index action。
22 | 如果 @user.save 失敗了,就 render "new" 這個 action 的 template
23 | ( 也就是 create 的上一步,此時可注意 URL 還是會在 create 的 path )
24 | ```
--------------------------------------------------------------------------------
/aorequalb.md:
--------------------------------------------------------------------------------
1 | # 請解釋這個語法 a ||= b
2 |
3 | 當 a 有值 ( 非 nil 非 false ) 時, a 保持原值
4 |
5 | 當 a 為 nil / false 時, a = b
6 |
7 | 我們看以下的範例
8 |
9 | ```ruby
10 | irb(main):024:0> a = nil
11 | => nil
12 | irb(main):025:0> b = 10
13 | => 10
14 | irb(main):026:0> a ||= b
15 | => 10
16 | irb(main):027:0> a
17 | => 10
18 |
19 | irb(main):028:0> a = false
20 | => false
21 | irb(main):029:0> b = 20
22 | => 20
23 | irb(main):030:0> a ||= b
24 | => 20
25 | irb(main):031:0> a
26 | => 20
27 |
28 | irb(main):032:0> a = ""
29 | => ""
30 | irb(main):033:0> b = "abc"
31 | => "abc"
32 | irb(main):034:0> a ||= b
33 | => ""
34 | irb(main):035:0> a
35 | => ""
36 |
37 | irb(main):037:0> a = 689
38 | => 689
39 | irb(main):038:0> b = 633
40 | => 633
41 | irb(main):039:0> a ||= b
42 | => 689
43 | irb(main):040:0> a
44 | => 689
45 | ```
--------------------------------------------------------------------------------
/csrf.md:
--------------------------------------------------------------------------------
1 | # CSRF 是什麼
2 |
3 | CSRF - Cross-Site Request Forgery 是指攻擊者惡意在可插入程式片段的地方放入如
4 |
5 | ```html
6 |
7 | ```
8 |
9 | 的程式碼,等到擁有管理權限的人看到這張假圖時,送出這個 request 給 server 然後刪除所有 post
10 |
11 | 如何防範 CSRF 攻擊呢? 首先從 routes 的角度來設計。
12 |
13 | > 所有讀取、查詢性質操作,都應該用 _GET_,而會修改或刪除到資料的,則要用 _POST_ 、 _PATCH/PUT_ 或 _DELETE_ 。這樣的設計,就可以防止上面的惡意程式碼了,因為在瀏覽器中必須用表單 _form_ 才能送出 _POST_ 請求。 from [Ruby on Rails實戰聖經](https://ihower.tw/rails/security.html#sec1)
14 |
15 | 而從 Rails 架構本身的防範來說,我們可以使用 protect_from_forgery 這個 method 來阻擋攻擊
16 |
17 | ```ruby
18 | class ApplicationController < ActionController::Base
19 | protect_from_forgery with: :exception
20 | end
21 | ```
22 | 這個 method 會在所有表單自動插入一組 token 而在每次送 _POST_ 的時候去和 session 裡的 token 比對是否正確,如果不正確就阻止 _POST_ 動作的發生。而 Layout中也有一段 <%= csrf_meta_tags %> 是給 JavaScript 讀取 token 用的。
23 |
24 |
--------------------------------------------------------------------------------
/SUMMARY.md:
--------------------------------------------------------------------------------
1 | # Summary
2 |
3 | * [Introduction](README.md)
4 | * [Symbol 和 String](symbolstring.md)
5 | * [proc 和 lambda](proc--lambda.md)
6 | * [include 和 extend](include--extend.md)
7 | * [instance\_eval 和 class\_eval](instanceeval--classeval.md)
8 | * [resouce 和 resources](resouce--resources.md)
9 | * [Hash 和 HashWithIndifferentAccess](hash.md)
10 | * [Model.find 和 Model.find_by](find.md)
11 | * [redirect_to 和 render](redirect.md)
12 | * [什麼是 Polymorphic Association](poly.md)
13 | * [N+1 Query](nplusone.md)
14 | * [為什麼要有 Migration 檔案](migration.md)
15 | * [Transaction 是什麼](transaction.md)
16 | * [如何用單一 action 套用 /beer/(beer\_type) 這種 route](beer_type.md)
17 | * [如何讓 Person model 可以指定另一個 person 為 parent](person.md)
18 | * [請解釋這個語法 a ||= b](aorequalb.md)
19 | * [請解釋對字串使用 += 和使用 concat 方法有何差異](concat.md)
20 | * [CSRF 是什麼](csrf.md)
21 | * [XSS 是什麼](xss.md)
22 | * [資料庫的 INDEX 是什麼](index.md)
23 | * [資料庫的 ACID 是什麼](acid.md)
24 | * [資料庫的 Database Isolation Level 是什麼](dil.md)
25 | * [資料庫的 Database Isolation Level 是什麼](dil.md)
--------------------------------------------------------------------------------
/poly.md:
--------------------------------------------------------------------------------
1 | # 什麼是 Polymorphic Association 多型關聯
2 |
3 | 使用場景例如,你的網站上有圖片 (Image) 和影片 (Video) 兩種 model,而 PM 告訴你,他想要讓這兩種 model 都可以留言 (Comment)
4 |
5 | 如果不使用 Polymorphic 的話,那你可能會產生 ImageComment 和 VideoComment 兩種 model 。而這兩者的行為又完全相同,這就違反了 DRY 的原則。
6 |
7 | 我們可以使用 Polymorphic Association 來解決這樣的需求
8 |
9 | ```ruby
10 | rails g model comment content:text commentable_id:integer commentable_type
11 |
12 | 會產生這樣的 migration 檔案
13 |
14 | class CreateComments < ActiveRecord::Migration
15 | def change
16 | create_table :comments do |t|
17 | t.text :content
18 | t.integer :commentable_id
19 | t.string :commentable_type
20 |
21 | t.timestamps
22 | end
23 | end
24 | end
25 |
26 | 或是可以寫成這樣
27 |
28 | class CreateComments < ActiveRecord::Migration
29 | def change
30 | create_table :comments do |t|
31 | t.text :content
32 | t.belongs_to :commentable, :polymorphic => true
33 |
34 | t.timestamps
35 | end
36 | end
37 | end
38 |
39 | 中間 t.belongs_to :commentable, :polymorphic => true
40 | 則會自動產生 commentable_id 和 commentable_type 這兩個欄位
41 | ```
42 |
43 | 而在 Model 的部份,只要這樣設定即可
44 |
45 | ```ruby
46 | class Comment < ActiveRecord::Base
47 | belongs_to :commentable, :polymorphic => true
48 | end
49 |
50 | class Video < ActiveRecord::Base
51 | has_many :comments, :as => :commentable
52 | end
53 |
54 | class Image < ActiveRecord::Base
55 | has_many :comments, :as => :commentable
56 | end
57 | ```
58 |
59 | 這樣一來就算之後還有第三、四、N 種 Model 可以被 Comment。也只要加入上述的 relation 就可以搞定了。
--------------------------------------------------------------------------------
/resouce--resources.md:
--------------------------------------------------------------------------------
1 | # resource 和 resources 的差別
2 |
3 | 從字面上來看 resouce 是單數而 resources 是複數,也就是說如果你想要列出某種類 model 的列表. 你應該選用 resources 來符合 rails 的 convention. 而兩者預設產生出來的 routes 差別在於有沒有 index action 和對應的 path / url
4 |
5 | ```ruby
6 | # 假設每個使用者只有一組 profile 可以設定
7 |
8 | resource :profile # in routes.rb
9 |
10 | rails routes
11 |
12 | new_profile GET /profile/new(.:format) profiles#new
13 | edit_profile GET /profile/edit(.:format) profiles#edit
14 | profile GET /profile(.:format) profiles#show
15 | PATCH /profile(.:format) profiles#update
16 | PUT /profile(.:format) profiles#update
17 | DELETE /profile(.:format) profiles#destroy
18 | POST /profile(.:format) profiles#create
19 |
20 | # 可以發現並沒有建立 index action 的 route
21 | ```
22 | ```ruby
23 | # 假設每個使用者可以設定多組 profile
24 |
25 | resources :profiles # in routes.rb
26 |
27 | rails routes
28 |
29 | profiles GET /profiles(.:format) profiles#index
30 | new_profile GET /profiles/new(.:format) profiles#new
31 | edit_profile GET /profiles/:id/edit(.:format) profiles#edit
32 | profile GET /profiles/:id(.:format) profiles#show
33 | PATCH /profiles/:id(.:format) profiles#update
34 | PUT /profiles/:id(.:format) profiles#update
35 | DELETE /profiles/:id(.:format) profiles#destroy
36 | POST /profiles(.:format) profiles#create
37 |
38 | # 這個情況下就有 profiles 列表的存在,且針對某一 profile 的操作需要 pass id 以找到特定記錄
39 | ```
--------------------------------------------------------------------------------
/instanceeval--classeval.md:
--------------------------------------------------------------------------------
1 | # instance\_eval 和 class\_eval 的差別
2 |
3 | ```
4 | 先講結論
5 | instance_eval 可以定義 instance method 但不能被同 class 的其它 instance 呼叫,
6 | 也可以定義 class method 因為 class 也是 Class 的一個 instance
7 |
8 | class_eval 可以定義 instance method 並且可以被同 class 的其它物件呼叫
9 | 是不是聽起來有點玄妙?
10 | 我們來看底下的例子
11 | ```
12 |
13 | ```ruby
14 | class MyClass
15 | def initialize(num)
16 | @num = num
17 | end
18 | end
19 |
20 | a = MyClass.new(1)
21 | b = MyClass.new(2)
22 | ```
23 |
24 | 當我們想要檢視 a,b 物件內的 num 值時,我們會用 a.num 來試試看
25 |
26 | ```ruby
27 | a.num
28 | => NoMethodError: undefined method `num' for #
29 | ```
30 |
31 | 噴錯了,因為我們沒有 def num 這個 method
32 | 那我們用 instance\_eval 來試試看吧
33 |
34 | ```ruby
35 | a.instance_eval do
36 | def num
37 | puts @num
38 | end
39 | end
40 |
41 | a.num
42 | => 1
43 | b.num
44 | => NoMethodError: undefined method `num' for #
45 | ```
46 |
47 | 又噴錯了,因為我們只有針對 a 這個物件去寫 instance\_eval, 但 b 是看不到 num 這個 method
48 |
49 | 那如果我們針對 MyClass 用 instance\_eval 會發生什麼事呢?
50 |
51 | ```ruby
52 | MyClass.instance_eval do
53 | def num
54 | @num
55 | end
56 | end
57 |
58 | b.num
59 | => NoMethodError: undefined method `num' for #
60 | ```
61 |
62 | 又噴錯了,因為我們是對 MyClass 這個 Class 的 instance 去寫 instance\_eval
63 | 上面的 code 執行起來是這樣
64 |
65 | ```ruby
66 | MyClass.num
67 | => nil # 因為我們沒有給值丟進 num 裡就直接 call num 這個變數. 自然是 nil
68 | ```
69 |
70 | 那麼正確讓 a.num / b.num 都可以回傳正確值的作法是什麼呢?
71 |
72 | ```ruby
73 | MyClass.class_eval do
74 | def num
75 | @num
76 | end
77 | end
78 |
79 | a.num
80 | => 1
81 | b.num
82 | => 2
83 | ```
84 |
85 | 事實上我們可以把上面 class\_eval 的例子視為平常在寫 instance method 的寫法,如下面所示
86 |
87 | ```ruby
88 | class MyClass
89 | def num
90 | @num
91 | end
92 | end
93 | ```
94 |
95 |
96 |
97 |
--------------------------------------------------------------------------------
/person.md:
--------------------------------------------------------------------------------
1 | # 如何讓 Person model 可以指定另一個 person 為 parent
2 |
3 | ```ruby
4 | irb(main):001:0> john = Person.create(name: "John")
5 | irb(main):002:0> jim = Person.create(name: "Jim", parent: john)
6 | irb(main):003:0> bob = Person.create(name: "Bob", parent: john)
7 | irb(main):004:0> john.children.map(&:name)
8 | => ["Jim", "Bob"]
9 | ```
10 | 如何達成這樣的關連呢?首先我們要知道 association 的 target class 是可以另外指定的,而外鍵的欄位也是可以自己定義
11 |
12 | ```ruby
13 | rails g migration add_parent_id_to_person
14 | # 先增加一個整數欄位 parent_id 到 person table
15 |
16 | class Person < ActiveRecord::Base
17 | belongs_to :parent, class: Person
18 | has_many :children, class: Person, foreign_key: :parent_id
19 | end
20 | ```
21 |
22 | 這個問題還可以延伸下去,如果我想達成這樣的效果,需要怎麼實作呢?
23 | ```ruby
24 | irb(main):001:0> sally = Person.create(name: "Sally")
25 | irb(main):002:0> sue = Person.create(name: "Sue", parent: sally)
26 | irb(main):003:0> kate = Person.create(name: "Kate", parent: sally)
27 | irb(main):004:0> lisa = Person.create(name: "Lisa", parent: sue)
28 | irb(main):005:0> robin = Person.create(name: "Robin", parent: kate)
29 | irb(main):006:0> donna = Person.create(name: "Donna", parent: kate)
30 | irb(main):007:0> sally.grandchildren.map(&:name)
31 | => ["Lisa", "Robin", "Donna"]
32 | ```
33 |
34 | 這邊考的是 has_many ... :through => 這個概念
35 |
36 | ```ruby
37 | class Person < ActiveRecord::Base
38 | belongs_to :parent, class: Person
39 | has_many :children, class: Person, foreign_key: :parent_id
40 | has_many :grandchildren, class: Person, through: :children, source: :children
41 | end
42 | ```
43 |
44 | 這個範例解釋得很好
45 | ```ruby
46 | Say you have these models:
47 |
48 | Car
49 | Engine
50 | Piston
51 |
52 | A car has_one :engine
53 | An engine belongs_to :car
54 | An engine has_many :pistons
55 | Piston belongs_to :engine
56 |
57 | A car has_many :pistons, through: :engine
58 | Piston has_one :car, through: :engine
59 |
60 | Essentially you are delegating a model relationship to another
61 | model, so instead of having to call car.engine.pistons, you can
62 | just do car.pistons
63 | ```
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # 常見的 Ruby on Rails 工程師面試問題
2 |
3 | 收錄一些業界常見/常問的面試問題和翻譯解答
4 |
5 | 解答不見得完整和精確,但在面試的環境下回答應該是足夠的
6 |
7 | 有需要改正或有什麼要新增 / 補充的地方也請大家發 PR
8 |
9 | [開始閱讀](https://unayung.gitbooks.io/ruby-on-rails-developer-interview-questions/content/)
10 |
11 | source 在 [Github](https://github.com/Unayung/ruby-on-rails-developer-interview-questions)
12 |
13 | ---
14 |
15 | 目錄
16 |
17 | * [Introduction](README.md)
18 | * [Symbol 和 String](symbolstring.md)
19 | * [proc 和 lambda](proc--lambda.md)
20 | * [include 和 extend](include--extend.md)
21 | * [instance\_eval 和 class\_eval](instanceeval--classeval.md)
22 | * [resouce 和 resources](resouce--resources.md)
23 | * [Hash 和 HashWithIndifferentAccess](hash.md)
24 | * [Model.find 和 Model.find_by](find.md)
25 | * [redirect_to 和 render](redirect.md)
26 | * [什麼是 Polymorphic Association](poly.md)
27 | * [N+1 Query](nplusone.md)
28 | * [為什麼要有 Migration 檔案](migration.md)
29 | * [Transaction 是什麼](transaction.md)
30 | * [如何用單一 action 套用 /beer/(beer\_type) 這種 route](beer_type.md)
31 | * [如何讓 Person model 可以指定另一個 person 為 parent](person.md)
32 | * [請解釋這個語法 a ||= b](aorequalb.md)
33 | * [請解釋對字串使用 += 和使用 concat 方法有何差異](concat.md)
34 | * [CSRF 是什麼](csrf.md)
35 | * [XSS 是什麼](xss.md)
36 | * [資料庫的 INDEX 是什麼](index.md)
37 | * [資料庫的 ACID 是什麼](acid.md)
38 | * [資料庫的 Database Isolation Level 是什麼](dil.md)
39 |
40 | 參考資料
41 |
42 | * [Ruby on Rails 實戰聖經](https://ihower.tw/rails/)
43 | * [8 Essential Ruby on Rails Interview Questions](https://www.toptal.com/ruby-on-rails/interview-questions)
44 | * [11 Ruby on Rails Interview Practice Questions](https://www.codementor.io/ruby-on-rails/tutorial/ruby-on-rails-interview-questions)
45 | * [15 Questions to Ask During a Ruby Interview](https://gist.github.com/ryansobol/5252653)
46 |
47 | 版權許可
48 |
49 | 採用創用CC授權4.0 "姓名標示─非商業性─相同方式分享(BY-NC-SA)" 授權。
50 |
51 | 
52 |
53 | 本授權條款允許使用者重製、散布、傳輸以及修改著作,但不得為商業目的之使用。若使用者修改該著作時,僅得依本授權條款或與本授權條款類似者來散布該衍生作品。使用時必須按照著作人指定的方式表彰其姓名。
54 |
55 | 詳細資訊請參考 [CC BY-NC-SA 4.0](https://creativecommons.org/licenses/by-nc-sa/4.0/)。
56 |
57 |
--------------------------------------------------------------------------------