make_taggable 1.1.0 → 1.1.1
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 +15 -0
- data/CONTRIBUTING.md +6 -0
- data/README.md +45 -15
- data/docs/caching.md +1 -1
- data/docs/contexts.md +6 -1
- data/docs/getting-started.md +6 -2
- data/docs/querying.md +13 -10
- data/lib/make_taggable/version.rb +1 -1
- metadata +1 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 7d3a7c89a48d79f6d985b8290d88007368ecdf983789a7e4881662724a1060a9
|
|
4
|
+
data.tar.gz: dda60e219b50e10b8948b6b9b260e703d8815f43bd200b1c434875144ae68071
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 7aa7e8b6c7190cbc8fbdcaf54fd5f49bf8f877c3161c7466e7df98eefd8f14eaa208391b47fa5a328db563d489d5e9a6f82b3bfd4b0ce770cdedbf3423f958bc
|
|
7
|
+
data.tar.gz: 0e868727368e57e72fe627cbbc4b7a4dc2077e459d6ac9131732788fec26a88037bd7ed12cb86a35f3b8308b3df7fa238319c24628f39e698c073e7d0dd8fa68
|
data/CHANGELOG.md
CHANGED
|
@@ -5,6 +5,21 @@ All notable changes to this project are documented here.
|
|
|
5
5
|
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/), and this project
|
|
6
6
|
adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
7
7
|
|
|
8
|
+
## [1.1.1] - 2026-08-22
|
|
9
|
+
|
|
10
|
+
### Fixed
|
|
11
|
+
|
|
12
|
+
- Documentation examples used `params.expect` and `ActiveRecord::Migration[8.0]`, neither of which
|
|
13
|
+
exists on Active Record 7.2 -- the version the gem promises to support. Both are corrected, and
|
|
14
|
+
`spec/docs_spec.rb` now fails the build if either creeps back.
|
|
15
|
+
|
|
16
|
+
### Internal
|
|
17
|
+
|
|
18
|
+
- Added documentation checks to the suite: every Ruby block in the README and `docs/` must parse,
|
|
19
|
+
example migrations must declare a version the floor accepts, version-sensitive calls must be
|
|
20
|
+
shown alongside an alternative, and relative links must resolve. They run on every Rails version
|
|
21
|
+
in the matrix.
|
|
22
|
+
|
|
8
23
|
## [1.1.0] - 2026-08-22
|
|
9
24
|
|
|
10
25
|
### Added
|
data/CONTRIBUTING.md
CHANGED
|
@@ -64,6 +64,12 @@ Prose documentation lives in [docs/](docs). API documentation is YARD comments i
|
|
|
64
64
|
the style already there: a `##` opening line, a description, a blank line, then tags with real Ruby
|
|
65
65
|
types.
|
|
66
66
|
|
|
67
|
+
`spec/docs_spec.rb` holds the prose to the versions the gemspec promises. It checks that every Ruby
|
|
68
|
+
block parses, that no example declares a migration version newer than the supported floor, that
|
|
69
|
+
calls the floor does not have are shown alongside an alternative, and that every relative link
|
|
70
|
+
resolves. It runs with the rest of the suite, so it runs on every Rails version in the matrix --
|
|
71
|
+
including the oldest, which is where documentation written on the newest tends to break.
|
|
72
|
+
|
|
67
73
|
Build it locally with `bundle exec yard doc`.
|
|
68
74
|
|
|
69
75
|
## Releasing
|
data/README.md
CHANGED
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
# MakeTaggable
|
|
2
2
|
|
|
3
|
-
[](https://rubygems.org/gems/make_taggable)
|
|
4
|
+
[](https://rubygems.org/gems/make_taggable)
|
|
5
|
+
[](https://github.com/MatthewKennedy/make_taggable/actions/workflows/ci.yml)
|
|
5
6
|
[](https://github.com/MatthewKennedy/make_taggable/actions/workflows/standard-ci.yml)
|
|
6
7
|
|
|
7
8
|
Tagging for Active Record models, across any number of named contexts.
|
|
@@ -12,7 +13,7 @@ order they were added in, and be cached on the record for display.
|
|
|
12
13
|
|
|
13
14
|
## Requirements
|
|
14
15
|
|
|
15
|
-
| | |
|
|
16
|
+
| Component | Supported |
|
|
16
17
|
|---|---|
|
|
17
18
|
| Ruby | 3.2 or newer |
|
|
18
19
|
| Active Record | 7.2 or newer |
|
|
@@ -35,44 +36,73 @@ rails db:migrate
|
|
|
35
36
|
|
|
36
37
|
```ruby
|
|
37
38
|
class Book < ApplicationRecord
|
|
38
|
-
make_taggable # the :tags context
|
|
39
|
-
make_taggable :genres #
|
|
39
|
+
make_taggable # the :tags context, for free-form tags
|
|
40
|
+
make_taggable :genres # a context of your own, for a curated set
|
|
40
41
|
end
|
|
41
42
|
```
|
|
42
43
|
|
|
44
|
+
Each context is a separate set of tags, with its own list:
|
|
45
|
+
|
|
43
46
|
```ruby
|
|
44
|
-
book = Book.create!(title: "Dune",
|
|
47
|
+
book = Book.create!(title: "Dune", genre_list: "sci-fi, classic")
|
|
48
|
+
|
|
49
|
+
book.genre_list # => ["sci-fi", "classic"]
|
|
50
|
+
```
|
|
45
51
|
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
52
|
+
Add and remove individual tags. Nothing is written until you save:
|
|
53
|
+
|
|
54
|
+
```ruby
|
|
55
|
+
book.genre_list.add("space opera")
|
|
56
|
+
book.genre_list.remove("classic")
|
|
49
57
|
book.save
|
|
50
58
|
|
|
51
|
-
book.genre_list
|
|
59
|
+
book.genre_list # => ["sci-fi", "space opera"]
|
|
60
|
+
book.genres # => [#<MakeTaggable::Tag name: "sci-fi">, #<MakeTaggable::Tag name: "space opera">]
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
Assigning replaces the whole list, and the two contexts never touch each other:
|
|
64
|
+
|
|
65
|
+
```ruby
|
|
66
|
+
book.tag_list = "desert, chosen-one, re-read"
|
|
52
67
|
book.save
|
|
68
|
+
|
|
69
|
+
book.tag_list # => ["desert", "chosen-one", "re-read"]
|
|
70
|
+
book.genre_list # => ["sci-fi", "space opera"]
|
|
53
71
|
```
|
|
54
72
|
|
|
55
73
|
Find them again:
|
|
56
74
|
|
|
57
75
|
```ruby
|
|
58
76
|
Book.tagged_with("sci-fi") # carries this tag
|
|
59
|
-
Book.tagged_with(["sci-fi", "
|
|
77
|
+
Book.tagged_with(["sci-fi", "space opera"]) # carries both
|
|
60
78
|
Book.tagged_with(["sci-fi", "fantasy"], any: true) # carries either
|
|
61
|
-
Book.tagged_with(["
|
|
79
|
+
Book.tagged_with(["fantasy"], exclude: true) # carries neither
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
Scope a query to one context, and tags in the others stop counting:
|
|
83
|
+
|
|
84
|
+
```ruby
|
|
85
|
+
Book.tagged_with("sci-fi", on: :genres) # => [#<Book title: "Dune">]
|
|
86
|
+
Book.tagged_with("sci-fi", on: :tags) # => []
|
|
87
|
+
```
|
|
62
88
|
|
|
63
|
-
|
|
89
|
+
Counts, for tag clouds and "most used" lists:
|
|
90
|
+
|
|
91
|
+
```ruby
|
|
92
|
+
Book.tag_counts_on(:genres) # tags carrying a `count`
|
|
64
93
|
Book.top_genres(10)
|
|
65
94
|
```
|
|
66
95
|
|
|
67
96
|
Tags are ordinary attributes as far as your controller is concerned:
|
|
68
97
|
|
|
69
98
|
```ruby
|
|
70
|
-
params.expect(book: [:title, :tag_list])
|
|
99
|
+
params.expect(book: [:title, :tag_list]) # Rails 8
|
|
100
|
+
params.require(:book).permit(:title, :tag_list) # Rails 7.2
|
|
71
101
|
```
|
|
72
102
|
|
|
73
103
|
## Documentation
|
|
74
104
|
|
|
75
|
-
| | |
|
|
105
|
+
| Guide | Covers |
|
|
76
106
|
|---|---|
|
|
77
107
|
| [Getting started](docs/getting-started.md) | Install, first tagged model, reading and writing |
|
|
78
108
|
| [Tag contexts](docs/contexts.md) | Multiple contexts, ordered tags, contexts created at runtime |
|
data/docs/caching.md
CHANGED
|
@@ -10,7 +10,7 @@ There is no setting. Add a column named `cached_<singular context>_list` and cac
|
|
|
10
10
|
itself on for that context:
|
|
11
11
|
|
|
12
12
|
```ruby
|
|
13
|
-
class AddCachedTagListToBooks < ActiveRecord::Migration[
|
|
13
|
+
class AddCachedTagListToBooks < ActiveRecord::Migration[7.2]
|
|
14
14
|
def change
|
|
15
15
|
add_column :books, :cached_tag_list, :string
|
|
16
16
|
add_column :books, :cached_genre_list, :string
|
data/docs/contexts.md
CHANGED
|
@@ -46,10 +46,15 @@ Calling `make_taggable` again adds contexts rather than replacing them, which is
|
|
|
46
46
|
subclass extend its parent:
|
|
47
47
|
|
|
48
48
|
```ruby
|
|
49
|
+
class Book < ApplicationRecord
|
|
50
|
+
make_taggable
|
|
51
|
+
end
|
|
52
|
+
|
|
49
53
|
class Manual < Book
|
|
50
54
|
make_taggable :audiences
|
|
51
55
|
end
|
|
52
56
|
|
|
57
|
+
Book.tag_types # => [:tags]
|
|
53
58
|
Manual.tag_types # => [:tags, :audiences]
|
|
54
59
|
```
|
|
55
60
|
|
|
@@ -134,7 +139,7 @@ tags, `Market.count` returns every tag in the table, and reloading a record give
|
|
|
134
139
|
`MakeTaggable::Tag` back. Add the column to get real separation:
|
|
135
140
|
|
|
136
141
|
```ruby
|
|
137
|
-
class AddTypeToTags < ActiveRecord::Migration[
|
|
142
|
+
class AddTypeToTags < ActiveRecord::Migration[7.2]
|
|
138
143
|
def change
|
|
139
144
|
add_column MakeTaggable.tags_table, :type, :string
|
|
140
145
|
add_index MakeTaggable.tags_table, :type
|
data/docs/getting-started.md
CHANGED
|
@@ -83,15 +83,19 @@ class BooksController < ApplicationController
|
|
|
83
83
|
private
|
|
84
84
|
|
|
85
85
|
def book_params
|
|
86
|
-
params.expect(book: [:title, :tag_list])
|
|
86
|
+
params.expect(book: [:title, :tag_list]) # Rails 8
|
|
87
|
+
# params.require(:book).permit(:title, :tag_list) # Rails 7.2
|
|
87
88
|
end
|
|
88
89
|
end
|
|
89
90
|
```
|
|
90
91
|
|
|
92
|
+
`params.expect` arrived in Rails 8. On Rails 7.2 use `require` and `permit`, as commented above.
|
|
93
|
+
|
|
91
94
|
To accept an array of tags from a multi-select, permit it as one:
|
|
92
95
|
|
|
93
96
|
```ruby
|
|
94
|
-
params.expect(book: [:title, {tag_list: []}])
|
|
97
|
+
params.expect(book: [:title, {tag_list: []}]) # Rails 8
|
|
98
|
+
params.require(:book).permit(:title, tag_list: []) # Rails 7.2
|
|
95
99
|
```
|
|
96
100
|
|
|
97
101
|
## Find tagged records
|
data/docs/querying.md
CHANGED
|
@@ -6,18 +6,18 @@
|
|
|
6
6
|
pagination.
|
|
7
7
|
|
|
8
8
|
```ruby
|
|
9
|
-
|
|
9
|
+
Book.tagged_with("sci-fi").order(published_at: :desc).limit(20)
|
|
10
10
|
```
|
|
11
11
|
|
|
12
12
|
By default every tag given must be present:
|
|
13
13
|
|
|
14
14
|
```ruby
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
15
|
+
Book.tagged_with(["sci-fi", "classic"]) # carries sci-fi AND classic
|
|
16
|
+
Book.tagged_with(["sci-fi", "classic"], any: true) # carries sci-fi OR classic
|
|
17
|
+
Book.tagged_with(["sci-fi", "classic"], exclude: true) # carries NEITHER
|
|
18
18
|
```
|
|
19
19
|
|
|
20
|
-
Passing nothing matches nothing. `
|
|
20
|
+
Passing nothing matches nothing. `Book.tagged_with([])` and `Book.tagged_with("")` both return an
|
|
21
21
|
empty relation rather than every record — worth knowing when the tags come from user input.
|
|
22
22
|
|
|
23
23
|
### Options
|
|
@@ -27,7 +27,7 @@ empty relation rather than every record — worth knowing when the tags come fro
|
|
|
27
27
|
| `:any` | Match records carrying at least one of the tags |
|
|
28
28
|
| `:exclude` | Match records carrying none of the tags |
|
|
29
29
|
| `:match_all` | Match records carrying only these tags and no others |
|
|
30
|
-
| `:wild` | Match tags *containing* the given text, i.e. `%
|
|
30
|
+
| `:wild` | Match tags *containing* the given text, i.e. `%sci%` |
|
|
31
31
|
| `:on` | Restrict to one context |
|
|
32
32
|
| `:owned_by` | Restrict to tags applied by one tagger |
|
|
33
33
|
| `:order_by_matching_tag_count` | With `:any`, order by how many tags matched, most first |
|
|
@@ -37,15 +37,15 @@ empty relation rather than every record — worth knowing when the tags come fro
|
|
|
37
37
|
`:wild` combines with `:any` or `:exclude`:
|
|
38
38
|
|
|
39
39
|
```ruby
|
|
40
|
-
|
|
40
|
+
Book.tagged_with(["sci", "clas"], any: true, wild: true)
|
|
41
41
|
```
|
|
42
42
|
|
|
43
43
|
Contexts are matched one call at a time, so chain to combine them:
|
|
44
44
|
|
|
45
45
|
```ruby
|
|
46
|
-
|
|
47
|
-
.tagged_with(["
|
|
48
|
-
.tagged_with(["
|
|
46
|
+
Book
|
|
47
|
+
.tagged_with(["sci-fi", "fantasy"], on: :genres, any: true)
|
|
48
|
+
.tagged_with(["desert", "space"], on: :tags, any: true)
|
|
49
49
|
```
|
|
50
50
|
|
|
51
51
|
### Case sensitivity
|
|
@@ -105,6 +105,9 @@ noticeably cheaper on a large table.
|
|
|
105
105
|
|
|
106
106
|
## Related records
|
|
107
107
|
|
|
108
|
+
These examples switch to a `User` model tagged on `:skills` — sharing tags is easiest to picture
|
|
109
|
+
with people.
|
|
110
|
+
|
|
108
111
|
Records sharing tags with this one, ordered by how many tags matched:
|
|
109
112
|
|
|
110
113
|
```ruby
|