mongoid_taggable_with_context 1.1.3 → 1.1.4

Sign up to get free protection for your applications and to get access to all the features.
data/Rakefile CHANGED
@@ -1,32 +1,32 @@
1
- require 'rubygems'
2
- require 'bundler'
3
- Bundler.setup
4
-
5
- require 'rake'
6
- require 'jeweler'
7
-
8
- $LOAD_PATH.unshift File.expand_path("../lib", __FILE__)
9
- require 'mongoid/taggable_with_context/version'
10
-
11
- Jeweler::Tasks.new do |gem|
12
- gem.name = "mongoid_taggable_with_context"
13
- gem.homepage = "http://github.com/lgs/mongoid_taggable_with_context"
14
- gem.license = "MIT"
15
- gem.summary = %Q{Mongoid taggable behaviour}
16
- gem.description = %Q{Add multiple tag fields on Mongoid documents with aggregation capability.}
17
- gem.authors = ["Aaron Qian", "Luca G. Soave", "John Shields", "Wilker Lucio", "Ches Martin"]
18
- gem.version = Mongoid::TaggableWithContext::VERSION
19
- end
20
- Jeweler::RubygemsDotOrgTasks.new
21
-
22
- require 'rspec/core'
23
- require 'rspec/core/rake_task'
24
- RSpec::Core::RakeTask.new(:spec) do |spec|
25
- spec.pattern = FileList['spec/**/*_spec.rb']
26
- spec.rspec_opts = "--color --format progress"
27
- end
28
-
29
- task default: :spec
30
-
31
- require 'yard'
32
- YARD::Rake::YardocTask.new
1
+ require 'rubygems'
2
+ require 'bundler'
3
+ Bundler.setup
4
+
5
+ require 'rake'
6
+ require 'jeweler'
7
+
8
+ $LOAD_PATH.unshift File.expand_path("../lib", __FILE__)
9
+ require 'mongoid/taggable_with_context/version'
10
+
11
+ Jeweler::Tasks.new do |gem|
12
+ gem.name = "mongoid_taggable_with_context"
13
+ gem.homepage = "http://github.com/lgs/mongoid_taggable_with_context"
14
+ gem.license = "MIT"
15
+ gem.summary = %Q{Mongoid taggable behaviour}
16
+ gem.description = %Q{Add multiple tag fields on Mongoid documents with aggregation capability.}
17
+ gem.authors = ["Aaron Qian", "Luca G. Soave", "John Shields", "Wilker Lucio", "Ches Martin"]
18
+ gem.version = Mongoid::TaggableWithContext::VERSION
19
+ end
20
+ Jeweler::RubygemsDotOrgTasks.new
21
+
22
+ require 'rspec/core'
23
+ require 'rspec/core/rake_task'
24
+ RSpec::Core::RakeTask.new(:spec) do |spec|
25
+ spec.pattern = FileList['spec/**/*_spec.rb']
26
+ spec.rspec_opts = "--color --format progress"
27
+ end
28
+
29
+ task default: :spec
30
+
31
+ require 'yard'
32
+ YARD::Rake::YardocTask.new
@@ -1,320 +1,320 @@
1
- module Mongoid::TaggableWithContext
2
- extend ActiveSupport::Concern
3
-
4
- class AggregationStrategyMissing < Exception; end
5
- class InvalidTagsFormat < Exception; end
6
-
7
- DEFAULT_FIELD = :tags
8
- DEFAULT_SEPARATOR = ' '
9
-
10
- included do
11
- class_attribute :taggable_with_context_options
12
- self.taggable_with_context_options = {}
13
- end
14
-
15
- def tag_string_for(context)
16
- self.read_attribute(context).join(self.class.get_tag_separator_for(context)) rescue ""
17
- end
18
-
19
- def set_tag_string_for(context, value)
20
- self.write_attribute(context, self.class.format_tags_for(context, value))
21
- end
22
-
23
- module ClassMethods
24
- # Macro to declare a document class as taggable, specify field name
25
- # for tags, and set options for tagging behavior.
26
- #
27
- # @example Define a taggable document.
28
- #
29
- # class Article
30
- # include Mongoid::Document
31
- # include Mongoid::TaggableWithContext
32
- # taggable :keywords, separator: ' ', default: ['foobar']
33
- # end
34
- #
35
- # @param [ Symbol ] field The name of the field for tags. Defaults to :tags if not specified.
36
- # @param [ Hash ] options Options for taggable behavior.
37
- #
38
- # @option options [ String ] :separator
39
- # The delimiter used when converting the tags to and from String format. Defaults to ' '
40
- # @option options [ :Symbol ] :group_by_field
41
- # The Mongoid field to group by when RealTimeGroupBy aggregation is used.
42
- # @option options [ <various> ] :default, :as, :localize, etc.
43
- # Options for Mongoid #field method will be automatically passed
44
- # to the underlying Array field
45
- def taggable(*args)
46
- # init variables
47
- options = args.extract_options!
48
- field = args.present? ? args.shift.to_sym : DEFAULT_FIELD
49
- added = add_taggable(field, options)
50
- # TODO: test if this is needed
51
- # descendants.each do |subclass|
52
- # subclass.add_taggable(field, options)
53
- # end
54
- added
55
- end
56
-
57
- def tag_contexts
58
- self.taggable_with_context_options.keys
59
- end
60
-
61
- def tag_database_fields
62
- self.taggable_with_context_options.keys.map do |context|
63
- tag_options_for(context)[:db_field]
64
- end
65
- end
66
-
67
- def tag_options_for(context)
68
- self.taggable_with_context_options[context]
69
- end
70
-
71
- def tags_for(context, group_by=nil, conditions={})
72
- raise AggregationStrategyMissing
73
- end
74
-
75
- def tags_with_weight_for(context, group_by=nil, conditions={})
76
- raise AggregationStrategyMissing
77
- end
78
-
79
- def get_tag_separator_for(context)
80
- self.taggable_with_context_options[context][:separator]
81
- end
82
-
83
- def get_tag_group_by_field_for(context)
84
- self.taggable_with_context_options[context][:group_by_field]
85
- end
86
-
87
- # Find documents tagged with all tags passed as a parameter, given
88
- # as an Array or a String using the configured separator.
89
- #
90
- # @example Find matching all tags in an Array.
91
- # Article.tagged_with(['ruby', 'mongodb'])
92
- # @example Find matching all tags in a String.
93
- # Article.tagged_with('ruby, mongodb')
94
- #
95
- # @param [ String ] :field The field name of the tag.
96
- # @param [ Array<String, Symbol>, String ] :tags Tags to match.
97
- # @return [ Criteria ] A new criteria.
98
- def tagged_with(context, tags)
99
- tags = format_tags_for(context, tags)
100
- field = tag_options_for(context)[:field]
101
- all_in(field => tags)
102
- end
103
-
104
- # Helper method to convert a a tag input value of unknown type
105
- # to a formatted array.
106
- def format_tags_for(context, value)
107
- return nil if value.nil?
108
- # 0) Tags must be an array or a string
109
- raise InvalidTagsFormat unless value.is_a?(Array) || value.is_a?(String)
110
- # 1) convert String to Array
111
- value = value.split(get_tag_separator_for(context)) if value.is_a? String
112
- # 2) remove all nil values
113
- # 3) strip all white spaces. Could leave blank strings (e.g. foo, , bar, baz)
114
- # 4) remove all blank strings
115
- # 5) remove duplicate
116
- value.compact.map(&:strip).reject(&:blank?).uniq
117
- end
118
-
119
- protected
120
-
121
- # Adds a taggable context to the list of contexts, and creates the underlying
122
- # Mongoid field and alias methods for the context.
123
- #
124
- # @param [ Symbol ] field The name of the Mongoid database field to store the taggable.
125
- # @param [ Hash ] options The taggable options.
126
- #
127
- # @since 1.1.1
128
- def add_taggable(field, options)
129
- validate_taggable_options(options)
130
-
131
- # db_field: the field name stored in the database
132
- options[:db_field] = field.to_sym
133
- # field: the field name used to identify the tags. :field will
134
- # be identical to :db_field unless the :as option is specified
135
- options[:field] = options[:as] || field
136
- context = options[:field]
137
- options.reverse_merge!(
138
- separator: DEFAULT_SEPARATOR
139
- )
140
-
141
- # register / update settings
142
- self.taggable_with_context_options[options[:field]] = options
143
-
144
- create_taggable_mongoid_field(field, options)
145
- create_taggable_mongoid_index(context)
146
- define_taggable_accessors(context)
147
- end
148
-
149
- # Validates the taggable options and raises errors if invalid options are detected.
150
- #
151
- # @param [ Hash ] options The taggable options.
152
- #
153
- # @since 1.1.1
154
- def validate_taggable_options(options)
155
- if options[:field]
156
- raise <<-ERR
157
- taggable :field option has been removed as of version 1.1.1. Please use the
158
- syntax "taggable <database_name>, as: <tag_name>"
159
- ERR
160
- end
161
- if options[:string_method]
162
- raise <<-ERR
163
- taggable :string_method option has been removed as of version 1.1.1. Please
164
- define an alias to "<tags>_string" in your Model
165
- ERR
166
- end
167
- end
168
-
169
- # Creates the underlying Mongoid field for the tag context.
170
- #
171
- # @param [ Symbol ] name The name of the Mongoid field.
172
- # @param [ Hash ] options Options for the Mongoid field.
173
- #
174
- # @since 1.1.1
175
- def create_taggable_mongoid_field(name, options)
176
- field name, mongoid_field_options(options)
177
- end
178
-
179
- # Prepares valid Mongoid option keys from the taggable options. Slices
180
- # the taggable options to include only valid options for the Mongoid #field
181
- # method, and coerces :type to Array.
182
- #
183
- # @param [ Hash ] :options The taggable options hash.
184
- # @return [ Hash ] A options hash for the Mongoid #field method.
185
- #
186
- # @since 1.1.1
187
- def mongoid_field_options(options = {})
188
- options.slice(*::Mongoid::Fields::Validators::Macro::OPTIONS).merge!(type: Array)
189
- end
190
-
191
- # Creates an index for the underlying Mongoid field.
192
- #
193
- # @param [ Symbol ] name The name or alias name of Mongoid field.
194
- #
195
- # @since 1.1.1
196
- def create_taggable_mongoid_index(name)
197
- index({ name => 1 }, { background: true })
198
- end
199
-
200
- # Defines all accessor methods for the taggable context at both
201
- # the instance and class level.
202
- #
203
- # @param [ Symbol ] context The name of the tag context.
204
- #
205
- # @since 1.1.1
206
- def define_taggable_accessors(context)
207
- define_class_tags_getter(context)
208
- define_class_weighted_tags_getter(context)
209
- define_class_separator_getter(context)
210
- define_class_tagged_with_getter(context)
211
- define_class_group_by_getter(context)
212
- define_instance_tag_string_getter(context)
213
- define_instance_tag_setter(context)
214
- end
215
-
216
- # Create the singleton getter method to retrieve all tags
217
- # of a given context for all instances of the model.
218
- #
219
- # @param [ Symbol ] context The name of the tag context.
220
- #
221
- # @since 1.1.1
222
- def define_class_tags_getter(context)
223
- # retrieve all tags ever created for the model
224
- self.class.class_eval do
225
- define_method context do |group_by = nil|
226
- tags_for(context, group_by)
227
- end
228
- end
229
- end
230
-
231
- # Create the singleton getter method to retrieve a weighted
232
- # array of tags of a given context for all instances of the model.
233
- #
234
- # @param [ Symbol ] context The name of the tag context.
235
- #
236
- # @since 1.1.1
237
- def define_class_weighted_tags_getter(context)
238
- self.class.class_eval do
239
- define_method :"#{context}_with_weight" do |group_by = nil|
240
- tags_with_weight_for(context, group_by)
241
- end
242
- end
243
- end
244
-
245
- # Create the singleton getter method to retrieve the tag separator
246
- # for a given context for all instances of the model.
247
- #
248
- # @param [ Symbol ] context The name of the tag context.
249
- #
250
- # @since 1.1.1
251
- def define_class_separator_getter(context)
252
- self.class.class_eval do
253
- define_method :"#{context}_separator" do
254
- get_tag_separator_for(context)
255
- end
256
- end
257
- end
258
-
259
- # Create the singleton getter method to retrieve the all
260
- # instances of the model which contain the tag/tags for a given context.
261
- #
262
- # @param [ Symbol ] context The name of the tag context.
263
- #
264
- # @since 1.1.1
265
- def define_class_tagged_with_getter(context)
266
- self.class.class_eval do
267
- define_method :"#{context}_tagged_with" do |tags|
268
- tagged_with(context, tags)
269
- end
270
- end
271
- end
272
-
273
- # Create the singleton getter method to retrieve the
274
- # group_by field
275
- #
276
- # @param [ Symbol ] context The name of the tag context.
277
- #
278
- # @since 1.1.1
279
- def define_class_group_by_getter(context)
280
- self.class.class_eval do
281
- define_method :"#{context}_group_by_field" do
282
- get_tag_group_by_field_for(context)
283
- end
284
- end
285
- end
286
-
287
- # Create the setter method for the provided taggable, using an
288
- # alias method chain to the underlying field method.
289
- #
290
- # @param [ Symbol ] context The name of the tag context.
291
- #
292
- # @since 1.1.1
293
- def define_instance_tag_setter(context)
294
- generated_methods.module_eval do
295
- re_define_method("#{context}_with_taggable=") do |value|
296
- value = self.class.format_tags_for(context, value)
297
- self.send("#{context}_without_taggable=", value)
298
- end
299
- alias_method_chain "#{context}=", :taggable
300
- end
301
- end
302
-
303
- # Create the getter method for the joined tags string.
304
- #
305
- # @param [ Symbol ] context The name of the tag context.
306
- #
307
- # @since 1.1.1
308
- def define_instance_tag_string_getter(context)
309
- generated_methods.module_eval do
310
- re_define_method("#{context}_string") do
311
- tag_string_for(context)
312
- end
313
-
314
- re_define_method("#{context}_string=") do |value|
315
- set_tag_string_for(context, value)
316
- end
317
- end
318
- end
319
- end
320
- end
1
+ module Mongoid::TaggableWithContext
2
+ extend ActiveSupport::Concern
3
+
4
+ class AggregationStrategyMissing < Exception; end
5
+ class InvalidTagsFormat < Exception; end
6
+
7
+ DEFAULT_FIELD = :tags
8
+ DEFAULT_SEPARATOR = ' '
9
+
10
+ included do
11
+ class_attribute :taggable_with_context_options
12
+ self.taggable_with_context_options = {}
13
+ end
14
+
15
+ def tag_string_for(context)
16
+ self.read_attribute(context).join(self.class.get_tag_separator_for(context)) rescue ""
17
+ end
18
+
19
+ def set_tag_string_for(context, value)
20
+ self.write_attribute(context, self.class.format_tags_for(context, value))
21
+ end
22
+
23
+ module ClassMethods
24
+ # Macro to declare a document class as taggable, specify field name
25
+ # for tags, and set options for tagging behavior.
26
+ #
27
+ # @example Define a taggable document.
28
+ #
29
+ # class Article
30
+ # include Mongoid::Document
31
+ # include Mongoid::TaggableWithContext
32
+ # taggable :keywords, separator: ' ', default: ['foobar']
33
+ # end
34
+ #
35
+ # @param [ Symbol ] field The name of the field for tags. Defaults to :tags if not specified.
36
+ # @param [ Hash ] options Options for taggable behavior.
37
+ #
38
+ # @option options [ String ] :separator
39
+ # The delimiter used when converting the tags to and from String format. Defaults to ' '
40
+ # @option options [ :Symbol ] :group_by_field
41
+ # The Mongoid field to group by when RealTimeGroupBy aggregation is used.
42
+ # @option options [ <various> ] :default, :as, :localize, etc.
43
+ # Options for Mongoid #field method will be automatically passed
44
+ # to the underlying Array field
45
+ def taggable(*args)
46
+ # init variables
47
+ options = args.extract_options!
48
+ field = args.present? ? args.shift.to_sym : DEFAULT_FIELD
49
+ added = add_taggable(field, options)
50
+ # TODO: test if this is needed
51
+ # descendants.each do |subclass|
52
+ # subclass.add_taggable(field, options)
53
+ # end
54
+ added
55
+ end
56
+
57
+ def tag_contexts
58
+ self.taggable_with_context_options.keys
59
+ end
60
+
61
+ def tag_database_fields
62
+ self.taggable_with_context_options.keys.map do |context|
63
+ tag_options_for(context)[:db_field]
64
+ end
65
+ end
66
+
67
+ def tag_options_for(context)
68
+ self.taggable_with_context_options[context]
69
+ end
70
+
71
+ def tags_for(context, group_by=nil, conditions={})
72
+ raise AggregationStrategyMissing
73
+ end
74
+
75
+ def tags_with_weight_for(context, group_by=nil, conditions={})
76
+ raise AggregationStrategyMissing
77
+ end
78
+
79
+ def get_tag_separator_for(context)
80
+ self.taggable_with_context_options[context][:separator]
81
+ end
82
+
83
+ def get_tag_group_by_field_for(context)
84
+ self.taggable_with_context_options[context][:group_by_field]
85
+ end
86
+
87
+ # Find documents tagged with all tags passed as a parameter, given
88
+ # as an Array or a String using the configured separator.
89
+ #
90
+ # @example Find matching all tags in an Array.
91
+ # Article.tagged_with(['ruby', 'mongodb'])
92
+ # @example Find matching all tags in a String.
93
+ # Article.tagged_with('ruby, mongodb')
94
+ #
95
+ # @param [ String ] :field The field name of the tag.
96
+ # @param [ Array<String, Symbol>, String ] :tags Tags to match.
97
+ # @return [ Criteria ] A new criteria.
98
+ def tagged_with(context, tags)
99
+ tags = format_tags_for(context, tags)
100
+ field = tag_options_for(context)[:field]
101
+ all_in(field => tags)
102
+ end
103
+
104
+ # Helper method to convert a a tag input value of unknown type
105
+ # to a formatted array.
106
+ def format_tags_for(context, value)
107
+ return nil if value.nil?
108
+ # 0) Tags must be an array or a string
109
+ raise InvalidTagsFormat unless value.is_a?(Array) || value.is_a?(String)
110
+ # 1) convert String to Array
111
+ value = value.split(get_tag_separator_for(context)) if value.is_a? String
112
+ # 2) remove all nil values
113
+ # 3) strip all white spaces. Could leave blank strings (e.g. foo, , bar, baz)
114
+ # 4) remove all blank strings
115
+ # 5) remove duplicate
116
+ value.compact.map(&:strip).reject(&:blank?).uniq
117
+ end
118
+
119
+ protected
120
+
121
+ # Adds a taggable context to the list of contexts, and creates the underlying
122
+ # Mongoid field and alias methods for the context.
123
+ #
124
+ # @param [ Symbol ] field The name of the Mongoid database field to store the taggable.
125
+ # @param [ Hash ] options The taggable options.
126
+ #
127
+ # @since 1.1.1
128
+ def add_taggable(field, options)
129
+ validate_taggable_options(options)
130
+
131
+ # db_field: the field name stored in the database
132
+ options[:db_field] = field.to_sym
133
+ # field: the field name used to identify the tags. :field will
134
+ # be identical to :db_field unless the :as option is specified
135
+ options[:field] = options[:as] || field
136
+ context = options[:field]
137
+ options.reverse_merge!(
138
+ separator: DEFAULT_SEPARATOR
139
+ )
140
+
141
+ # register / update settings
142
+ self.taggable_with_context_options[options[:field]] = options
143
+
144
+ create_taggable_mongoid_field(field, options)
145
+ create_taggable_mongoid_index(context)
146
+ define_taggable_accessors(context)
147
+ end
148
+
149
+ # Validates the taggable options and raises errors if invalid options are detected.
150
+ #
151
+ # @param [ Hash ] options The taggable options.
152
+ #
153
+ # @since 1.1.1
154
+ def validate_taggable_options(options)
155
+ if options[:field]
156
+ raise <<-ERR
157
+ taggable :field option has been removed as of version 1.1.1. Please use the
158
+ syntax "taggable <database_name>, as: <tag_name>"
159
+ ERR
160
+ end
161
+ if options[:string_method]
162
+ raise <<-ERR
163
+ taggable :string_method option has been removed as of version 1.1.1. Please
164
+ define an alias to "<tags>_string" in your Model
165
+ ERR
166
+ end
167
+ end
168
+
169
+ # Creates the underlying Mongoid field for the tag context.
170
+ #
171
+ # @param [ Symbol ] name The name of the Mongoid field.
172
+ # @param [ Hash ] options Options for the Mongoid field.
173
+ #
174
+ # @since 1.1.1
175
+ def create_taggable_mongoid_field(name, options)
176
+ field name, mongoid_field_options(options)
177
+ end
178
+
179
+ # Prepares valid Mongoid option keys from the taggable options. Slices
180
+ # the taggable options to include only valid options for the Mongoid #field
181
+ # method, and coerces :type to Array.
182
+ #
183
+ # @param [ Hash ] :options The taggable options hash.
184
+ # @return [ Hash ] A options hash for the Mongoid #field method.
185
+ #
186
+ # @since 1.1.1
187
+ def mongoid_field_options(options = {})
188
+ options.slice(*::Mongoid::Fields::Validators::Macro::OPTIONS).merge!(type: Array)
189
+ end
190
+
191
+ # Creates an index for the underlying Mongoid field.
192
+ #
193
+ # @param [ Symbol ] name The name or alias name of Mongoid field.
194
+ #
195
+ # @since 1.1.1
196
+ def create_taggable_mongoid_index(name)
197
+ index({ name => 1 }, { background: true })
198
+ end
199
+
200
+ # Defines all accessor methods for the taggable context at both
201
+ # the instance and class level.
202
+ #
203
+ # @param [ Symbol ] context The name of the tag context.
204
+ #
205
+ # @since 1.1.1
206
+ def define_taggable_accessors(context)
207
+ define_class_tags_getter(context)
208
+ define_class_weighted_tags_getter(context)
209
+ define_class_separator_getter(context)
210
+ define_class_tagged_with_getter(context)
211
+ define_class_group_by_getter(context)
212
+ define_instance_tag_string_getter(context)
213
+ define_instance_tag_setter(context)
214
+ end
215
+
216
+ # Create the singleton getter method to retrieve all tags
217
+ # of a given context for all instances of the model.
218
+ #
219
+ # @param [ Symbol ] context The name of the tag context.
220
+ #
221
+ # @since 1.1.1
222
+ def define_class_tags_getter(context)
223
+ # retrieve all tags ever created for the model
224
+ self.class.class_eval do
225
+ define_method context do |group_by = nil|
226
+ tags_for(context, group_by)
227
+ end
228
+ end
229
+ end
230
+
231
+ # Create the singleton getter method to retrieve a weighted
232
+ # array of tags of a given context for all instances of the model.
233
+ #
234
+ # @param [ Symbol ] context The name of the tag context.
235
+ #
236
+ # @since 1.1.1
237
+ def define_class_weighted_tags_getter(context)
238
+ self.class.class_eval do
239
+ define_method :"#{context}_with_weight" do |group_by = nil|
240
+ tags_with_weight_for(context, group_by)
241
+ end
242
+ end
243
+ end
244
+
245
+ # Create the singleton getter method to retrieve the tag separator
246
+ # for a given context for all instances of the model.
247
+ #
248
+ # @param [ Symbol ] context The name of the tag context.
249
+ #
250
+ # @since 1.1.1
251
+ def define_class_separator_getter(context)
252
+ self.class.class_eval do
253
+ define_method :"#{context}_separator" do
254
+ get_tag_separator_for(context)
255
+ end
256
+ end
257
+ end
258
+
259
+ # Create the singleton getter method to retrieve the all
260
+ # instances of the model which contain the tag/tags for a given context.
261
+ #
262
+ # @param [ Symbol ] context The name of the tag context.
263
+ #
264
+ # @since 1.1.1
265
+ def define_class_tagged_with_getter(context)
266
+ self.class.class_eval do
267
+ define_method :"#{context}_tagged_with" do |tags|
268
+ tagged_with(context, tags)
269
+ end
270
+ end
271
+ end
272
+
273
+ # Create the singleton getter method to retrieve the
274
+ # group_by field
275
+ #
276
+ # @param [ Symbol ] context The name of the tag context.
277
+ #
278
+ # @since 1.1.1
279
+ def define_class_group_by_getter(context)
280
+ self.class.class_eval do
281
+ define_method :"#{context}_group_by_field" do
282
+ get_tag_group_by_field_for(context)
283
+ end
284
+ end
285
+ end
286
+
287
+ # Create the setter method for the provided taggable, using an
288
+ # alias method chain to the underlying field method.
289
+ #
290
+ # @param [ Symbol ] context The name of the tag context.
291
+ #
292
+ # @since 1.1.1
293
+ def define_instance_tag_setter(context)
294
+ generated_methods.module_eval do
295
+ re_define_method("#{context}_with_taggable=") do |value|
296
+ value = self.class.format_tags_for(context, value)
297
+ self.send("#{context}_without_taggable=", value)
298
+ end
299
+ alias_method_chain "#{context}=", :taggable
300
+ end
301
+ end
302
+
303
+ # Create the getter method for the joined tags string.
304
+ #
305
+ # @param [ Symbol ] context The name of the tag context.
306
+ #
307
+ # @since 1.1.1
308
+ def define_instance_tag_string_getter(context)
309
+ generated_methods.module_eval do
310
+ re_define_method("#{context}_string") do
311
+ tag_string_for(context)
312
+ end
313
+
314
+ re_define_method("#{context}_string=") do |value|
315
+ set_tag_string_for(context, value)
316
+ end
317
+ end
318
+ end
319
+ end
320
+ end