论坛首页 入门技术论坛

rails 框架里的模型(模型)继承和类的问题

浏览 7027 次
该帖已经被评为新手帖
作者 正文
   发表时间:2008-08-22  
开发中遇到一个问题
ReportRequest是一个表对应一个model:report_request.rb

model report_request.rb 里面
class ReportRequest < ActiveRecord::Base

model TeikiRecountRequest.rb 里面
class TeikiRecountRequest < ActiveRecord::Base

model spot_report_request.rb 里面
class SpotReportRequest < ReportRequest

现在用 ReportRequest.find 方法在数据库里取数据
为什么取出来的对象会是SpotReportRequest 或者 TeikiRecountRequest 的类的对象

请教大家谢谢
   发表时间:2008-08-22  
deferling 写道

model report_request.rb 里面
class ReportRequest < ActiveRecord::Base

model spot_report_request.rb 里面
class SpotReportRequest < ReportRequest


这个继承的model在数据库里 是如何生成数据表的呢?
0 请登录后投票
   发表时间:2008-08-22  
class TeikiRecountRequest < ActiveRecord::Base
  establish_connection "#{ENV['RAILS_ENV']}"
  belongs_to :teiki_report_request
  has_and_belongs_to_many :product_references
 
  alias report_request :teiki_report_request
  alias products :product_references
end


class SpotReportRequest < ReportRequest
  has_and_belongs_to_many :sources,
      :join_table  => 'report_requests_sources',
      :foreign_key => 'report_request_id'
  has_and_belongs_to_many :subjects,
      :join_table  => 'report_requests_subjects',
      :foreign_key => 'report_request_id'

  has_many :topic_keywords, :class_name => "TopicKeyword", :finder_sql =>
      'SELECT DISTINCT tkw.* ' +
      'FROM topic_keywords tkw, report_requests rr ' +
      'WHERE rr.id = #{id} AND rr.topic_keyword_type = tkw.type ' +
      'ORDER BY tkw.name'
  has_many :evaluations
  has_many :job_report_item_generator, :dependent => :destroy
  has_one :report_file

这点够不够
这个继承的model在数据库里 是如何生成数据表的呢?
继承的model在数据库里生成数据表的方法有哪些能请教一下吗
0 请登录后投票
   发表时间:2008-08-22  
rails code in activerecord/lib/activerecord/base.rb:
module ActiveRecord 
  class Base
    class << self
      # Works like find(:all), but requires a complete SQL string. Examples:
      #   Post.find_by_sql "SELECT p.*, c.author FROM posts p, comments c WHERE p.id = c.post_id"
      #   Post.find_by_sql ["SELECT * FROM posts WHERE author = ? AND created > ?", author_id, start_date]
      def find_by_sql(sql)
        connection.select_all(sanitize_sql(sql), "#{name} Load").collect! { |record| instantiate(record) }
      end


# Finder methods must instantiate through this method to work with the
        # single-table inheritance model that makes it possible to create
        # objects of different types from the same table.
        def instantiate(record)
          object =
            if subclass_name = record[inheritance_column]
              if subclass_name.empty?
                # No type given.
                allocate
              else
                # Ignore type if no column is present since it was probably
                # pulled in from a sloppy join.
                unless columns_hash.include?(inheritance_column)
                  allocate

                else
                  begin
                    compute_type(subclass_name).allocate
                  rescue NameError
                    raise SubclassNotFound,
                      "The single-table inheritance mechanism failed to locate the subclass: '#{record[inheritance_column]}'. " +
                      "This error is raised because the column '#{inheritance_column}' is reserved for storing the class in case of inheritance. " +
                      "Please rename this column if you didn't intend it to be used for storing the inheritance class " +
                      "or overwrite #{self.to_s}.inheritance_column to use another column for that information."
                  end
                end
              end
            else
              allocate
            end

          object.instance_variable_set("@attributes", record)
          object
        end

    end
  end
end


YourClass.find_xxx will get one or more record(Hash), call YourClass.allocate to create instance for each, and populate properties to them.
while single table inheritance return corresponding subclass instance.

Q: what's allocate?
A: allocate memory for the newly created instance, without calling constructor(initialize).
  
YourClass.new(*args) 

    equal to
   YourClass.allocate.initialize(*args)


search "instantiate" in activerecord source code, you will find callbacks.rb rewrites it to enable "after_find" and "after_initialize" callbacks, and assocations.rb how to manage join table instantiate.



0 请登录后投票
   发表时间:2008-08-22  

assocations.rb can not be find.
in callbacks.rb

 

    # Is called when the object was instantiated by one of the finders, like Base.find.
    #def after_find() end

    # Is called after the object has been instantiated by a call to Base.new.
    #def after_initialize() end

 so i still don't know why

 can u explain it more detailed?

 thks a lot

0 请登录后投票
   发表时间:2008-08-22  
我看的是rails-1.2.3的源码。
今天比较忙,有时间再跟大家一起学习。

源码大体是,调哪个类的find方法,就生成哪个类的实例。
单表继承的 会生成具体子类的实例。
确认子类名的依据,参考上面代码的17行和29行:如果表中有字段名为type,则该记录的字段值就代表了子类名。
如果不想用type这个名字,可以通过set_inheritance_column定制。但rails把 数据库值和子类名直接对应,没有提供接口让我们定制它们的映射关系(compute_type只是简单的确保不让类名前面的module忽略掉)。

--
切到笔记本,终于可以不用蹩脚的英文了。
0 请登录后投票
   发表时间:2008-08-22  
恩,是有type的,好厉害!
那我想问一下也就是说有一个model A,对应的是table表(映射关系?),
A分别派生了C跟B,table里面的type只要是C那就被认为是C的对象
table里面的type只要是B那就被认为是B的对象,是这么一回事情吗,
如此智能。。。。?


小弟刚刚做ruby on rails 以前是做c++的,源代码暂时还看不懂全部的意思,希望和大家一起进步。


0 请登录后投票
   发表时间:2008-08-22  
deferling 写道
恩,是有type的,好厉害!
那我想问一下也就是说有一个model A,对应的是table表(映射关系?),
A分别派生了C跟B,table里面的type只要是C那就被认为是C的对象
table里面的type只要是B那就被认为是B的对象,是这么一回事情吗,
如此智能。。。。?


小弟刚刚做ruby on rails 以前是做c++的,源代码暂时还看不懂全部的意思,希望和大家一起进步。




nod nod 
0 请登录后投票
   发表时间:2008-08-22  
表是自己建的,万一没有type字段怎么办?
0 请登录后投票
   发表时间:2008-08-22  
A.find_xx就返回A的对象呗,有type字段的,是作为单表继承的。
0 请登录后投票
论坛首页 入门技术版

跳转论坛:
Global site tag (gtag.js) - Google Analytics