Froze rails gems
[depot.git] / vendor / rails / railties / doc / guides / source / creating_plugins / acts_as_yaffle.txt
1 == Add an `acts_as_yaffle` method to Active Record ==
2
3 A common pattern in plugins is to add a method called 'acts_as_something' to models. In this case, you want to write a method called 'acts_as_yaffle' that adds a 'squawk' method to your models.
4
5 To begin, set up your files so that you have:
6
7 *vendor/plugins/yaffle/test/acts_as_yaffle_test.rb*
8
9 [source, ruby]
10 ------------------------------------------------------
11 require File.dirname(__FILE__) + '/test_helper.rb'
12
13 class ActsAsYaffleTest < Test::Unit::TestCase
14 end
15 ------------------------------------------------------
16
17 *vendor/plugins/yaffle/lib/yaffle.rb*
18
19 [source, ruby]
20 ------------------------------------------------------
21 require 'yaffle/acts_as_yaffle'
22 ------------------------------------------------------
23
24 *vendor/plugins/yaffle/lib/yaffle/acts_as_yaffle.rb*
25
26 [source, ruby]
27 ------------------------------------------------------
28 module Yaffle
29 # your code will go here
30 end
31 ------------------------------------------------------
32
33 Note that after requiring 'acts_as_yaffle' you also have to include it into ActiveRecord::Base so that your plugin methods will be available to the rails models.
34
35 One of the most common plugin patterns for 'acts_as_yaffle' plugins is to structure your file like so:
36
37 *vendor/plugins/yaffle/lib/yaffle/acts_as_yaffle.rb*
38
39 [source, ruby]
40 ------------------------------------------------------
41 module Yaffle
42 def self.included(base)
43 base.send :extend, ClassMethods
44 end
45
46 module ClassMethods
47 # any method placed here will apply to classes, like Hickwall
48 def acts_as_something
49 send :include, InstanceMethods
50 end
51 end
52
53 module InstanceMethods
54 # any method placed here will apply to instaces, like @hickwall
55 end
56 end
57 ------------------------------------------------------
58
59 With structure you can easily separate the methods that will be used for the class (like `Hickwall.some_method`) and the instance (like `@hickwell.some_method`).
60
61 === Add a class method ===
62
63 This plugin will expect that you've added a method to your model named 'last_squawk'. However, the plugin users might have already defined a method on their model named 'last_squawk' that they use for something else. This plugin will allow the name to be changed by adding a class method called 'yaffle_text_field'.
64
65 To start out, write a failing test that shows the behavior you'd like:
66
67 *vendor/plugins/yaffle/test/acts_as_yaffle_test.rb*
68
69 [source, ruby]
70 ------------------------------------------------------
71 require File.dirname(__FILE__) + '/test_helper.rb'
72
73 class Hickwall < ActiveRecord::Base
74 acts_as_yaffle
75 end
76
77 class Wickwall < ActiveRecord::Base
78 acts_as_yaffle :yaffle_text_field => :last_tweet
79 end
80
81 class ActsAsYaffleTest < Test::Unit::TestCase
82 load_schema
83
84 def test_a_hickwalls_yaffle_text_field_should_be_last_squawk
85 assert_equal "last_squawk", Hickwall.yaffle_text_field
86 end
87
88 def test_a_wickwalls_yaffle_text_field_should_be_last_tweet
89 assert_equal "last_tweet", Wickwall.yaffle_text_field
90 end
91 end
92 ------------------------------------------------------
93
94 To make these tests pass, you could modify your `acts_as_yaffle` file like so:
95
96 *vendor/plugins/yaffle/lib/yaffle/acts_as_yaffle.rb*
97
98 [source, ruby]
99 ------------------------------------------------------
100 module Yaffle
101 def self.included(base)
102 base.send :extend, ClassMethods
103 end
104
105 module ClassMethods
106 def acts_as_yaffle(options = {})
107 cattr_accessor :yaffle_text_field
108 self.yaffle_text_field = (options[:yaffle_text_field] || :last_squawk).to_s
109 end
110 end
111 end
112
113 ActiveRecord::Base.send :include, Yaffle
114 ------------------------------------------------------
115
116 === Add an instance method ===
117
118 This plugin will add a method named 'squawk' to any Active Record objects that call 'acts_as_yaffle'. The 'squawk' method will simply set the value of one of the fields in the database.
119
120 To start out, write a failing test that shows the behavior you'd like:
121
122 *vendor/plugins/yaffle/test/acts_as_yaffle_test.rb*
123
124 [source, ruby]
125 ------------------------------------------------------
126 require File.dirname(__FILE__) + '/test_helper.rb'
127
128 class Hickwall < ActiveRecord::Base
129 acts_as_yaffle
130 end
131
132 class Wickwall < ActiveRecord::Base
133 acts_as_yaffle :yaffle_text_field => :last_tweet
134 end
135
136 class ActsAsYaffleTest < Test::Unit::TestCase
137 load_schema
138
139 def test_a_hickwalls_yaffle_text_field_should_be_last_squawk
140 assert_equal "last_squawk", Hickwall.yaffle_text_field
141 end
142
143 def test_a_wickwalls_yaffle_text_field_should_be_last_tweet
144 assert_equal "last_tweet", Wickwall.yaffle_text_field
145 end
146
147 def test_hickwalls_squawk_should_populate_last_squawk
148 hickwall = Hickwall.new
149 hickwall.squawk("Hello World")
150 assert_equal "squawk! Hello World", hickwall.last_squawk
151 end
152
153 def test_wickwalls_squawk_should_populate_last_tweeted_at
154 wickwall = Wickwall.new
155 wickwall.squawk("Hello World")
156 assert_equal "squawk! Hello World", wickwall.last_tweet
157 end
158 end
159 ------------------------------------------------------
160
161 Run this test to make sure the last two tests fail, then update 'acts_as_yaffle.rb' to look like this:
162
163 *vendor/plugins/yaffle/lib/yaffle/acts_as_yaffle.rb*
164
165 [source, ruby]
166 ------------------------------------------------------
167 module Yaffle
168 def self.included(base)
169 base.send :extend, ClassMethods
170 end
171
172 module ClassMethods
173 def acts_as_yaffle(options = {})
174 cattr_accessor :yaffle_text_field
175 self.yaffle_text_field = (options[:yaffle_text_field] || :last_squawk).to_s
176 send :include, InstanceMethods
177 end
178 end
179
180 module InstanceMethods
181 def squawk(string)
182 write_attribute(self.class.yaffle_text_field, string.to_squawk)
183 end
184 end
185 end
186
187 ActiveRecord::Base.send :include, Yaffle
188 ------------------------------------------------------
189
190 .Editor's note:
191 NOTE: The use of `write_attribute` to write to the field in model is just one example of how a plugin can interact with the model, and will not always be the right method to use. For example, you could also use `send("#{self.class.yaffle_text_field}=", string.to_squawk)`.