make_taggable 0.7.5 → 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGELOG.md +79 -0
- data/CONTRIBUTING.md +65 -22
- data/LICENSE.md +18 -17
- data/README.md +73 -444
- data/UPGRADING.md +28 -2
- data/docs/caching.md +93 -0
- data/docs/configuration.md +108 -0
- data/docs/contexts.md +147 -0
- data/docs/database.md +106 -0
- data/docs/getting-started.md +114 -0
- data/docs/migrating-from-aato.md +67 -0
- data/docs/ownership.md +111 -0
- data/docs/parsers.md +109 -0
- data/docs/querying.md +163 -0
- data/docs/tag-clouds.md +74 -0
- data/lib/make_taggable/default_parser.rb +45 -32
- data/lib/make_taggable/engine.rb +6 -0
- data/lib/make_taggable/generic_parser.rb +30 -4
- data/lib/make_taggable/tag.rb +121 -19
- data/lib/make_taggable/tag_list.rb +77 -24
- data/lib/make_taggable/taggable/cache.rb +61 -11
- data/lib/make_taggable/taggable/collection.rb +102 -30
- data/lib/make_taggable/taggable/core.rb +154 -34
- data/lib/make_taggable/taggable/ownership.rb +82 -4
- data/lib/make_taggable/taggable/related.rb +66 -3
- data/lib/make_taggable/taggable/tag_list_type.rb +8 -0
- data/lib/make_taggable/taggable/tagged_with_query/all_tags_query.rb +10 -0
- data/lib/make_taggable/taggable/tagged_with_query/any_tags_query.rb +10 -0
- data/lib/make_taggable/taggable/tagged_with_query/exclude_tags_query.rb +10 -0
- data/lib/make_taggable/taggable/tagged_with_query/query_base.rb +15 -0
- data/lib/make_taggable/taggable/tagged_with_query.rb +17 -0
- data/lib/make_taggable/taggable.rb +34 -33
- data/lib/make_taggable/tagger.rb +73 -12
- data/lib/make_taggable/tagging.rb +30 -3
- data/lib/make_taggable/tags_helper.rb +22 -1
- data/lib/make_taggable/utils.rb +40 -5
- data/lib/make_taggable/version.rb +8 -1
- data/lib/make_taggable.rb +153 -8
- data/make_taggable.gemspec +13 -20
- metadata +50 -165
- data/.dummyrc +0 -17
- data/.github/workflows/ci.yml +0 -140
- data/.github/workflows/standard-ci.yml +0 -27
- data/.gitignore +0 -17
- data/.rspec +0 -3
- data/Appraisals +0 -15
- data/Gemfile +0 -16
- data/Rakefile +0 -13
- data/gemfiles/rails_5.gemfile +0 -9
- data/gemfiles/rails_6.gemfile +0 -9
- data/gemfiles/rails_6_1.gemfile +0 -9
- data/gemfiles/rails_master.gemfile +0 -9
- data/lib/tasks/setup_test_db.rake +0 -8
data/README.md
CHANGED
|
@@ -1,518 +1,147 @@
|
|
|
1
1
|
# MakeTaggable
|
|
2
|
+
|
|
2
3
|
[](https://badge.fury.io/rb/make_taggable)
|
|
3
4
|

|
|
4
5
|
[](https://github.com/MatthewKennedy/make_taggable/actions/workflows/standard-ci.yml)
|
|
5
6
|
|
|
6
|
-
|
|
7
|
+
Tagging for Active Record models, across any number of named contexts.
|
|
7
8
|
|
|
8
|
-
|
|
9
|
+
One model can carry several independent sets of tags — genres and moods, skills and interests —
|
|
10
|
+
each with its own list, counts and queries. Tags can belong to the user who applied them, keep the
|
|
11
|
+
order they were added in, and be cached on the record for display.
|
|
9
12
|
|
|
10
|
-
|
|
13
|
+
## Requirements
|
|
11
14
|
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
+
| | |
|
|
16
|
+
|---|---|
|
|
17
|
+
| Ruby | 3.2 or newer |
|
|
18
|
+
| Active Record | 7.2 or newer |
|
|
19
|
+
| Databases | PostgreSQL, MySQL, SQLite |
|
|
15
20
|
|
|
16
|
-
|
|
21
|
+
Tested against Rails 7.2, 8.0 and 8.1 on Ruby 3.2 through 4.0.
|
|
17
22
|
|
|
18
|
-
Install
|
|
23
|
+
## Install
|
|
19
24
|
|
|
20
25
|
```shell
|
|
21
|
-
|
|
26
|
+
bundle add make_taggable
|
|
22
27
|
```
|
|
23
28
|
|
|
24
|
-
Review the generated migrations then migrate:
|
|
25
29
|
```shell
|
|
30
|
+
rails make_taggable_engine:install:migrations
|
|
26
31
|
rails db:migrate
|
|
27
32
|
```
|
|
28
33
|
|
|
29
|
-
|
|
30
|
-
To make MySQL play nice with spÉcial characters you can setting the following line in an initializer file:
|
|
31
|
-
|
|
32
|
-
```ruby
|
|
33
|
-
MakeTaggable.force_binary_collation = true
|
|
34
|
-
```
|
|
35
|
-
|
|
36
|
-
Or by run this rake task:
|
|
37
|
-
|
|
38
|
-
```shell
|
|
39
|
-
rails make_taggable_engine:tag_names:collate_bin
|
|
40
|
-
```
|
|
41
|
-
|
|
42
|
-
See the Configuration section for more details.
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
## Usage
|
|
46
|
-
|
|
47
|
-
Setup
|
|
48
|
-
|
|
49
|
-
```ruby
|
|
50
|
-
class User < ActiveRecord::Base
|
|
51
|
-
make_taggable # Alias for make_taggable :tags
|
|
52
|
-
make_taggable :skills, :interests
|
|
53
|
-
end
|
|
54
|
-
|
|
55
|
-
class UsersController < ApplicationController
|
|
56
|
-
def user_params
|
|
57
|
-
params.require(:user).permit(:name, :tag_list) ## Rails 4 strong params usage
|
|
58
|
-
end
|
|
59
|
-
end
|
|
60
|
-
|
|
61
|
-
@user = User.new(:name => "Bobby")
|
|
62
|
-
```
|
|
63
|
-
|
|
64
|
-
Add and remove a single tag
|
|
65
|
-
|
|
66
|
-
```ruby
|
|
67
|
-
@user.tag_list.add("awesome") # add a single tag. alias for <<
|
|
68
|
-
@user.tag_list.remove("awesome") # remove a single tag
|
|
69
|
-
@user.save # save to persist tag_list
|
|
70
|
-
```
|
|
71
|
-
|
|
72
|
-
Add and remove multiple tags in an array
|
|
73
|
-
|
|
74
|
-
```ruby
|
|
75
|
-
@user.tag_list.add("awesome", "slick")
|
|
76
|
-
@user.tag_list.remove("awesome", "slick")
|
|
77
|
-
@user.save
|
|
78
|
-
```
|
|
79
|
-
|
|
80
|
-
You can also add and remove tags in format of String. This would
|
|
81
|
-
be convenient in some cases such as handling tag input param in a String.
|
|
82
|
-
|
|
83
|
-
Pay attention you need to add `parse: true` as option in this case.
|
|
84
|
-
|
|
85
|
-
You may also want to take a look at delimiter in the string. The default
|
|
86
|
-
is comma `,` so you don't need to do anything here. However, if you made
|
|
87
|
-
a change on delimiter setting, make sure the string will match. See
|
|
88
|
-
[configuration](#configuration) for more about delimiter.
|
|
89
|
-
|
|
90
|
-
```ruby
|
|
91
|
-
@user.tag_list.add("awesome, slick", parse: true)
|
|
92
|
-
@user.tag_list.remove("awesome, slick", parse: true)
|
|
93
|
-
```
|
|
94
|
-
|
|
95
|
-
You can also add and remove tags by direct assignment. Note this will
|
|
96
|
-
remove existing tags so use it with attention.
|
|
97
|
-
|
|
98
|
-
```ruby
|
|
99
|
-
@user.tag_list = "awesome, slick, hefty"
|
|
100
|
-
@user.save
|
|
101
|
-
@user.reload
|
|
102
|
-
@user.tags
|
|
103
|
-
=> [#<MakeTaggable::Tag id: 1, name: "awesome", taggings_count: 1>,
|
|
104
|
-
#<MakeTaggable::Tag id: 2, name: "slick", taggings_count: 1>,
|
|
105
|
-
#<MakeTaggable::Tag id: 3, name: "hefty", taggings_count: 1>]
|
|
106
|
-
```
|
|
107
|
-
|
|
108
|
-
With the defined context in model, you have multiple new methods at disposal
|
|
109
|
-
to manage and view the tags in the context. For example, with `:skill` context
|
|
110
|
-
these methods are added to the model: `skill_list`(and `skill_list.add`, `skill_list.remove`
|
|
111
|
-
`skill_list=`), `skills`(plural), `skill_counts`.
|
|
112
|
-
|
|
113
|
-
```ruby
|
|
114
|
-
@user.skill_list = "joking, clowning, boxing"
|
|
115
|
-
@user.save
|
|
116
|
-
@user.reload
|
|
117
|
-
@user.skills
|
|
118
|
-
=> [#<MakeTaggable::Tag id: 1, name: "joking", taggings_count: 1>,
|
|
119
|
-
#<MakeTaggable::Tag id: 2, name: "clowning", taggings_count: 1>,
|
|
120
|
-
#<MakeTaggable::Tag id: 3, name: "boxing", taggings_count: 1>]
|
|
121
|
-
|
|
122
|
-
@user.skill_list.add("coding")
|
|
123
|
-
|
|
124
|
-
@user.skill_list
|
|
125
|
-
# => ["joking", "clowning", "boxing", "coding"]
|
|
126
|
-
|
|
127
|
-
@another_user = User.new(:name => "Alice")
|
|
128
|
-
@another_user.skill_list.add("clowning")
|
|
129
|
-
@another_user.save
|
|
130
|
-
|
|
131
|
-
User.skill_counts
|
|
132
|
-
=> [#<MakeTaggable::Tag id: 1, name: "joking", taggings_count: 1>,
|
|
133
|
-
#<MakeTaggable::Tag id: 2, name: "clowning", taggings_count: 2>,
|
|
134
|
-
#<MakeTaggable::Tag id: 3, name: "boxing", taggings_count: 1>]
|
|
135
|
-
```
|
|
136
|
-
|
|
137
|
-
To preserve the order in which tags are created use `acts_as_ordered_taggable`:
|
|
138
|
-
|
|
139
|
-
```ruby
|
|
140
|
-
class User < ActiveRecord::Base
|
|
141
|
-
# Alias for acts_as_ordered_taggable_on :tags
|
|
142
|
-
acts_as_ordered_taggable
|
|
143
|
-
acts_as_ordered_taggable_on :skills, :interests
|
|
144
|
-
end
|
|
145
|
-
|
|
146
|
-
@user = User.new(:name => "Bobby")
|
|
147
|
-
@user.tag_list = "east, south"
|
|
148
|
-
@user.save
|
|
149
|
-
|
|
150
|
-
@user.tag_list = "north, east, south, west"
|
|
151
|
-
@user.save
|
|
152
|
-
|
|
153
|
-
@user.reload
|
|
154
|
-
@user.tag_list # => ["north", "east", "south", "west"]
|
|
155
|
-
```
|
|
156
|
-
|
|
157
|
-
### Finding most or least used tags
|
|
158
|
-
|
|
159
|
-
You can find the most or least used tags by using:
|
|
160
|
-
|
|
161
|
-
```ruby
|
|
162
|
-
MakeTaggable::Tag.most_used
|
|
163
|
-
MakeTaggable::Tag.least_used
|
|
164
|
-
```
|
|
165
|
-
|
|
166
|
-
You can also filter the results by passing the method a limit, however the default limit is 20.
|
|
167
|
-
|
|
168
|
-
```ruby
|
|
169
|
-
MakeTaggable::Tag.most_used(10)
|
|
170
|
-
MakeTaggable::Tag.least_used(10)
|
|
171
|
-
```
|
|
172
|
-
|
|
173
|
-
### Finding Tagged Objects
|
|
174
|
-
|
|
175
|
-
MakeTaggable uses scopes to create an association for tags.
|
|
176
|
-
This way you can mix and match to filter down your results.
|
|
177
|
-
|
|
178
|
-
```ruby
|
|
179
|
-
class User < ActiveRecord::Base
|
|
180
|
-
make_taggable :tags, :skills
|
|
181
|
-
scope :by_join_date, order("created_at DESC")
|
|
182
|
-
end
|
|
183
|
-
|
|
184
|
-
User.tagged_with("awesome").by_join_date
|
|
185
|
-
User.tagged_with("awesome").by_join_date.paginate(:page => params[:page], :per_page => 20)
|
|
186
|
-
|
|
187
|
-
# Find users that matches all given tags:
|
|
188
|
-
# NOTE: This only matches users that have the exact set of specified tags. If a user has additional tags, they are not returned.
|
|
189
|
-
User.tagged_with(["awesome", "cool"], :match_all => true)
|
|
190
|
-
|
|
191
|
-
# Find users with any of the specified tags:
|
|
192
|
-
User.tagged_with(["awesome", "cool"], :any => true)
|
|
193
|
-
|
|
194
|
-
# Find users that have not been tagged with awesome or cool:
|
|
195
|
-
User.tagged_with(["awesome", "cool"], :exclude => true)
|
|
196
|
-
|
|
197
|
-
# Find users with any of the tags based on context:
|
|
198
|
-
User.tagged_with(['awesome', 'cool'], :on => :tags, :any => true).tagged_with(['smart', 'shy'], :on => :skills, :any => true)
|
|
199
|
-
```
|
|
200
|
-
|
|
201
|
-
You can also use `:wild => true` option along with `:any` or `:exclude` option. It will be looking for `%awesome%` and `%cool%` in SQL.
|
|
202
|
-
|
|
203
|
-
__Tip:__ `User.tagged_with([])` or `User.tagged_with('')` will return `[]`, an empty set of records.
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
### Relationships
|
|
207
|
-
|
|
208
|
-
You can find objects of the same type based on similar tags on certain contexts.
|
|
209
|
-
Also, objects will be returned in descending order based on the total number of
|
|
210
|
-
matched tags.
|
|
211
|
-
|
|
212
|
-
```ruby
|
|
213
|
-
@bobby = User.find_by_name("Bobby")
|
|
214
|
-
@bobby.skill_list # => ["jogging", "diving"]
|
|
215
|
-
|
|
216
|
-
@frankie = User.find_by_name("Frankie")
|
|
217
|
-
@frankie.skill_list # => ["hacking"]
|
|
218
|
-
|
|
219
|
-
@tom = User.find_by_name("Tom")
|
|
220
|
-
@tom.skill_list # => ["hacking", "jogging", "diving"]
|
|
221
|
-
|
|
222
|
-
@tom.find_related_skills # => [<User name="Bobby">, <User name="Frankie">]
|
|
223
|
-
@bobby.find_related_skills # => [<User name="Tom">]
|
|
224
|
-
@frankie.find_related_skills # => [<User name="Tom">]
|
|
225
|
-
```
|
|
226
|
-
|
|
227
|
-
### Dynamic Tag Contexts
|
|
228
|
-
|
|
229
|
-
In addition to the generated tag contexts in the definition, it is also possible
|
|
230
|
-
to allow for dynamic tag contexts (this could be user generated tag contexts!)
|
|
231
|
-
|
|
232
|
-
```ruby
|
|
233
|
-
@user = User.new(:name => "Bobby")
|
|
234
|
-
@user.set_tag_list_on(:customs, "same, as, tag, list")
|
|
235
|
-
@user.tag_list_on(:customs) # => ["same", "as", "tag", "list"]
|
|
236
|
-
@user.save
|
|
237
|
-
@user.tags_on(:customs) # => [<Tag name='same'>,...]
|
|
238
|
-
@user.tag_counts_on(:customs)
|
|
239
|
-
User.tagged_with("same", :on => :customs) # => [@user]
|
|
240
|
-
```
|
|
241
|
-
|
|
242
|
-
### Tag Parsers
|
|
243
|
-
|
|
244
|
-
If you want to change how tags are parsed, you can define your own implementation:
|
|
245
|
-
|
|
246
|
-
```ruby
|
|
247
|
-
class MyParser < MakeTaggable::GenericParser
|
|
248
|
-
def parse
|
|
249
|
-
MakeTaggable::TagList.new.tap do |tag_list|
|
|
250
|
-
tag_list.add @tag_list.split('|')
|
|
251
|
-
end
|
|
252
|
-
end
|
|
253
|
-
end
|
|
254
|
-
```
|
|
255
|
-
|
|
256
|
-
Now you can use this parser, passing it as parameter:
|
|
257
|
-
|
|
258
|
-
```ruby
|
|
259
|
-
@user = User.new(:name => "Bobby")
|
|
260
|
-
@user.tag_list = "east, south"
|
|
261
|
-
@user.tag_list.add("north|west", parser: MyParser)
|
|
262
|
-
@user.tag_list # => ["north", "east", "south", "west"]
|
|
263
|
-
|
|
264
|
-
# Or also:
|
|
265
|
-
@user.tag_list.parser = MyParser
|
|
266
|
-
@user.tag_list.add("north|west")
|
|
267
|
-
@user.tag_list # => ["north", "east", "south", "west"]
|
|
268
|
-
```
|
|
269
|
-
|
|
270
|
-
Or change it globally:
|
|
271
|
-
|
|
272
|
-
```ruby
|
|
273
|
-
MakeTaggable.default_parser = MyParser
|
|
274
|
-
@user = User.new(:name => "Bobby")
|
|
275
|
-
@user.tag_list = "east|south"
|
|
276
|
-
@user.tag_list # => ["east", "south"]
|
|
277
|
-
```
|
|
278
|
-
|
|
279
|
-
### Tag Ownership
|
|
280
|
-
|
|
281
|
-
Tags can have owners:
|
|
34
|
+
## Quick start
|
|
282
35
|
|
|
283
36
|
```ruby
|
|
284
|
-
class
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
class Photo < ActiveRecord::Base
|
|
289
|
-
make_taggable :locations
|
|
37
|
+
class Book < ApplicationRecord
|
|
38
|
+
make_taggable # the :tags context
|
|
39
|
+
make_taggable :genres # and one of your own
|
|
290
40
|
end
|
|
291
|
-
|
|
292
|
-
@some_user.tag(@some_photo, :with => "paris, normandy", :on => :locations)
|
|
293
|
-
@some_user.owned_taggings
|
|
294
|
-
@some_user.owned_tags
|
|
295
|
-
Photo.tagged_with("paris", :on => :locations, :owned_by => @some_user)
|
|
296
|
-
@some_photo.locations_from(@some_user) # => ["paris", "normandy"]
|
|
297
|
-
@some_photo.owner_tags_on(@some_user, :locations) # => [#<MakeTaggable::Tag id: 1, name: "paris">...]
|
|
298
|
-
@some_photo.owner_tags_on(nil, :locations) # => Ownerships equivalent to saying @some_photo.locations
|
|
299
|
-
@some_user.tag(@some_photo, :with => "paris, normandy", :on => :locations, :skip_save => true) #won't save @some_photo object
|
|
300
41
|
```
|
|
301
42
|
|
|
302
|
-
#### Working with Owned Tags
|
|
303
|
-
Note that `tag_list` only returns tags whose taggings do not have an owner. Continuing from the above example:
|
|
304
43
|
```ruby
|
|
305
|
-
|
|
306
|
-
```
|
|
307
|
-
To retrieve all tags of an object (regardless of ownership) or if only one owner can tag the object, use `all_tags_list`.
|
|
44
|
+
book = Book.create!(title: "Dune", tag_list: "sci-fi, classic")
|
|
308
45
|
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
```ruby
|
|
314
|
-
def add_owned_tag
|
|
315
|
-
@some_item = Item.find(params[:id])
|
|
316
|
-
owned_tag_list = @some_item.all_tags_list - @some_item.tag_list
|
|
317
|
-
owned_tag_list += [(params[:tag])]
|
|
318
|
-
@tag_owner.tag(@some_item, :with => stringify(owned_tag_list), :on => :tags)
|
|
319
|
-
@some_item.save
|
|
320
|
-
end
|
|
46
|
+
book.tag_list # => ["sci-fi", "classic"]
|
|
47
|
+
book.tag_list.add("desert")
|
|
48
|
+
book.tag_list.remove("classic")
|
|
49
|
+
book.save
|
|
321
50
|
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
end
|
|
325
|
-
```
|
|
326
|
-
##### Removing owned tags
|
|
327
|
-
Similarly as above, removing will be as follows:
|
|
328
|
-
```ruby
|
|
329
|
-
def remove_owned_tag
|
|
330
|
-
@some_item = Item.find(params[:id])
|
|
331
|
-
owned_tag_list = @some_item.all_tags_list - @some_item.tag_list
|
|
332
|
-
owned_tag_list -= [(params[:tag])]
|
|
333
|
-
@tag_owner.tag(@some_item, :with => stringify(owned_tag_list), :on => :tags)
|
|
334
|
-
@some_item.save
|
|
335
|
-
end
|
|
51
|
+
book.genre_list = "science fiction"
|
|
52
|
+
book.save
|
|
336
53
|
```
|
|
337
54
|
|
|
338
|
-
|
|
55
|
+
Find them again:
|
|
339
56
|
|
|
340
57
|
```ruby
|
|
341
|
-
|
|
342
|
-
|
|
58
|
+
Book.tagged_with("sci-fi") # carries this tag
|
|
59
|
+
Book.tagged_with(["sci-fi", "desert"]) # carries both
|
|
60
|
+
Book.tagged_with(["sci-fi", "fantasy"], any: true) # carries either
|
|
61
|
+
Book.tagged_with(["sci-fi"], exclude: true) # carries neither
|
|
343
62
|
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
@bobby.skill_list = "swimming"
|
|
348
|
-
@bobby.changes.should == {"skill_list"=>["jogging, diving", ["swimming"]]}
|
|
349
|
-
@bobby.skill_list_changed? #=> true
|
|
350
|
-
|
|
351
|
-
@bobby.skill_list_change.should == ["jogging, diving", ["swimming"]]
|
|
63
|
+
Book.tag_counts_on(:genres) # tags with usage counts
|
|
64
|
+
Book.top_genres(10)
|
|
352
65
|
```
|
|
353
66
|
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
To construct tag clouds, the frequency of each tag needs to be calculated.
|
|
357
|
-
Because we specified `make_taggable` on the `User` class, we can
|
|
358
|
-
get a calculation of all the tag counts by using `User.tag_counts_on(:customs)`. But what if we wanted a tag count for
|
|
359
|
-
a single user's posts? To achieve this we call tag_counts on the association:
|
|
67
|
+
Tags are ordinary attributes as far as your controller is concerned:
|
|
360
68
|
|
|
361
69
|
```ruby
|
|
362
|
-
|
|
70
|
+
params.expect(book: [:title, :tag_list])
|
|
363
71
|
```
|
|
364
72
|
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
Here is an example that generates a tag cloud.
|
|
368
|
-
|
|
369
|
-
Helper:
|
|
370
|
-
|
|
371
|
-
```ruby
|
|
372
|
-
module PostsHelper
|
|
373
|
-
include MakeTaggable::TagsHelper
|
|
374
|
-
end
|
|
375
|
-
```
|
|
73
|
+
## Documentation
|
|
376
74
|
|
|
377
|
-
|
|
75
|
+
| | |
|
|
76
|
+
|---|---|
|
|
77
|
+
| [Getting started](docs/getting-started.md) | Install, first tagged model, reading and writing |
|
|
78
|
+
| [Tag contexts](docs/contexts.md) | Multiple contexts, ordered tags, contexts created at runtime |
|
|
79
|
+
| [Querying](docs/querying.md) | Every `tagged_with` option, counting, related records |
|
|
80
|
+
| [Ownership](docs/ownership.md) | Taggers, owned tags, and why `tag_list` can look empty |
|
|
81
|
+
| [Parsers and delimiters](docs/parsers.md) | Custom parsers, delimiters, escaping |
|
|
82
|
+
| [Caching](docs/caching.md) | `cached_*_list` columns, and what they cost |
|
|
83
|
+
| [Tag clouds](docs/tag-clouds.md) | Counts and the `tag_cloud` helper |
|
|
84
|
+
| [Configuration](docs/configuration.md) | Every setting |
|
|
85
|
+
| [Database](docs/database.md) | Schema, indexes, per-adapter notes |
|
|
86
|
+
| [Migrating from acts-as-taggable-on](docs/migrating-from-aato.md) | Method and constant mapping |
|
|
378
87
|
|
|
379
|
-
|
|
380
|
-
class PostController < ApplicationController
|
|
381
|
-
def tag_cloud
|
|
382
|
-
@tags = Post.tag_counts_on(:tags)
|
|
383
|
-
end
|
|
384
|
-
end
|
|
385
|
-
```
|
|
88
|
+
API documentation is generated with YARD:
|
|
386
89
|
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
```erb
|
|
390
|
-
<% tag_cloud(@tags, %w(css1 css2 css3 css4)) do |tag, css_class| %>
|
|
391
|
-
<%= link_to tag.name, { :action => :tag, :id => tag.name }, :class => css_class %>
|
|
392
|
-
<% end %>
|
|
393
|
-
```
|
|
394
|
-
|
|
395
|
-
CSS:
|
|
396
|
-
|
|
397
|
-
```css
|
|
398
|
-
.css1 { font-size: 1.0em; }
|
|
399
|
-
.css2 { font-size: 1.2em; }
|
|
400
|
-
.css3 { font-size: 1.4em; }
|
|
401
|
-
.css4 { font-size: 1.6em; }
|
|
402
|
-
```
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
## Configuration
|
|
406
|
-
|
|
407
|
-
If you would like to remove unused tag objects after removing taggings, add:
|
|
408
|
-
|
|
409
|
-
```ruby
|
|
410
|
-
MakeTaggable.remove_unused_tags = true
|
|
411
|
-
```
|
|
412
|
-
|
|
413
|
-
If you want force tags to be saved downcased:
|
|
414
|
-
|
|
415
|
-
```ruby
|
|
416
|
-
MakeTaggable.force_lowercase = true
|
|
417
|
-
```
|
|
418
|
-
|
|
419
|
-
If you want tags to be saved parametrized (you can redefine to_param as well):
|
|
420
|
-
|
|
421
|
-
```ruby
|
|
422
|
-
MakeTaggable.force_parameterize = true
|
|
423
|
-
```
|
|
424
|
-
|
|
425
|
-
If you would like tags to be case-sensitive and not use LIKE queries for creation:
|
|
426
|
-
|
|
427
|
-
```ruby
|
|
428
|
-
MakeTaggable.strict_case_match = true
|
|
429
|
-
```
|
|
430
|
-
|
|
431
|
-
If you would like to have an exact match covering special characters with MySql:
|
|
432
|
-
|
|
433
|
-
```ruby
|
|
434
|
-
MakeTaggable.force_binary_collation = true
|
|
435
|
-
```
|
|
436
|
-
|
|
437
|
-
If you would like to specify table names:
|
|
438
|
-
|
|
439
|
-
```ruby
|
|
440
|
-
MakeTaggable.tags_table = 'aato_tags'
|
|
441
|
-
MakeTaggable.taggings_table = 'aato_taggings'
|
|
442
|
-
```
|
|
443
|
-
|
|
444
|
-
If you want to change the default delimiter (it defaults to ','). You can also pass in an array of delimiters such as ([',', '|']):
|
|
445
|
-
|
|
446
|
-
```ruby
|
|
447
|
-
MakeTaggable.delimiter = ','
|
|
90
|
+
```shell
|
|
91
|
+
bundle exec yard doc
|
|
448
92
|
```
|
|
449
93
|
|
|
450
|
-
*NOTE 1: SQLite by default can't upcase or downcase multibyte characters, resulting in unwanted behavior. Load the SQLite ICU extension for proper handle of such characters. [See docs](http://www.sqlite.org/src/artifact?ci=trunk&filename=ext/icu/README.txt)*
|
|
451
|
-
|
|
452
|
-
|
|
453
94
|
## Upgrading
|
|
454
95
|
|
|
455
|
-
|
|
96
|
+
See [UPGRADING.md](UPGRADING.md). Version 1.0 removes the `acts_as_*` method names and changes how
|
|
97
|
+
delimiters are escaped.
|
|
98
|
+
|
|
99
|
+
Install new migrations when upgrading:
|
|
456
100
|
|
|
457
101
|
```shell
|
|
458
102
|
rails make_taggable_engine:install:migrations
|
|
103
|
+
rails db:migrate
|
|
459
104
|
```
|
|
460
105
|
|
|
461
|
-
##
|
|
462
|
-
|
|
463
|
-
Version 0.7.x is compatible with Ruby 2.5 > and Rails 5.2 >
|
|
106
|
+
## Development
|
|
464
107
|
|
|
465
|
-
|
|
466
|
-
## Testing
|
|
467
|
-
|
|
468
|
-
MakeTaggable uses RSpec for its test coverage. Inside the gem directory, you can run the specs by following the steps below:
|
|
469
|
-
|
|
470
|
-
Install the rquired gems:
|
|
108
|
+
The test suite runs against bare Active Record — there is no dummy application to generate.
|
|
471
109
|
|
|
472
110
|
```shell
|
|
473
111
|
bundle install
|
|
112
|
+
bundle exec rake
|
|
474
113
|
```
|
|
475
114
|
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
```shell
|
|
479
|
-
bundle exec rake test_app
|
|
480
|
-
```
|
|
481
|
-
|
|
482
|
-
Run the spec tests against SQLite use the followiong command.
|
|
115
|
+
That uses in-memory SQLite. To run against another adapter, point it at a database:
|
|
483
116
|
|
|
484
117
|
```shell
|
|
485
|
-
bundle exec rake
|
|
118
|
+
DATABASE_ADAPTER=postgresql DATABASE_URL=postgres://localhost/make_taggable_test bundle exec rake
|
|
119
|
+
DATABASE_ADAPTER=mysql2 DATABASE_URL=mysql2://root@127.0.0.1/make_taggable_test bundle exec rake
|
|
486
120
|
```
|
|
487
121
|
|
|
488
|
-
|
|
122
|
+
Across every supported Rails version:
|
|
489
123
|
|
|
490
124
|
```shell
|
|
491
125
|
bundle exec appraisal install
|
|
492
|
-
|
|
493
126
|
bundle exec appraisal rake
|
|
494
127
|
```
|
|
495
128
|
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
Please use the following Standard Rb commands to format your code before creating a pull request:
|
|
499
|
-
|
|
500
|
-
Check for code errors:
|
|
129
|
+
Format with Standard before opening a pull request:
|
|
501
130
|
|
|
502
131
|
```shell
|
|
503
|
-
bundle exec standardrb
|
|
132
|
+
bundle exec standardrb --fix
|
|
504
133
|
```
|
|
505
134
|
|
|
506
|
-
|
|
135
|
+
Public API needs YARD documentation. `bundle exec yard stats --list-undoc` should report 100%.
|
|
507
136
|
|
|
508
|
-
|
|
509
|
-
bundle exec standardrb --fix
|
|
510
|
-
```
|
|
511
|
-
For more information please review the [Contributing](https://github.com/MatthewKennedy/make_taggable/blob/master/CONTRIBUTING.md) section.
|
|
137
|
+
See [CONTRIBUTING.md](CONTRIBUTING.md) for more.
|
|
512
138
|
|
|
513
|
-
|
|
514
|
-
List of valued contributors From Acts-As-Taggable-On: [Check them all](https://github.com/mbleigh/acts-as-taggable-on/contributors)
|
|
139
|
+
## Credits
|
|
515
140
|
|
|
141
|
+
MakeTaggable is a fork of [acts-as-taggable-on](https://github.com/mbleigh/acts-as-taggable-on) by
|
|
142
|
+
Michael Bleigh and Joost Baaij, with thanks to
|
|
143
|
+
[its contributors](https://github.com/mbleigh/acts-as-taggable-on/contributors).
|
|
516
144
|
|
|
517
145
|
## License
|
|
518
|
-
|
|
146
|
+
|
|
147
|
+
Available as open source under the terms of the [MIT License](LICENSE.md).
|
data/UPGRADING.md
CHANGED
|
@@ -1,5 +1,31 @@
|
|
|
1
|
-
|
|
1
|
+
Upgrading to MakeTaggable 1.0
|
|
2
|
+
|
|
3
|
+
This release renames the declaration methods and changes how delimiters are escaped.
|
|
4
|
+
|
|
5
|
+
1. Rename the declarations in your models:
|
|
6
|
+
|
|
7
|
+
acts_as_taggable -> make_taggable
|
|
8
|
+
acts_as_taggable_on :skills -> make_taggable :skills
|
|
9
|
+
acts_as_ordered_taggable -> make_ordered_taggable
|
|
10
|
+
acts_as_ordered_taggable_on :skills -> make_ordered_taggable :skills
|
|
11
|
+
acts_as_tagger -> make_tagger
|
|
12
|
+
|
|
13
|
+
Everything generated per context keeps its name: skill_list, skills,
|
|
14
|
+
skill_counts, top_skills, skills_from, find_related_skills.
|
|
15
|
+
|
|
16
|
+
2. If you configure a delimiter containing a regular expression
|
|
17
|
+
metacharacter, unescape it. Delimiters are now literal strings:
|
|
18
|
+
|
|
19
|
+
MakeTaggable.delimiter = ['\|'] -> MakeTaggable.delimiter = ["|"]
|
|
20
|
+
|
|
21
|
+
3. If you rely on `make_taggable` with no arguments adding no contexts,
|
|
22
|
+
note that it now tags on :tags.
|
|
23
|
+
|
|
24
|
+
4. Requirements are now Ruby 3.2 and Active Record 7.2 or newer.
|
|
25
|
+
|
|
26
|
+
Install any new migrations:
|
|
2
27
|
|
|
3
28
|
rails make_taggable_engine:install:migrations
|
|
29
|
+
rails db:migrate
|
|
4
30
|
|
|
5
|
-
|
|
31
|
+
Full notes: https://github.com/MatthewKennedy/make_taggable/blob/master/CHANGELOG.md
|