All Projects → alexruperez → Tagging

alexruperez / Tagging

Licence: mit
🏷 Type-safe tags in Swift

Programming Languages

swift
15916 projects

Projects that are alternatives of or similar to Tagging

Redis Tag Cache
Cache and invalidate records in Redis with tags
Stars: ✭ 48 (-46.07%)
Mutual labels:  tags
Django Taggit Labels
Clickable label widget for django-taggit
Stars: ✭ 62 (-30.34%)
Mutual labels:  tags
React Categorized Tag Input
React.js component for making tag autocompletion inputs with categorized results.
Stars: ✭ 78 (-12.36%)
Mutual labels:  tags
Univeq
Safer universal equivalence (==) for Scala.
Stars: ✭ 55 (-38.2%)
Mutual labels:  type-safety
Io Ts Reporters
Error reporters for io-ts
Stars: ✭ 58 (-34.83%)
Mutual labels:  type-safety
Tagflowlayout
支持多选的自定义标签View,可展开收起,标签样式可自定义。
Stars: ✭ 68 (-23.6%)
Mutual labels:  tags
Laravel Tags
Add tags and taggable behaviour to your Laravel app
Stars: ✭ 1,026 (+1052.81%)
Mutual labels:  tags
Strict Variant
A realtime/embedded-friendly C++11 variant type which is never empty and prevents undesirable implicit conversions
Stars: ✭ 81 (-8.99%)
Mutual labels:  type-safety
Dzhtmltext
Delphi and Lazarus HTML Label component
Stars: ✭ 60 (-32.58%)
Mutual labels:  tags
Pfun
Functional, composable, asynchronous, type-safe Python.
Stars: ✭ 75 (-15.73%)
Mutual labels:  type-safety
Dry Validation
Validation library with type-safe schemas and rules
Stars: ✭ 1,087 (+1121.35%)
Mutual labels:  type-safety
Threadly
Type-safe thread-local storage in Swift
Stars: ✭ 58 (-34.83%)
Mutual labels:  type-safety
Redoflacs
Parallel BASH commandline FLAC compressor, verifier, organizer, analyzer, and retagger
Stars: ✭ 71 (-20.22%)
Mutual labels:  tags
Magic Type
🎩 Use Your TypeScript definitions at runtime. Powered by Manta Style.
Stars: ✭ 53 (-40.45%)
Mutual labels:  type-safety
Betterdiscord Plugins
Assorted small plugins for BetterDiscord
Stars: ✭ 79 (-11.24%)
Mutual labels:  tags
Typewiz
Automatically discover and add missing types in your TypeScript code
Stars: ✭ 1,026 (+1052.81%)
Mutual labels:  type-safety
Mailpile
A free & open modern, fast email client with user-friendly encryption and privacy features
Stars: ✭ 8,533 (+9487.64%)
Mutual labels:  tags
React Tagsinput
Highly customizable React component for inputing tags.
Stars: ✭ 1,241 (+1294.38%)
Mutual labels:  tags
Dilate
Nearly zero runtime object allocation powered by scalameta. Value class and Unboxed Tagged Type generation at compile-time.
Stars: ✭ 80 (-10.11%)
Mutual labels:  type-safety
Materialchipview
Material Chip view. Can be used as tags for categories, contacts or creating text clouds
Stars: ✭ 1,181 (+1226.97%)
Mutual labels:  tags

🏷 Tagging

Twitter Swift Swift Package Manager Compatible

Welcome to Tagging, a small library that makes it easy to create type-safe tags in Swift. Categorization are often very useful for our models, so leveraging the compiler to ensure that they're used in a correct manner can go a long way to making the model layer of an app or system more robust.

This library is strongly inspired by JohnSundell/🆔entity and mbleigh/acts-as-taggable-on, for theoretical information, check out "Type-safe identifiers in Swift" on Swift by Sundell.

Making types taggable

All you have to do to use Tagging is to make a model conform to Taggable, and give it an tags property, like this:

struct Article: Taggable {
    let tags: [Tag<Article>]
    let title: String
}

And just like that, the above Article tags are now type-safe! Thanks to Swift’s type inference capabilities, it’s also possible to implement an Taggable type’s tags simply by using Tags as its type:

struct Article: Taggable {
    let tags: Tags
    let title: String
}

