2013-03-08 46 views
3

當我使用像Sequel這樣的ORM時,模型的列由連接的數據庫定義。我如何獲得表格列的文檔?ORM(特別是Sequel)存儲列描述的位置?

(續集,但我認爲原則是AR相同):

我創建一個表,這個遷移:

Sequel.migration do 
    up do 
    create_table(:person) do 
     primary_key :id 
     String :name, :null=>false 
    end 
    end 
    down do 
    drop_table(:person) 
    end 
end 

沒有辦法添加一列描述到數據庫(或者是否有?請不要DB特定的解決方案)。

當我產生我的RDoc文檔對應的模型被定義爲

class Person < Sequel::Model 
end 

,對人的文檔是「空」的,我沒有得到任何列的說明。

我可以一個欄添加一個getter法喜歡這裏:

class Person < Sequel::Model 
    #Name of the person 
    attr_reader :name 
end 

我得到RDoc的描述,但這裏有兩個問題:

  • Person#name永遠是零,連接到數據庫丟失
  • 如果它能工作,這是違反DRY原則。

我可以添加所有列的列表:

#Columns: 
# * name: Name of the person 
# ... 
class Person < Sequel::Model 
end 

但同樣:

  • 這破壞了DRY原則。
  • 我想查看所有可用的列,如getter-methods。

我創建了annotate-gem。但這個寶石刪除了以前的評論,它只增加了技術信息。我無法添加評論。

一些其他模型框架,如datamapper,mongomaper和mongoid直接定義模型中的屬性。 (source)但我不想改變我的ORM。

所以我的問題:什麼是最好的做法來存儲列的描述?

回答

0

到目前爲止沒有答案 - 也許沒有最佳做法。

在此期間,我有一個想法,修改了annotate-gem的想法。

附加的腳本創建一個新的紅寶石文件與模型的文檔。 這個ruby文件可能不會被添加到你的應用程序(它會打破模型),但你可以將它添加到你的rdoc調用。

添加以下代碼ATT以下腳本的末尾:

require 'your_application' #Get your model definitions 

#Define ModelDocumentation with comments for the different fields 
doc = ModelDoc.new(
    #reference with table.field 
    'tables.field1' => 'field one of table tables', 
    #reference with model.field 
    'Table#field2' => "field two of table, referenced by model Table", 
) 
doc.save('my_doc.rb') 

而且現在的腳本:

#encoding: utf-8 
=begin rdoc 
Generate documentation file for Model, 
enriched with data from docdata 
=end 

=begin rdoc 
Get all subclasses from a class. 

Code from http://stackoverflow.com/a/436724/676874 
=end 
class Class 
    def subclasses 
    ObjectSpace.each_object(Class).select { |klass| klass < self } 
    end 
end 


=begin rdoc 
Class to generate a Model-documentation 

==Usage: 

Write a script like this: 

    require 'my_application' 
    require 'model_doc' #this script 

    doc = ModelDoc.new(
    #reference with table.field 
    'tables.field1' => 'field one of table tables', 
    #reference with model.field 
    'Table#field2' => "field two of table, referenced by model Table", 
) 
    doc.save('my_doc.rb') 

my_doc.rb can be included to your library. 
Don't load it to your application! 
Only add it to your documentation with rdoc. 
=end 
class ModelDoc 
=begin rdoc 
Class to generate a Model-documentation. 

Comments are a hash with. 

Keys may be: 
* Modelname#field 
* tablename.field 
=end 
    def initialize(comments = {}) 
    @comments = comments 
    end 

    def save(filename) 
    docfile = File.new(filename, 'w') 

    puts "(Re-)Generate #{docfile.path}" 
    docfile << <<doc 
=begin 
This file is generated by #{__FILE__}, 
based on data from #{Sequel::Model.db.inspect} 

Don't use this code in your implementation! 
This code will overwrite your real model. 


This is only for usage with rdoc. 

=end 
doc 
    Sequel::Model.subclasses.each{|model| 
     docfile << "\n\n#\n" 
     docfile << "#Model for table '#{model.table_name}'\n" 
     docfile << "#\n" 
     docfile << "class #{model} < Sequel::Model\n" 
     model.columns.each{|column| 
     comment = @comments[[model, column].join('#')] 
     comment = @comments[[model.table_name, column].join('.')] unless comment 

     docfile << " #\n #table field #{field_description(model.table_name, column, model.db_schema[column]).join("\n #* ")}\n" 
     if comment 
      docfile << comment.gsub(/^/, " #") 
      docfile << "\n" 
     end 
     #~ docfile << " #\n#accessor generated by Model\n" 
     docfile << " attr_reader #{column.inspect}\n" 
     } 
     docfile << "end\n\n" 
    } 

    docfile.close 
    end 

    def field_description(table_name, column, db_schema) 
    [ 
     "#{table_name}.#{column} (#{db_schema[:type]}/#{db_schema[:db_type]})", 
     db_schema[:primary_key] ? "This is a key field" : nil, 
     "Default is #{db_schema[:default] || 'undefined'}", 
     #fixme: ruby_default 
     "Null-values are #{'not ' unless db_schema[:allow_null]}allowed", 
    ].compact 
    end 
end #ModelDoc 

該腳本僅適用於續集,但我認爲它可以適應AR。