rails内之class关于上加了has_many或者belongs_to后怎么动态增长一些额外的方 ?Ruby类继承、抽象类、类进行混入、代理类实例,ruby实例。

rails版本5.0.0.1

Ruby类继承、抽象类、类进行混入、代理类实例,ruby实例

总一下行事被相遇的切近扩展:

1、类继承:

当多独八九不离十公用很多方的时光可以公用方法有些抽取出来,需要之好像做连锁后续。

例子:

复制代码 代码如下:

class A < ActiveRecord::Base
    def a
        p “it was a “
    end
end

class B<A
end

class C<A
end

B.new.a #=>”it was a “
C.new.a #=>”it was a “

2、抽象类

当多单近乎设延续一个好像时,用第一种植艺术,会遇上一个题目。
(引用一个别人的注释来叙述抽象类的采用吧https://ihower.tw/rails4/activerecord-others.html)

單一表格繼承STI(Single-table inheritance)

什么將物件導向中之繼承概念,對應到關聯式資料庫的設計,是個大哉問。Rails內建了间最簡單的一個解法,只用一個資料表儲存繼承體系中之物件,搭配一個type欄位用來指名這筆資料的類別名稱。

如果開啟STI功能,依照慣例只要来一個欄位叫做type,型態字串即可。假設以下的posts資料表有欄位叫做type,那麼這三個Models實際上就會共用posts一個資料表,當然,還有這兩個子類別也还繼承到父類別的validates_presence_of
:subject:

复制代码 代码如下:

class Post < ActiveRecord::Base 
    validates_presence_of :subject 
end 
 
class GuestPost < Post 
end 
 
class MemberPost < Post 
end 

讓我們進入rails
console實驗看看,Rails會根據你下的類別,自動去設定type欄位:

复制代码 代码如下:

post = GuestPost.create( :subject => “guest”)
post.type # “GuestPost”
post.id # 1
post = MemberPost.create( :subject => “member” )
post.id # 2
post.type # “MemberPost”
GuestPost.last # 1

万分遺憾,也因為這個慣例的關係,你不可知將type這麼名字挪做它因此。
STI最深之問題在於欄位的浪費,如果繼承體系中掺杂的欄位不多,那麼使用STI就會非常的浪費空間。如果生較多的匪同台用底欄位,筆者會建議不要以這個功能,讓個別的類別有自己之資料表。要關閉STI,請父類別加上self.abstract_class
= true

复制代码 代码如下:

class Post < ActiveRecord::Base 
    self.abstract_class = true 
end 
 
class GuestPost < Post 
end 
 
class MemberPost < Post 
end 

這裡的GuestPost和MemberPost就待发协调的Migrations建立guest_posts和member_posts資料表。

而还足以当某某类吃,引入多个因

复制代码 代码如下:

class Dependency<Post 
    require_dependency ‘guestpost’ 
    require_dependency ‘memberpost’ 
end 

3、类进行混入

ruby的好像是单继承的,要贯彻多累的功能要为此mixin(参合模式)的方法,即类拓展混入来兑现。例子:

复制代码 代码如下:

module Extract 
  def self.included(base) 
     base.extend(ClassMethods) 
  end 
  module ClassMethods 
     def a 
        p “it was a ” 
     end 
  end 
end   
 
class A<ActiveRecord::Base 
  include Extract 
end 
 
A.new.a  #=>”it was a” 

4、代理类

当某个功能是比较复杂的,当然写再lib中,作为一个面向函数的法去处理好粗略,也可以用代理类的道实现面向对象的调用。

例子:

复制代码 代码如下:

class A<ActiveRecord::Base
 def generate_schedule
    generator =  Generator::ExcelGenerator.new(self)
    generator.generate_schedule
  end
end

module Generator
  class ExcelGenerator

    attr_reader :excel,:workbook,:a,:worksheet
    attr_accessor :styles

    def initialize(a)
      @excel ||= Axlsx::Package.new
      @workbook ||= @excel.workbook
      @worksheet = @workbook.add_worksheet(:name =>
‘测试大成一个excel文件’)
      @a ||= a
      @styles ||= Hash.new
    end
   
    def generate_schedule
        #excel内容的切切实实定义
    end

  end
end

A.new.generate_schedule
就可以通过代办类ExcelGenerator实现一个A的类实例方法generate_schedule

自然为堪由此include
一个model的主意贯彻互补加类实例方法,有时候为可以混使用。另外利用代理类的利在给多只八九不离十都亟待平等方法的时段可定义共同之有些,举一个作邮件的例子:

复制代码 代码如下:

class A<ActiveRecord::Base
    include SendEmail
end

class B<ActiveRecord::Base
    include SendEmail
end

贯彻引入模块:

复制代码 代码如下:

module SendEmail
    #include this module to class::A and B
    #use like that–  A.first.send_email
    def send_email
      Email.call_email(self)
    end
end

落实代理类:

复制代码 代码如下:

class Email < ActionMailer::Base
  default :from =>
“[email protected]”

  def self.call_email(obj)
     define_method “#{obj.state}” do |obj|
       @obj = obj
       mail(:to => @obj.email, :subject => “XX标题” )
     end
     send(“#{obj.state}”).deliver
    
#因不同目标obj.state得到不同状态下,定义不同方式,然后send派发调用相关对象状态的模板。
  end
    
end

RUBY很灵活当然还有很多旁的法门实现再次多之章程,以后重新逐步总结。

http://www.bkjia.com/ruby/937070.htmlwww.bkjia.comtruehttp://www.bkjia.com/ruby/937070.htmlTechArticleRuby类继承、抽象类、类拓展混入、代理类实例,ruby实例
总结一下办事负相遇的切近扩展: 1、类继承:
当多个像样公用很多道的时可以以…

比如来如下的个别独八九不离十

class User < ActiveRecord::Base
  has_many :posts

end

class Post < ActiveRecord::Base
  belongs_to :user

end

此时段发一个user

user = User.take

然后可以使用user.posts来找到属于user的拥有的posts,同理如果生一个post否足以透过post.user来找到属于她好的user

以此上不禁怀念咨询,这个user.post道是怎来的也罢?

ActiveRecord::Core里有个generated_association_methods方法

def generated_association_methods
  @generated_association_methods ||= begin
    mod = const_set(:GeneratedAssociationMethods, Module.new)
    include mod
    mod
  end
end

当你的rails加载你的class就会实施之点子(比如加载了User
class),并新建一个xxx::GeneratedAssociationMethods的module(加载User
class便创造了属user自己的module:User::GeneratedAssociationMethods),然后通过include方式将xxx::GeneratedAssociationMethods
module加载进入及公的class里。而此module就见面就此来存放在user.posts类似这样的法子。

User class中长的has_many
:posts
尽管当加载class时实行同样多元措施及2个方式:self.define_readers(mixin,
name)
self.define_writers(mixin, name) 

此地的一定量只参数对应之个别吗mixin: User, name: posts**

切实代码如下:

 

    def self.define_readers(mixin, name)
      mixin.class_eval <<-CODE, __FILE__, __LINE__ + 1
        def #{name}(*args)
          association(:#{name}).reader(*args)
        end
      CODE
    end

    def self.define_writers(mixin, name)
      mixin.class_eval <<-CODE, __FILE__, __LINE__ + 1
        def #{name}=(value)
          association(:#{name}).writer(value)
        end
      CODE
    end

当即简单个主意就是是动态地抬高.posts(*args)和.posts=(value) 2只user的实例方法。

class_eval 这个方法会在一个已在的类的光景文中执行一个块,并且会窜是类似的情(《ruby元编程》的说明)。

如下代码会添加.posts(*args)到User::GeneratedAssociationMethods模块里

mixin.class_eval <<-CODE, __FILE__, __LINE__ + 1

        def #{name}(*args)
          association(:#{name}).reader(*args)
        end
      CODE

 

若是依《ruby元编程》的学问的话,可以这样改写

mixin.class_eval do
  define_method(name) do |*args|
    association(name.to_sym).reader(*args)
  end
end

 又或可以一行改写

mixin.class_eval("def #{name}(*args); association(:#{name}).reader(*args); end")

 

相关文章