[Ruby] Modules
1. Namespace:
Ruby可以像Javascript一样定义全局的functions。这些functions都放在global namespace中。容易和之后的method name冲突。我们可以用module来包括这些functions。
1. module中的方法需要加self:
def self.good_name end
2. 调用的时候先需要引入module文件: if they are not in the same file!!
require 'image_utils'
3. 调用方法:
ImageUtils.preview(image)
Code:
#image_utils.rb module ImageUtils def self.preview(image) end def self.transfer(image, destination) end end #run.rb require 'image_utils' image = user.image ImageUtils.preview(image)
2. Mixin
另一种方法是Mixin, 我们需要做的是把Module在class中include。然后就可以作为class instance的方法调用。
#image_utils.rb module ImageUtils def preview end def transfer(destination) end end #avatar.rb require 'image_utils' #require module file class Image include ImageUtils #including module end #run.rb imge = user.image image.preview
Ancestors:
被加载进去的模块会被加入到Image的ancestor(祖先)中去,可以用:
Image.ancestors
[Image, ImageUtils, Object, Kernel, BasicObject]
Image.include_modules
[ImageUtils, Kernel]
Mixins vs Class inheritance:
Class inheritance:
Ruby中一个class只能继承一个父类,所以如何几个class的behaviors不适合的话最好不要用继承。
Mixing:
以上的情况适用Mixin更加的合适。
另外Mixin同时可以include多个Modules:
Mixin -- Extend:
Mixin还有另外一种形式:extend。
include: 把module的方法用class instance来调用。
extend: 把module的方法当做class methods来调用,可以理解为静态方法。
module Searchable def find_all_from(user) end end class Tweet extend Searchable end Tweet.find_all_from('@GreggPollack')
Object extend a module:
If an object extends a module, the module only avaiable for this object.
Hooks -- Self.included
If we want to both include and extends modules in the same class. It is also possible.
The extended Module should inside the included module.
This is how it looks like:
Also, we can make it better by using Hooks: it will still work as the same.
module ImageUtils def self.included(base) base.extend(classMethodsModule) end module classMethodsModule end end
self.included()
is a special “callback” method that gets automatically called when ever the module is included into something.
ActiveSupport::concern
Read More:
http://www.fakingfantastic.com/2010/09/20/concerning-yourself-with-active-support-concern/
http://api.rubyonrails.org/classes/ActiveSupport/Concern.html
1. ActiveSupport::concern will help to handle the dependencies.
2. So by using ActiveSupport:concern can remove the code:
self.included(base)
base.extend(ClassMethods)
end
3. in inlcuded do block can call the method in in-side Module:
module LibraryUtils extend ActiveSupport::Concern included do load_game_list end def add_game(game) end def remove_game(game) end module ClassMethods def search_by_game_name(name) end def load_game_list end end end
Example:
require 'active_support/concern' module LibraryLoader extend ActiveSupport::Concern module ClassMethods def load_game_list end end end module LibraryUtils extend ActiveSupport::Concern include LibraryLoader included do load_game_list end end class AtariLibrary include LibraryUtils end