The Tags type alias is automatically added for all Taggable types, which also makes it possible to refer to [Tag<Article>] as Article.Tags.

Customizing the raw type

Tag values are backed by strings by default, but that can easily be customized by giving an Taggable type a RawTag, but must be at least Hashable:

struct Article: Taggable {
    typealias RawTag = UUID

    let tags: Tags
    let title: String
}

The above Article tags are now backed by a UUID instead of a String.

Conveniences built-in

Even though Tagging is focused on type safety, it still offers several conveniences to help reduce verbosity. For example, if a Tag is backed by a raw value type that can be expressed by a String literal, so can the tags:

let article = Article(tags: ["foo", "bar"], title: "Example")

The same is also true for tags that are backend by a raw value type that can be expressed by Int literals:

let article = Article(tags: [7, 9], title: "Example")

Tag also becomes Codable, Hashable and Equatable whenever its raw value type conforms to one of those protocols.

Type safety

So how exactly does Tagging make tags more type-safe? First, when using Tagging, it no longer becomes possible to accidentally pass a tag for one type to an API that accepts an tag for another type. For example, this code won't compile when using Tagging:

articleManager.articles(withTags: user.tags)

The compiler will give us an error above, since we're trying to pass an [Tag<User>] value to a method that accepts an [Tag<Article>] - giving us much stronger type safety than when using plain values, like String or Int, as tag types.

Tagging also makes it impossible to accidentally declare tags properties of the wrong type. So the following won't compile either:

struct User: Tagging {
    let tags: [Tag<Article>]
}

The reason the above code will fail to compile is because Taggable requires types conforming to it to declare tags that are bound to the same type as the conformer, again providing an extra level of type safety.

Finding most or least used tags

You can find the most or least used tags by using:

taggableCollection.mostUsedTags()
taggableCollection.leastUsedTags()

You can also filter the results by passing the method a limit, however the default limit is 20.

taggableCollection.mostUsedTags(10)
taggableCollection.leastUsedTags(10)

Or directly get the raw values.

taggableCollection.mostUsedRawTags()
taggableCollection.leastUsedRawTags()

Finding tagged objects

NOTE: By default, find objects tagged with any of the specified tags.
taggableCollection.tagged(with: "foo")
taggableCollection.tagged(with: ["foo"])
taggableCollection.tagged(with: ["foo", "bar"])
taggableCollection.tagged(with: taggable.tags)

Find tagged objects that matches all given tags

NOTE: This only matches tagged objects that have the exact set of specified tags. If a tagged object has additional tags, they are not returned.
taggableCollection.tagged(with: ["foo", "bar"], match: .all)
taggableCollection.tagged(with: taggable.tags, match: .all)

Find tagged objects that have not been tagged with given tags

taggableCollection.tagged(with: ["foo", "bar"], match: .none)
taggableCollection.tagged(with: taggable.tags, match: .none)

Installation

Since Tagging is implemented within a single file!, the easiest way to use it is to simply drag and drop it into your Xcode project.

But if you wish to use a dependency manager, you can use the Swift Package Manager by declaring Tagging as a dependency in your Package.swift file:

.package(url: "https://github.com/alexruperez/Tagging", from: "0.1.0")

For more information, see the Swift Package Manager documentation.

Contributions & support

Tagging is developed completely in the open, and your contributions are more than welcome.

Before you start using Tagging in any of your projects, it’s highly recommended that you spend a few minutes familiarizing yourself with its documentation and internal implementation (it all fits in a single file!), so that you’ll be ready to tackle any issues or edge cases that you might encounter.

To learn more about the principles used to implement Tagging, check out "Type-safe identifiers in Swift" on Swift by Sundell.

This project does not come with GitHub Issues-based support, and users are instead encouraged to become active participants in its continued development — by fixing any bugs that they encounter, or improving the documentation wherever it’s found to be lacking.

If you wish to make a change, open a Pull Request — even if it just contains a draft of the changes you’re planning, or a test that reproduces an issue — and we can discuss it further from there.

Hope you’ll enjoy using Tagging! 😀

Note that the project description data, including the texts, logos, images, and/or trademarks, for each open source project belongs to its rightful owner. If you wish to add or remove any projects, please contact us at [email protected].