趁著還有想法的時候,趕快寫下來。
因為專案的關係,用到了class_eval and super
相信大家對super不陌生,可能常看到吧。

super是什麼呢?
It[Super] calls a method on the parent class with the same name as the method that calls super.
它是當我們想要使用一個類別(class)中的特定方法,但又想保留它父層原有同名方法裡的內容。

1
2
3
4
5
6
7
8
9
10
11
12
13
class A
def hi
p "哈摟"
end
end

class B < A
def hi
super
end
end
B.new.hi
=> "哈摟"

A class裡面定義了一個hi method,B class繼承A class,同時B class裡面也定義了hi,在裡面用了super,當B class使用了hi方法時,也一併把B class裡的方法帶到父層A class裡的hi method裡執行。但上面的範例根本不用這樣做,因為既然是繼承了,它根本不用在定義一個同名方法,直接使用B.new.hi也會是一樣的結果。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
class A
def hi
p "哈摟"
end
end

class B < A
def hi
super
p "大家好"
end
end

B.new.hi
=>
"哈摟"
"大家好"

雖然範例不是很好,但我這次在B class加了”大家好”,B class hi method,就把它帶到父層A class hi method一起執行了。

那這次專案裡踩到的雷,是我們使用了class_eval這個method(可自行google or 我哪天會寫一篇)
我需要從原本的index繼續延伸下去,所以我以為在class_eval裡用super就能繼續在index寫下去。

1
2
3
4
5
6
7
8
xxxController.class_eval do

def index
super
#以下我要執行得代碼
...
end
end

但會噴
NoMethodError (super: no superclass method index)

因為這時xxxController.class_eval就是它自己,所以在延伸index時沒有super可用(除非它的父層有index)。
我用ancestors來看看這個controller的祖先們是誰,看到以下這些,感覺就沒有繼承index難怪會錯。


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
Spree::BaseController,
Spree::ViewContext,
ActionController::Base,
Devise::OmniAuth::UrlHelpers,
Devise::Controllers::UrlHelpers,
Devise::Controllers::Helpers,
Devise::Controllers::StoreLocation,
Devise::Controllers::SignInOut,
Turbolinks::Redirection,
Turbolinks::Controller,
Rollbar::Rails::ControllerMethods,
Rollbar::RequestDataExtractor,
ActiveRecord::Railties::ControllerRuntime,
ActionDispatch::Routing::RouteSet::MountedHelpers,
VersionCake::ControllerAdditions,
ActionController::RespondWith,
CanCan::ControllerAdditions,
ActionController::ParamsWrapper,
ActionController::Instrumentation,
ActionController::Rescue

這時就可以用concern moduleinclude。就可以嘍。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
module Hello
extend ActiveSupport::Concern

def index
super
respond_to do |f|
f.html
f.xlsx do
...
end
end
end
end

---我是分隔線

xxxController.class_eval do
include Hello
...
end

-W