Ruby on Rails | Screencasts | Download | Documentation | Weblog | Community | Source

Ticket #10424: documenting_cattr_accessors.rb

File documenting_cattr_accessors.rb, 9.8 kB (added by toolmantim, 2 years ago)
Line 
1 # Currently a whole bunch of Rails config options aren't documented. This is due to RDoc not picking up comments on cattr_accessor. Here's a bit of a look at the options.
2 #
3 # Run rdoc over it to read the docs and see the results of the different options.
4 #
5 # Tim Lucas <t.lucas@toolmantim.com>
6
7 require 'rubygems'
8 gem 'activesupport'
9 require 'activesupport'
10
11 class Class
12   # Defines a class attribute accessor method and sets the class attribute's
13   # default by calling the class attribute writer method, such as <tt>self.option=</tt>.
14   #
15   # The class attribute writer method must be defined before calling this method.
16   #
17   # Without this convience method you'd typically do:
18   #   class Mailer
19   #     # Sets whether to perform deliveries of outgoing mail
20   #     def self.perform_deliveries=(perform_deliveries)
21   #       @@perform_deliveries = perform_deliveries
22   #     end
23   #     def self.perform_deliveries
24   #       @@perform_deliveries
25   #     end
26   #     @@perform_deliveries = true
27   #   end
28   #
29   # The equivalent to the above code but using cattr_reader_with_default is:
30   #   class Mailer
31   #     # Sets whether to perform deliveries of outgoing mail
32   #     def self.perform_deliveries=(perform_deliveries)
33   #       @@perform_deliveries = perform_deliveries
34   #     end
35   #     cattr_reader_with_default :perform_deliveries, true
36   #   end
37   def cattr_reader_with_default(sym, default)
38     cattr_reader sym
39     class_eval(<<-EOS, __FILE__, __LINE__)
40       self.#{sym} = default
41     EOS
42   end
43 end
44
45 # Currently a whole bunch of Rails config options aren't documented. This is due to RDoc not picking up comments on <tt>cattr_accessor</tt>.
46 #
47 # Some common examples might be <tt>ActionView::Base.field_error_proc</tt> and <tt>ActiveRecord::Base.colorize_logging</tt> which currently are only documented via the source, blogs and google.
48 #
49 # Possible solutions:
50 # * Move the comment from the <tt>cattr_accessor</tt> into an rdoc "Configuration" section on Base
51 #   * Lose the connection between code+comment (bad for maintenance)
52 #   * The cattr_accessor may be defined in any extension module so documentation is very far from its source code
53 #   * This is the approach for <tt>ActionMailer</tt> but it works because its mostly in the one file
54 # * Copy + paste the comment from the <tt>cattr_accessor</tt> into an rdoc "Configuration" section on Base
55 #   * Copy + paste is bad
56 #   * The cattr_accessor may be defined in any extension module so documentation is very far from its source code
57 # * Patch RDoc to pick up cattr_accessor comments
58 # * Use class/module writer and reader methods and manually set default
59 #   * RDoc documents both config option readers and writers
60 #   * Bloaty
61 #   * e.g. ClassWriterAndReaderMethods
62 # * Use class/module writer and some convenenience method
63 #   * RDoc only documents config option writers
64 #   * e.g. ClassWriterAndAttrConvenienceMethod
65 # * Leave them as is (i.e. using an RDoc above <tt>cattr_accessor</tt>)
66 #   * Everything stays undocumented );
67 #   * e.g. AttributeAccessors
68 #
69 # Considering most config options are now using <tt>instance_writer => false</tt> its probably a good time for a refactoring
70 module ActiveSupportConfigDocsDemo
71   # The current way of documenting config options.
72   #
73   # The ultimate in minimalism, though we all have to suffer for it.
74   class AttributeAccessors
75     # Accessor for the prefix type that will be prepended to every primary key column name. The options are :table_name and
76     # :table_name_with_underscore. If the first is specified, the Product class will look for "productid" instead of "id" as
77     # the primary column. If the latter is specified, the Product class will look for "product_id" instead of "id". Remember
78     # that this is a global setting for all Active Records.
79     cattr_accessor :primary_key_prefix_type, :instance_writer => false
80     @@primary_key_prefix_type = nil
81  
82     # Accessor for the name of the prefix string to prepend to every table name. So if set to "basecamp_", all
83     # table names will be named like "basecamp_projects", "basecamp_people", etc. This is a convenient way of creating a namespace
84     # for tables in a shared database. By default, the prefix is the empty string.
85     cattr_accessor :table_name_prefix, :instance_writer => false
86     @@table_name_prefix = ""
87  
88     # Works like +table_name_prefix+, but appends instead of prepends (set to "_basecamp" gives "projects_basecamp",
89     # "people_basecamp"). By default, the suffix is the empty string.
90     cattr_accessor :table_name_suffix, :instance_writer => false
91     @@table_name_suffix = ""
92  
93     # Indicates whether table names should be the pluralized versions of the corresponding class names.
94     # If true, the default table name for a +Product+ class will be +products+. If false, it would just be +product+.
95     # See table_name for the full rules on table/class naming. This is true, by default.
96     cattr_accessor :pluralize_table_names, :instance_writer => false
97     @@pluralize_table_names = true
98   end
99
100   # A straight ruby way of specifying config options.
101   #
102   # It's pretty darn bloaty, though it has the advantage of both writer and reader methods getting picked up by RDoc.
103   class ClassWriterAndReaderMethods
104     class << self
105       # Accessor for the prefix type that will be prepended to every primary key column name. The options are :table_name and
106       # :table_name_with_underscore. If the first is specified, the Product class will look for "productid" instead of "id" as
107       # the primary column. If the latter is specified, the Product class will look for "product_id" instead of "id". Remember
108       # that this is a global setting for all Active Records.
109       def primary_key_prefix_type=(primary_key_prefix_type)
110         @@primary_key_prefix_type = primary_key_prefix_type
111       end
112       def primary_key_prefix_type
113         @@primary_key_prefix_type
114       end
115       @@primary_key_prefix_type = nil
116
117       # Accessor for the name of the prefix string to prepend to every table name. So if set to "basecamp_", all
118       # table names will be named like "basecamp_projects", "basecamp_people", etc. This is a convenient way of creating a namespace
119       # for tables in a shared database. By default, the prefix is the empty string.
120       def table_name_prefix=(table_name_prefix)
121         @@table_name_prefix = table_name_prefix
122       end
123       def table_name_prefix
124         @@table_name_prefix
125       end
126       @@table_name_prefix = ""
127
128       # Works like +table_name_prefix+, but appends instead of prepends (set to "_basecamp" gives "projects_basecamp",
129       # "people_basecamp"). By default, the suffix is the empty string.
130       def table_name_suffix=(table_name_suffix)
131         @@table_name_suffix = table_name_suffix
132       end
133       def table_name_suffix
134         @@table_name_suffix
135       end
136       @@table_name_suffix = ""
137
138       # Indicates whether table names should be the pluralized versions of the corresponding class names.
139       # If true, the default table name for a +Product+ class will be +products+. If false, it would just be +product+.
140       # See table_name for the full rules on table/class naming. This is true, by default.
141       def pluralize_table_names=(pluralize_table_names)
142         @@pluralize_table_names = pluralize_table_names
143       end
144       def pluralize_table_names
145         @@pluralize_table_names
146       end
147       @@pluralize_table_names = true
148     end
149   end
150
151   # Using standard Ruby to declaring option writers and Class.cattr_reader_with_default to specify the reader method and default value.
152   #
153   # At least 5 times sexier than the ClassWriterAndReaderMethods approach.
154   class ClassWriterAndAttrConvenienceMethod
155     # Accessor for the prefix type that will be prepended to every primary key column name. The options are :table_name and
156     # :table_name_with_underscore. If the first is specified, the Product class will look for "productid" instead of "id" as
157     # the primary column. If the latter is specified, the Product class will look for "product_id" instead of "id". Remember
158     # that this is a global setting for all Active Records.
159     def self.primary_key_prefix_type=(primary_key_prefix_type)
160       @@primary_key_prefix_type = primary_key_prefix_type
161     end
162     cattr_reader_with_default :primary_key_prefix_type, nil
163
164     # Accessor for the name of the prefix string to prepend to every table name. So if set to "basecamp_", all
165     # table names will be named like "basecamp_projects", "basecamp_people", etc. This is a convenient way of creating a namespace
166     # for tables in a shared database. By default, the prefix is the empty string.
167     def self.table_name_prefix=(table_name_prefix)
168       @@table_name_prefix = table_name_prefix
169     end
170     cattr_reader_with_default :table_name_prefix, ""
171
172     # Works like +table_name_prefix+, but appends instead of prepends (set to "_basecamp" gives "projects_basecamp",
173     # "people_basecamp"). By default, the suffix is the empty string.
174     def self.table_name_suffix=(table_name_suffix)
175       @@table_name_suffix = table_name_suffix
176     end
177     cattr_reader_with_default :table_name_suffix, ""
178
179     # Indicates whether table names should be the pluralized versions of the corresponding class names.
180     # If true, the default table name for a +Product+ class will be +products+. If false, it would just be +product+.
181     # See table_name for the full rules on table/class naming. This is true, by default.
182     def self.pluralize_table_names=(pluralize_table_names)
183       @@pluralize_table_names = pluralize_table_names
184     end
185     cattr_reader_with_default :pluralize_table_names, true
186   end
187 end
188  
189 if $0 == __FILE__
190   require 'test/unit'
191   class SomeClass #:nodoc:
192     def self.option=(option)
193       @@option = option
194     end
195     cattr_reader_with_default :option, "Value"
196   end
197   class CAttrReaderWithDefaultTest < Test::Unit::TestCase #:nodoc:
198     def test_should_create_and_accessor_and_set_the_default
199       assert_equal "Value", SomeClass.option
200     end
201   end
202 end