Given the name of an ActiveRecord class, create a schema info block (basically a comment containing information on the columns and their types) and put it at the front of the model and fixture source files.
# File vendor/plugins/ubiquo_core/lib/ubiquo/tasks/annotate_models.rb, line 77
77: def annotate(path, klass, header)
78: info = get_schema_info(klass, header)
79:
80: model_file_name = File.join(path, klass.name.underscore + ".rb")
81: annotate_one_file(model_file_name, info)
82:
83: if Rails.root.join('spec')
84: rspec_file_name = File.join(RSPEC_DIR, klass.name.underscore + "_spec.rb")
85: annotate_one_file(rspec_file_name, info)
86:
87: rspec_fixture = File.join(RSPEC_FIXTURES, klass.table_name + ".yml")
88: annotate_one_file(rspec_fixture, info)
89: end
90:
91: Dir.glob(File.join(FIXTURE_DIR, "**", klass.table_name + ".yml")) do | fixture_file_name |
92: annotate_one_file(fixture_file_name, info)
93: end
94: end
Add a schema block to a file. If the file already contains a schema info block (a comment starting with “Schema as of …”), remove it first.
# File vendor/plugins/ubiquo_core/lib/ubiquo/tasks/annotate_models.rb, line 60
60: def annotate_one_file(file_name, info_block)
61: if File.exist?(file_name)
62: content = File.read(file_name)
63:
64: # Remove old schema info
65: content.sub!(/^# #{PREFIX}.*?\n(#.*\n)*\n/, '')
66:
67: # Write it back
68: File.open(file_name, "w") { |f| f.puts info_block + content }
69: end
70: end
We’re passed a name of things that might be ActiveRecord models. If we can find the class, and if its a subclass of ActiveRecord::Base, then pas it to the associated block
# File vendor/plugins/ubiquo_core/lib/ubiquo/tasks/annotate_models.rb, line 127
127: def do_annotations
128: header = PREFIX.dup
129: version = ActiveRecord::Migrator.current_version rescue 0
130: if version > 0
131: header << "\n# Schema version: #{version}"
132: end
133:
134: get_model_names.each_pair do |path, models|
135: models.each do |model|
136: class_name = model.sub(/\.rb$/,'').camelize
137: begin
138: klass = class_name.split('::').inject(Object){ |klass,part| klass.const_get(part) }
139: if klass < ActiveRecord::Base && !klass.abstract_class?
140: puts "Annotating #{class_name}"
141: annotate(path, klass, header)
142: else
143: puts "Skipping #{class_name}"
144: end
145: rescue Exception => e
146: puts "Unable to annotate #{class_name}: #{e.message}"
147: end
148: end
149:
150: end
151: end
Return a list of the model files to annotate. If we have command line arguments, they’re assumed to be either the underscore or CamelCase versions of model names. Otherwise we take all the model files in the app/models and vendor/plugins/xxxx/app/models directory.
# File vendor/plugins/ubiquo_core/lib/ubiquo/tasks/annotate_models.rb, line 101
101: def get_model_names
102: models = ARGV.dup
103: models.shift
104:
105: if models.empty?
106: Dir.chdir(MODEL_DIR) do
107: models = {MODEL_DIR => Dir["**/*.rb"]}
108: end
109: Dir.chdir(PLUGIN_DIR) do
110: Dir["*"].each do |plugin|
111: if plugin =~ /ubiquo/ && File.exists?(File.join(plugin, MODEL_REL_DIR))
112: Dir.chdir(File.join(plugin, MODEL_REL_DIR)) do
113: models[File.join(PLUGIN_DIR, plugin, MODEL_REL_DIR)] = Dir["**/*.rb"]
114: end
115: end
116: end
117: end
118: end
119: models
120: end
Use the column information in an ActiveRecord class to create a comment block containing a line for each column. The line contains the column name, the type (and length), and any optional attributes
# File vendor/plugins/ubiquo_core/lib/ubiquo/tasks/annotate_models.rb, line 32
32: def get_schema_info(klass, header)
33: info = "# #{header}\n#\n"
34: info << "# Table name: #{klass.table_name}\n#\n"
35:
36: max_size = klass.column_names.collect{|name| name.size}.max + 1
37: klass.columns.each do |col|
38: attrs = []
39: attrs << "default(#{quote(col.default)})" if col.default
40: attrs << "not null" unless col.null
41: attrs << "primary key" if col.name == klass.primary_key
42:
43: col_type = col.type.to_s
44: if col_type == "decimal"
45: col_type << "(#{col.precision}, #{col.scale})"
46: else
47: col_type << "(#{col.limit})" if col.limit
48: end
49: info << sprintf("# %-#{max_size}.#{max_size}s:%-15.15s %s", col.name, col_type, attrs.join(", ")).rstrip
50: info << "\n"
51: end
52:
53: info << "#\n\n"
54: end
Simple quoting for the default column value
# File vendor/plugins/ubiquo_core/lib/ubiquo/tasks/annotate_models.rb, line 15
15: def quote(value)
16: case value
17: when NilClass then "NULL"
18: when TrueClass then "TRUE"
19: when FalseClass then "FALSE"
20: when Float, Fixnum, Bignum then value.to_s
21: # BigDecimals need to be output in a non-normalized form and quoted.
22: when BigDecimal then value.to_s('F')
23: else
24: value.inspect
25: end
26: end
Disabled; run with $DEBUG to generate this.
Generated with the Darkfish Rdoc Generator 1.1.6.