Inter
Easily add arbitrary attributes to an ActiveRecord model on the fly, without the need of any extra new database columns or migrations.
Why?
Ever added a 5th boolean to a model just so you could keep track if something had happened to this user, article, etc? With Inter you can add any arbitrary attributes to any ActiveRecord model on the fly without the need to add yet another database migration. Instead all interactions are stored in a seperate table and hooked up using polymorphism. Using a simple DSL you can then quickly manipulate and query interactions.
Benefits:
- Cleaner models
- Simple and powerful DSL
- More lightweight than a full state machine
- Can store any value
Usage
Dependencies
- >= Ruby 2.0
Installation
Add the gem to your Gemfile.
gem "inter"
Then generate and run the database migrations.
rails generate inter:install
rake db:migrate
And finally define an ActiveRecord model as an interactable.
class Article < ActiveRecord::Base
include Inter::Actable
end
Basic usage
Instance methods
Setting a value on an Article is now easy. Just pick a key name and set it to a desired value.
# simple boolean setting and getting2
article.is_published! # sets the published interaction to true
article.isnt_published! # sets the published interaction to false
article.is_published? #=> false
# you can also combine keys
article.is_published_and_not_promoted! #=> nil
article.is_published_and_promoted? #=> false
article.is_published_and_not_promoted? #=> true
# more complex values
article.set :tags, [:ruby, :rails, :gem] # or article.set "tags", [:ruby, :rails, :gem]
article.get :tags #=> ["ruby", "rails", "gem"]
article.has? :tags #=> true
article.set :tags, nil
article.has? :tags #=> false
Class methods
You can query interactable objects in a similar fasion.
# similar to instance methods there are simple lookup methods
Article.is_published #=> all articles for which published == true
Article.isnt_published #=> all articles for which published != true
# again you can combine interactions
Article.is_published_and_promoted #=> all promoted and published articles
Interaction history
One of the advantages of Interactions is that they are kept as a permanent log. Thefefore you can easily look up if an interaction has ever happened in the past.
# look up if an article has ever been published
article.was_published? #=> false
article.is_published! #=> nil
article.isnt_published! #=> nil
article.is_published? #=> false
article.was_published? #=> true
article.wasnt_published? #=> false
# again you can combine keys
article.was_published_and_promoted? #=> false
# to fully inspect the log you need to dig a bit deeper
# and access the interactions directly
article.history :published #=> all interactions that match this key
article.history "published"
article.history :published, :promoted
article.history ["published", "promoted"]
Advanced usage
A lot of the magic methods have underlying dumb methods that can be used too to further customize your needs.
Instance methods
article.is "published" #=> nil
article.is :published, :promoted #=> nil
article.is [:published, :not_promoted] #=> nil
article.is? :published, :promoted #=> false
article.is? [:published, :not_promoted] #=> true
article.get :promoted #=> true
Class methods
Article.inter(published: true) # loads all articles for which the current published state us true
Article.inter(published: true).first # lazy loads the latest article
# You can also get access to the raw interactions
Article.interactions(published: true)
Related lookup methods
Finally if 2 related models are both interactable then you can query related models by interaction status.
class Article < ActiveRecord::Base
include Inter::Actable
has_many :comments
end
class Comment < ActiveRecord::Base
include Inter::Actable
belongs_to :article
end
article.comments.first.is_spam! #=> nil
article.spam_comments #=> all comments with an interaction of "spam" set to true
article.not_spam_comments #=> all comments with an interaction of "spam" != true
article.spam_comments_ids #=> an array of IDs
article.spam_comments_count #=> the length of all the comments that match the criteria
# all of this maps down to the known pattern
article.comments.inter(spam: true)
Changelog
- 0.0.2 Copied over implementation
- 0.0.1 Gem skeleton
Contributors
- Cristiano Betta - Developer Evangelist - PayPal
Todos
- Add a generator
- Add tests
- Add option to disable history
License
See LICENSE