Implements vote / like / follow functionality for Ecto models in Elixir. Inspired from Acts as Votable gem in Ruby on Rails
Switch branches/tags
Nothing to show
Clone or download
Fetching latest commit…
Cannot retrieve the latest commit at this time.
Permalink
Failed to load latest commit information.
config Cache support, Code formatted, Introduced cleanup Sep 3, 2018
lib
priv/templates Initial Commit Sep 1, 2018
test Added Travis CI Sep 10, 2018
.formatter.exs Initial Commit Sep 1, 2018
.gitignore Initial Commit Sep 1, 2018
.travis.yml Fixed Travis Sep 10, 2018
LICENSE Cache support, Code formatted, Introduced cleanup Sep 3, 2018
README.md Update README.md Sep 10, 2018
mix.exs
mix.lock Added Travis CI Sep 10, 2018

README.md

travis

Votex

Implements 👍 vote / ❤️ like / follow functionality for Ecto models in Elixir

Inspired from Acts as Votable ⭐️ in Ruby on Rails

Features

  • Any model can be voted
  • Any model can vote
  • Supports self referential voting
  • Easy to understand syntax

Installation

Add Votex to your project dependencies mix.exs

defp deps do
  [{:votex, "~> 0.3.0"}]
end

Specify your root project's repo in config

config :votex, Votex.DB,
  repo: MyApp.Repo

Votex needs a table in DB to store votes information. Install votex and generate votex schema migration

mix deps.get
mix votex.gen.migration
mix ecto.migrate

Usage

Configure Models

defmodule User do
  use Ecto.Schema
  use Votex.Voter
end

defmodule Post do
  use Ecto.Schema
  use Votex.Votable
end

Vote / Unvote

post |> Post.vote_by user
user |> User.voted_for? post
# true
post |> Post.votes_for |> length
# 1

post |> Post.votes_for
[
  %{
    id: 1,
    votable_id: 3,
    votable_type: "posts",
    voter: %Sample.User{
      id: 5,
      name: "John"
    },
    voter_id: 5,
    voter_type: "users"
  }
]

post |> Post.unvote_by user

Self Referential Vote

defmodule User do
  use Ecto.Schema 
  use Votex.Voter
  use Votex.Votable
end

user2 |> User.vote_by user1
# {:ok, _}

Cleanup

Since polymorphic associations are not supported in Ecto and callbacks are deprecated, orphan votes need to be cleared when a parent entity is destroyed. Therefore, you need to call cleanup_votes when you delete a Voter or a Votable record.

# Delete user
Repo.delete(user) |> User.cleanup_votes

# Delete post
Repo.delete(post) |> Post.cleanup_votes

Cache Support

Some fields like total number of votes on a post can be cached in posts table to avoid extra calls to DB. Votex will update the field if present in schema.

defmodule Post do
  use Ecto.Schema
  use Votex.Votable

  schema "posts" do
    field(:cached_votes_for_total, :integer)
  end

  @fields ~w(cached_votes_for_total)a

  # Publicly accessible changeset for Votex to update field
  def changeset(post, attrs) do
    post
    |> cast(attrs, @fields)
    |> validate_required(@fields)
  end
end

The posts table will track total votes from now on

post |> Post.vote_by user
post = Repo.get(Post, 1)
post.cached_votes_for_total
# 5