Inkwell
Inkwell provides a simple way to add social networking features (e.g., comments, reblogs, favorites, following/followers, communities and timelines) to your Ruby on Rails application.
Installation
To get Inkwell from RubyGems, put the following line in the Gemfile
.
gem 'inkwell'
Alternatively, you can get it from Github (This version may contain unfinished features).
gem 'inkwell', :git => 'git://github.com/salkar/inkwell.git'
After that, run bundle install
Next, get gem migrations:
$ rake inkwell:install:migrations
and rake db:migrate
them.
Upgrading
After upgrading Inkwell remember to get new migrations and migrate them.
$ rake inkwell:install:migrations
$ rake db:migrate
Usage
Favoriting features
Setup
Include relevant modules to models:
- add
include Inkwell::CanFavorite
to models which instances should be able to favorite other objects - add
include Inkwell::CanBeFavorited
to models which instances should be able to be added to favorites
For sample:
# app/models/user.rb
class User < ApplicationRecord
include Inkwell::CanFavorite
#...
end
# app/models/post.rb
class Post < ApplicationRecord
include Inkwell::CanBeFavorited
#...
end
Inkwell::CanFavorite usage
Inkwell::CanFavorite#favorite(obj)
user.favorite(post)
After that post
will appear in the user.favorites
. Also if user
sees post
in someone else's timelines (or blog, favorites, etc.),
post
will have favorited_in_timeline
attribute with true
value.
Inkwell::CanFavorite#unfavorite(obj)
user.unfavorite(post)
Rolls back favorite
effects.
Inkwell::CanFavorite#favorite?(obj)
user.favorite?(post)
#=> false
user.favorite(post)
#=> true
user.favorite?(post)
#=> true
Check that post
is added to favorites by user
.
Notice: if obj
passed to favorite
, unfavorite
or favorite?
does not
include Inkwell::CanBeFavorited
Inkwell::Errors::NotFavoritable
will
be raised
Inkwell::CanFavorite#favorites(for_viewer: nil, &block)
Return array of instances favorited by object.
user.favorites
#=> [#<Post>, #<Comment>, ...]
If favorites
used without block, all favorited objects will be
returned (without pagination, ordering, etc). In this case Array
is
returned not Relation
!
For perform operations on relation block should be used:
# Gemfile
gem 'kaminari'
# code
user.favorites do |relation|
relation.page(1).order('created_at DESC')
end
#=> [#<Post>, #<Comment>, ...]
Notice: relation
is relation of Inkwell::Favorite instances (internal
Inkwell model)
Notice: realization with block looks complicated, but it helps with solve troubles with many-to-many relations through other polymorphic relations on both sides.
If there is necessary to get each result's object with flags for another
user
(favorited_in_timeline
, reblogged_in_timeline
, etc.),
for_viewer
should be passed:
user.favorite(post)
user.favorite(other_post)
other_user.favorite(other_post)
result = user.favorites(for_viewer: other_user)
result.detect{|item| item == post}.favorited_in_timeline
#=> false
result.detect{|item| item == other_post}.favorited_in_timeline
#=> true
Inkwell::CanFavorite#favorites_count
post.favorited_by.each do |obj|
obj.favorites_count
end
Use favorites_count
(instead of obj.favorites.count
or
obj.inkwell_favorited.count
for sample) for prevent n+1
because
favorites_count
get counter from inkwell cache included in favorited_by
by default.
Inkwell::CanBeFavorited usage
Inkwell::CanBeFavorited#favorited_by?(subject)
post.favorited_by?(user)
#=> false
user.favorite(post)
#=> true
post.favorited_by?(user)
#=> true
Check that post
is added to favorites by user
.
Notice: if subject
does not include Inkwell::CanFavorite
Inkwell::Errors::CannotFavorite
will be raised
Inkwell::CanBeFavorited#favorited_count
user.favorites.each do |obj|
obj.favorited_count
end
Use favorited_count
(instead of obj.favorited_by.count
or
obj.inkwell_favorited.count
for sample) for prevent n+1
because
favorites_count
get counter from inkwell cache included in favorites
by default.
Inkwell::CanBeFavorited#favorited_by(&block)
Return array of instances who favorite this object.
post.favorited_by
#=> [#<User>, #<Community>, ...] # Array, NOT Relation
# Gemfile
gem 'kaminari'
# code
user.favorited_by do |relation|
# relation - Inkwell::Favorite relation
relation.page(1).order('created_at DESC')
end
#=> [#<User>, #<Community>, ...] # Array, NOT Relation
Notice: for more details see Inkwell::CanFavorite#favorites . It works the same way.
Blogging features
Setup
Include relevant modules to models:
- add
include Inkwell::CanBlogging
to models which instances should be able to add objects to their blog. - add
include Inkwell::CanBeBlogged
to models which instances should be able to be added to blogs.
For sample:
# app/models/user.rb
class User < ApplicationRecord
include Inkwell::CanBlogging
#...
end
# app/models/post.rb
class Post < ApplicationRecord
include Inkwell::CanBeBlogged
#...
end
To automatically add posts
to user
blog, you can do the following:
class Post < ApplicationRecord
include Inkwell::CanBeBlogged
#...
belongs_to :user
#...
validates :user, presence: true
#...
after_create :blog_filling
#...
private
def blog_filling
user.add_to_blog(self)
end
end
Inkwell::CanBlogging usage
Inkwell::CanBlogging#add_to_blog(obj)
user.add_to_blog(post)
After that post
will appear in the user.blog
.
Inkwell::CanBlogging#remove_from_blog(obj)
user.remove_from_blog(post)
Rolls back add_to_blog
effects.
Inkwell::CanBlogging#added_to_blog?(obj)
user.added_to_blog?(post)
#=> false
user.add_to_blog(post)
#=> true
user.added_to_blog?(post)
#=> true
Check that post
is added to user's
blog.
Notice: if obj
passed to add_to_blog
, remove_from_blog
or
added_to_blog?
does not include Inkwell::CanBeBlogged
Inkwell::Errors::NotBloggable
will be raised
Inkwell::CanBlogging#blog(for_viewer: nil, &block)
Return array of instances blogged and reblogged by object.
user.blogs
#=> [#<Post>, #<Comment>, ...] # array NOT relation
# Gemfile
gem 'kaminari'
# code
user.blogs do |relation|
# relation - Inkwell::BlogItem relation
relation.page(1).order('created_at DESC')
end
#=> [#<Post>, #<Comment>, ...]
Reblogged items has reblog_in_timeline
flag
user.add_to_blog(post)
user.reblog(other_post)
result = user.blogs
result.detect{|item| item == post}.reblog_in_timeline
#=> false
result.detect{|item| item == other_post}.reblog_in_timeline
#=> true
If there is necessary to get each result's object with flags for another
user
(reblogged_in_timeline
, favorited_in_timeline
, etc.),
for_viewer
should be passed:
user.add_to_blog(post)
user.add_to_blog(other_post)
other_user.reblog(other_post)
result = user.blog(for_viewer: other_user)
result.detect{|item| item == post}.reblogged_in_timeline
#=> false
result.detect{|item| item == other_post}.reblogged_in_timeline
#=> true
Notice: for more details see Inkwell::CanFavorite#favorites . It works the same way.
Inkwell::CanBlogging#blog_items_count
Return added to blog objects count (including reblogs).
user.blog_items_count
Use blog_items_count
for prevent n+1
.
Inkwell::CanBeBlogged usage
Inkwell::CanBeBlogged#blogged_by?(subject)
post.blogged_by?(user)
#=> false
user.add_to_blog(post)
#=> true
post.blogged_by?(user)
#=> true
Check that post
is added to user's
blog.
Notice: if subject
does not include Inkwell::CanBlogging
Inkwell::Errors::CannotBlogging
will be raised
Inkwell::CanBeFavorited#blogged_by
Return instance who add to blog this object (owner of this object).
user.add_to_blog(post)
post.blogged_by
#=> #<User> # user
Reblog features
Setup
Include relevant modules to models:
- add
include Inkwell::CanReblog
to models which instances should be able to reblog objects. If object is reblogged, it is added to subject's blog. - add
include Inkwell::CanBeReblogged
to models which instances should be able to be reblogged.
For sample:
# app/models/user.rb
class User < ApplicationRecord
include Inkwell::CanBlogging
include Inkwell::CanReblog
#...
end
# app/models/post.rb
class Post < ApplicationRecord
include Inkwell::CanBeBlogged
include Inkwell::CanBeReblogged
#...
end
Inkwell::CanReblog usage
Inkwell::CanReblog#reblog(obj)
user.reblog(post)
After that post
will appear in the user.blog
as reblog (reblog_in_timeline
flag).
Inkwell::CanReblog#unreblog(obj)
user.unreblog(post)
Rolls back reblog
effects.
Inkwell::CanReblog#reblog?(obj)
user.reblog?(post)
#=> false
user.reblog(post)
#=> true
user.reblog?(post)
#=> true
Check that post
is reblogged by user
and added to user's
blog.
Notice: if obj
passed to reblog
, unreblog
or
reblog?
does not include Inkwell::CanBeReblogged
Inkwell::Errors::NotRebloggable
will be raised
Inkwell::CanReblog#reblogs_count
Return reblogged objects count.
user.reblogs_count
Use reblogs_count
instead of obj.reblogs.count
or
obj.inkwell_reblogs.count
for sample for prevent n+1
.
Inkwell::CanBeReblogged usage
Inkwell::CanBeReblogged#reblogged_by?(subject)
post.reblogged_by?(user)
#=> false
user.reblog(post)
#=> true
post.reblogged_by?(user)
#=> true
Check that post
is added to users's
blog as reblog.
Notice: if subject
does not include Inkwell::CanReblog
Inkwell::Errors::CannotReblog
will be raised
Inkwell::CanBeReblogged#reblogged_count
user.blog.each do |obj|
obj.try(:reblogged_count) # try is not needed if all objects in blog are rebloggable
end
Use reblogged_count
for prevent n+1
.
Inkwell::CanBeReblogged#reblogged_by(&block)
Return array of instances who reblog this object.
post.reblogged_by
#=> [#<User>, #<Community>, ...] # Array, NOT Relation
# Gemfile
gem 'kaminari'
# code
user.reblogged_by do |relation|
# relation - Inkwell::BlogItem relation
relation.page(1).order('created_at DESC')
end
#=> [#<User>, #<Community>, ...] # Array, NOT Relation
Notice: for more details see Inkwell::CanFavorite#favorites . It works the same way.