public
Description: Rails plugin that provides a simple API for extending a model/class from a module.
Homepage: http://henrik.nyh.se/2008/09/augmentations
Clone URL: git://github.com/henrik/augmentations.git
augmentations / README.markdown
0078f6cf » henrik 2008-09-10 First commit. Comment 1 # Augmentations
2
3 Too "fat" Rails models can be unmanageable. Also, sometimes you want to define or run the same methods in several different models.
4
5 *Augmentations* is a Rails plugin that provides a simple API for extending a model (or other class) with instance methods and class methods, as well as running class methods like `belongs_to` at extend time.
6
7 ## Rails model extensions
8
9 This plugin uses regular Ruby modules, but with some additions.
10
11 My [Rails model extensions](http://henrik.nyh.se/2008/02/rails-model-extensions) article gives details on how you can use modules to extend Rails models. In brief:
12
13 You define a module like
14
15 module Shared
16 module Pingable
5c7e9e12 » henrik 2008-09-10 Consistently use "# …" rath... 17 # …
0078f6cf » henrik 2008-09-10 First commit. Comment 18 end
19 end
20
21 in `app/models/shared/pingable.rb`, or
22
23 module User
24 module PasswordResetExtension
5c7e9e12 » henrik 2008-09-10 Consistently use "# …" rath... 25 # …
0078f6cf » henrik 2008-09-10 First commit. Comment 26 end
27 end
28
29 in `app/models/user/password_reset_extension.rb`.
30
31
32 ## Old style
33
34 Without this plugin, you would then include them in models like
35
36 class User < ActiveRecord::Base
37 include PasswordResetExtension,
38 Shared::Pingable
39 end
40
41 The `app/models/shared/pingable.rb` file could look something like
42
43 module Shared
44 module Pingable
45
46 def an_instance_method
47 # …
48 end
49
50 def self.included(klass)
51 klass.class_eval do
52 belongs_to :ping
53
54 def self.a_class_method
55 # …
56 end
57 end
58 end
59
60 end
61 end
62
63 I have some issues with this:
64
65 * There is too much boilerplate in the module, obscuring what you're actually adding.
66
77fb517b » henrik 2008-11-19 README: "extend", not "excl... 67 * Abusing the standard method `include` to not only add instance methods but also do stuff on the class level can be confusing. You could use `extend` as well, though this is more verbose. To get the `belongs_to`, you'd still need to use module hooks, or put another line of code in the model.
0078f6cf » henrik 2008-09-10 First commit. Comment 68
69 * It looks different from how the code would look if defined in the model: the instance methods are in a different block of code than the class-level stuff – though you could get around this by putting everything in the `class_eval`.
70
71
72 ## New style
73
71188c1f » henrik 2008-09-10 No need to refer to the blo... 74 Modules are still used, as described above, but the API is improved.
0078f6cf » henrik 2008-09-10 First commit. Comment 75
76 Use *Augmentations* like:
77
78 class User < ActiveRecord::Base
79 augment Shared::Pingable, PasswordResetExtension
80 end
81
82 With modules like
83
84 module Shared
85 module Pingable
86 augmentation do
87
88 belongs_to :ping
89
90 def self.a_class_method
91 # …
92 end
93
94 def an_instance_method
95 # …
96 end
97
98 end
99 end
100 end
101
102 What I like about this:
103
104 * A new method, `augment`, is used, rather than abusing `include`.
105
fa770f15 » henrik 2008-09-10 Consistent spelling: "boile... 106 * Less boilerplate.
0078f6cf » henrik 2008-09-10 First commit. Comment 107
108 * Keeps the code for class and instances together, looking just like it would do in the model. You could achieve this with `included` and `class_eval` as mentioned above, but it would not have the other benefits.
109
110 * The plugin amounts to very little code and a straightforward implementation. It's basically lipstick on `included` and `class_eval`.
111
112 (If you want to weird things up in the name of fewer lines of code, the Ruby parser will accept
113
114 module Shared
115 module Pingable augmentation do
116
117
118
119 end end
120 end
121
122 too.)
123
124
125 ## To-do
126
127 Add support for module arguments; something like
128
129 augment Shared::Pingable, :pong => false
130
131
132 ## Credits
133
134 By [Henrik Nyh](http://henrik.nyh.se/) for [DanceJam](http://dancejam.com).