mirror of
https://github.com/philomena-dev/philomena.git
synced 2024-11-23 20:18:00 +01:00
elastix and elasticsearch binding
This commit is contained in:
parent
962c681c8e
commit
aee3bbccc4
20 changed files with 585 additions and 19 deletions
|
@ -9,6 +9,7 @@ use Mix.Config
|
||||||
|
|
||||||
config :philomena,
|
config :philomena,
|
||||||
ecto_repos: [Philomena.Repo],
|
ecto_repos: [Philomena.Repo],
|
||||||
|
elasticsearch_url: "http://localhost:9200",
|
||||||
password_pepper: "dn2e0EpZrvBLoxUM3gfQveBhjf0bG/6/bYhrOyq3L3hV9hdo/bimJ+irbDWsuXLP",
|
password_pepper: "dn2e0EpZrvBLoxUM3gfQveBhjf0bG/6/bYhrOyq3L3hV9hdo/bimJ+irbDWsuXLP",
|
||||||
image_url_root: "/img"
|
image_url_root: "/img"
|
||||||
|
|
||||||
|
@ -21,6 +22,9 @@ config :philomena, :pow,
|
||||||
config :bcrypt_elixir,
|
config :bcrypt_elixir,
|
||||||
log_rounds: 12
|
log_rounds: 12
|
||||||
|
|
||||||
|
config :elastix,
|
||||||
|
json_codec: Jason
|
||||||
|
|
||||||
# Configures the endpoint
|
# Configures the endpoint
|
||||||
config :philomena, PhilomenaWeb.Endpoint,
|
config :philomena, PhilomenaWeb.Endpoint,
|
||||||
url: [host: "localhost"],
|
url: [host: "localhost"],
|
||||||
|
|
|
@ -3,7 +3,6 @@ defmodule Philomena.Comments.Comment do
|
||||||
import Ecto.Changeset
|
import Ecto.Changeset
|
||||||
|
|
||||||
schema "comments" do
|
schema "comments" do
|
||||||
|
|
||||||
timestamps()
|
timestamps()
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
99
lib/philomena/elasticsearch.ex
Normal file
99
lib/philomena/elasticsearch.ex
Normal file
|
@ -0,0 +1,99 @@
|
||||||
|
defmodule Philomena.Elasticsearch do
|
||||||
|
defmacro __using__(opts) do
|
||||||
|
definition = Keyword.fetch!(opts, :definition)
|
||||||
|
index_name = Keyword.fetch!(opts, :index_name)
|
||||||
|
|
||||||
|
elastic_url = Application.get_env(:philomena, :elasticsearch_url)
|
||||||
|
|
||||||
|
quote do
|
||||||
|
alias Philomena.Repo
|
||||||
|
import Ecto.Query, warn: false
|
||||||
|
|
||||||
|
def create_index! do
|
||||||
|
Elastix.Index.create(
|
||||||
|
unquote(elastic_url),
|
||||||
|
unquote(index_name),
|
||||||
|
unquote(definition).mapping()
|
||||||
|
)
|
||||||
|
end
|
||||||
|
|
||||||
|
def delete_index! do
|
||||||
|
Elastix.Index.delete(unquote(elastic_url), unquote(index_name))
|
||||||
|
end
|
||||||
|
|
||||||
|
def index_document(doc) do
|
||||||
|
data = unquote(definition).as_json(doc)
|
||||||
|
|
||||||
|
Elastix.Document.index(unquote(elastic_url), unquote(index_name), ["_doc"], data.id, data)
|
||||||
|
end
|
||||||
|
|
||||||
|
def reindex(ecto_query, batch_size \\ 1000) do
|
||||||
|
ids =
|
||||||
|
ecto_query
|
||||||
|
|> exclude(:preload)
|
||||||
|
|> exclude(:order_by)
|
||||||
|
|> order_by(asc: :id)
|
||||||
|
|> select([m], m.id)
|
||||||
|
|> limit(^batch_size)
|
||||||
|
|> Repo.all()
|
||||||
|
|
||||||
|
reindex(ecto_query, batch_size, ids)
|
||||||
|
end
|
||||||
|
|
||||||
|
def reindex(ecto_query, batch_size, []), do: nil
|
||||||
|
|
||||||
|
def reindex(ecto_query, batch_size, ids) do
|
||||||
|
lines =
|
||||||
|
ecto_query
|
||||||
|
|> where([m], m.id in ^ids)
|
||||||
|
|> Repo.all()
|
||||||
|
|> Enum.flat_map(fn m ->
|
||||||
|
doc = unquote(definition).as_json(m)
|
||||||
|
|
||||||
|
[
|
||||||
|
%{index: %{_index: unquote(index_name), _type: "_doc", _id: doc.id}},
|
||||||
|
doc
|
||||||
|
]
|
||||||
|
end)
|
||||||
|
|
||||||
|
Elastix.Bulk.post(unquote(elastic_url), lines,
|
||||||
|
index: unquote(index_name),
|
||||||
|
httpoison_options: [timeout: 30_000]
|
||||||
|
)
|
||||||
|
|
||||||
|
ids =
|
||||||
|
ecto_query
|
||||||
|
|> exclude(:preload)
|
||||||
|
|> exclude(:order_by)
|
||||||
|
|> order_by(asc: :id)
|
||||||
|
|> where([m], m.id > ^Enum.max(ids))
|
||||||
|
|> select([m], m.id)
|
||||||
|
|> limit(^batch_size)
|
||||||
|
|> Repo.all()
|
||||||
|
|
||||||
|
reindex(ecto_query, batch_size, ids)
|
||||||
|
end
|
||||||
|
|
||||||
|
def search_results(elastic_query) do
|
||||||
|
{:ok, %{body: results, status_code: 200}} =
|
||||||
|
Elastix.Search.search(
|
||||||
|
unquote(elastic_url),
|
||||||
|
unquote(index_name),
|
||||||
|
["_doc"],
|
||||||
|
elastic_query
|
||||||
|
)
|
||||||
|
|
||||||
|
results
|
||||||
|
end
|
||||||
|
|
||||||
|
def search_records(elastic_query, ecto_query \\ __MODULE__) do
|
||||||
|
results = search_results(elastic_query)
|
||||||
|
|
||||||
|
ids = results["hits"]["hits"] |> Enum.map(&String.to_integer(&1["_id"]))
|
||||||
|
records = ecto_query |> where([m], m.id in ^ids) |> Repo.all()
|
||||||
|
|
||||||
|
records |> Enum.sort_by(&Enum.find_index(ids, fn el -> el == &1.id end))
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
104
lib/philomena/galleries.ex
Normal file
104
lib/philomena/galleries.ex
Normal file
|
@ -0,0 +1,104 @@
|
||||||
|
defmodule Philomena.Galleries do
|
||||||
|
@moduledoc """
|
||||||
|
The Galleries context.
|
||||||
|
"""
|
||||||
|
|
||||||
|
import Ecto.Query, warn: false
|
||||||
|
alias Philomena.Repo
|
||||||
|
|
||||||
|
alias Philomena.Galleries.Gallery
|
||||||
|
|
||||||
|
@doc """
|
||||||
|
Returns the list of galleries.
|
||||||
|
|
||||||
|
## Examples
|
||||||
|
|
||||||
|
iex> list_galleries()
|
||||||
|
[%Gallery{}, ...]
|
||||||
|
|
||||||
|
"""
|
||||||
|
def list_galleries do
|
||||||
|
Repo.all(Gallery)
|
||||||
|
end
|
||||||
|
|
||||||
|
@doc """
|
||||||
|
Gets a single gallery.
|
||||||
|
|
||||||
|
Raises `Ecto.NoResultsError` if the Gallery does not exist.
|
||||||
|
|
||||||
|
## Examples
|
||||||
|
|
||||||
|
iex> get_gallery!(123)
|
||||||
|
%Gallery{}
|
||||||
|
|
||||||
|
iex> get_gallery!(456)
|
||||||
|
** (Ecto.NoResultsError)
|
||||||
|
|
||||||
|
"""
|
||||||
|
def get_gallery!(id), do: Repo.get!(Gallery, id)
|
||||||
|
|
||||||
|
@doc """
|
||||||
|
Creates a gallery.
|
||||||
|
|
||||||
|
## Examples
|
||||||
|
|
||||||
|
iex> create_gallery(%{field: value})
|
||||||
|
{:ok, %Gallery{}}
|
||||||
|
|
||||||
|
iex> create_gallery(%{field: bad_value})
|
||||||
|
{:error, %Ecto.Changeset{}}
|
||||||
|
|
||||||
|
"""
|
||||||
|
def create_gallery(attrs \\ %{}) do
|
||||||
|
%Gallery{}
|
||||||
|
|> Gallery.changeset(attrs)
|
||||||
|
|> Repo.insert()
|
||||||
|
end
|
||||||
|
|
||||||
|
@doc """
|
||||||
|
Updates a gallery.
|
||||||
|
|
||||||
|
## Examples
|
||||||
|
|
||||||
|
iex> update_gallery(gallery, %{field: new_value})
|
||||||
|
{:ok, %Gallery{}}
|
||||||
|
|
||||||
|
iex> update_gallery(gallery, %{field: bad_value})
|
||||||
|
{:error, %Ecto.Changeset{}}
|
||||||
|
|
||||||
|
"""
|
||||||
|
def update_gallery(%Gallery{} = gallery, attrs) do
|
||||||
|
gallery
|
||||||
|
|> Gallery.changeset(attrs)
|
||||||
|
|> Repo.update()
|
||||||
|
end
|
||||||
|
|
||||||
|
@doc """
|
||||||
|
Deletes a Gallery.
|
||||||
|
|
||||||
|
## Examples
|
||||||
|
|
||||||
|
iex> delete_gallery(gallery)
|
||||||
|
{:ok, %Gallery{}}
|
||||||
|
|
||||||
|
iex> delete_gallery(gallery)
|
||||||
|
{:error, %Ecto.Changeset{}}
|
||||||
|
|
||||||
|
"""
|
||||||
|
def delete_gallery(%Gallery{} = gallery) do
|
||||||
|
Repo.delete(gallery)
|
||||||
|
end
|
||||||
|
|
||||||
|
@doc """
|
||||||
|
Returns an `%Ecto.Changeset{}` for tracking gallery changes.
|
||||||
|
|
||||||
|
## Examples
|
||||||
|
|
||||||
|
iex> change_gallery(gallery)
|
||||||
|
%Ecto.Changeset{source: %Gallery{}}
|
||||||
|
|
||||||
|
"""
|
||||||
|
def change_gallery(%Gallery{} = gallery) do
|
||||||
|
Gallery.changeset(gallery, %{})
|
||||||
|
end
|
||||||
|
end
|
24
lib/philomena/galleries/gallery.ex
Normal file
24
lib/philomena/galleries/gallery.ex
Normal file
|
@ -0,0 +1,24 @@
|
||||||
|
defmodule Philomena.Galleries.Gallery do
|
||||||
|
use Ecto.Schema
|
||||||
|
import Ecto.Changeset
|
||||||
|
|
||||||
|
schema "galleries" do
|
||||||
|
belongs_to :thumbnail, Philomena.Images.Image, source: :thumbnail_id
|
||||||
|
belongs_to :creator, Philomena.Users.User, source: :creator_id
|
||||||
|
|
||||||
|
field :title, :string
|
||||||
|
field :spoiler_warning, :string
|
||||||
|
field :description, :string
|
||||||
|
field :image_count, :integer
|
||||||
|
field :order_position_asc, :boolean
|
||||||
|
|
||||||
|
timestamps(inserted_at: :created_at)
|
||||||
|
end
|
||||||
|
|
||||||
|
@doc false
|
||||||
|
def changeset(gallery, attrs) do
|
||||||
|
gallery
|
||||||
|
|> cast(attrs, [])
|
||||||
|
|> validate_required([])
|
||||||
|
end
|
||||||
|
end
|
18
lib/philomena/galleries/interaction.ex
Normal file
18
lib/philomena/galleries/interaction.ex
Normal file
|
@ -0,0 +1,18 @@
|
||||||
|
defmodule Philomena.Galleries.Interaction do
|
||||||
|
use Ecto.Schema
|
||||||
|
import Ecto.Changeset
|
||||||
|
|
||||||
|
schema "gallery_interactions" do
|
||||||
|
belongs_to :gallery, Philomena.Galleries.Gallery
|
||||||
|
belongs_to :image, Philomena.Images.Image
|
||||||
|
|
||||||
|
field :position, :integer
|
||||||
|
end
|
||||||
|
|
||||||
|
@doc false
|
||||||
|
def changeset(interaction, attrs) do
|
||||||
|
interaction
|
||||||
|
|> cast(attrs, [])
|
||||||
|
|> validate_required([])
|
||||||
|
end
|
||||||
|
end
|
147
lib/philomena/images/elasticsearch.ex
Normal file
147
lib/philomena/images/elasticsearch.ex
Normal file
|
@ -0,0 +1,147 @@
|
||||||
|
defmodule Philomena.Images.Elasticsearch do
|
||||||
|
def mapping do
|
||||||
|
%{
|
||||||
|
settings: %{
|
||||||
|
index: %{
|
||||||
|
number_of_shards: 5,
|
||||||
|
max_result_window: 10_000_000
|
||||||
|
}
|
||||||
|
},
|
||||||
|
mappings: %{
|
||||||
|
_doc: %{
|
||||||
|
_all: %{enabled: false},
|
||||||
|
dynamic: false,
|
||||||
|
properties: %{
|
||||||
|
anonymous: %{type: "boolean"},
|
||||||
|
aspect_ratio: %{type: "float"},
|
||||||
|
comment_count: %{type: "integer"},
|
||||||
|
commenters: %{type: "keyword"},
|
||||||
|
created_at: %{type: "date"},
|
||||||
|
deleted_by_user: %{type: "keyword"},
|
||||||
|
deleted_by_user_id: %{type: "keyword"},
|
||||||
|
deletion_reason: %{type: "text", analyzer: "snowball"},
|
||||||
|
description: %{type: "text", analyzer: "snowball"},
|
||||||
|
downvoter_ids: %{type: "keyword"},
|
||||||
|
downvoters: %{type: "keyword"},
|
||||||
|
downvotes: %{type: "integer"},
|
||||||
|
faves: %{type: "integer"},
|
||||||
|
favourited_by_user_ids: %{type: "keyword"},
|
||||||
|
favourited_by_users: %{type: "keyword"},
|
||||||
|
file_name: %{type: "keyword"},
|
||||||
|
fingerprint: %{type: "keyword"},
|
||||||
|
first_seen_at: %{type: "date"},
|
||||||
|
height: %{type: "integer"},
|
||||||
|
hidden_by_user_ids: %{type: "keyword"},
|
||||||
|
hidden_by_users: %{type: "keyword"},
|
||||||
|
hidden_from_users: %{type: "keyword"},
|
||||||
|
id: %{type: "integer"},
|
||||||
|
ip: %{type: "ip"},
|
||||||
|
mime_type: %{type: "keyword"},
|
||||||
|
orig_sha512_hash: %{type: "keyword"},
|
||||||
|
original_format: %{type: "keyword"},
|
||||||
|
score: %{type: "integer"},
|
||||||
|
sha512_hash: %{type: "keyword"},
|
||||||
|
source_url: %{type: "keyword"},
|
||||||
|
tag_count: %{type: "integer"},
|
||||||
|
tag_ids: %{type: "keyword"},
|
||||||
|
tags: %{type: "text", analyzer: "keyword"},
|
||||||
|
true_uploader: %{type: "keyword"},
|
||||||
|
true_uploader_id: %{type: "keyword"},
|
||||||
|
updated_at: %{type: "date"},
|
||||||
|
uploader: %{type: "keyword"},
|
||||||
|
uploader_id: %{type: "keyword"},
|
||||||
|
upvoter_ids: %{type: "keyword"},
|
||||||
|
upvoters: %{type: "keyword"},
|
||||||
|
upvotes: %{type: "integer"},
|
||||||
|
user_id: %{type: "keyword"},
|
||||||
|
width: %{type: "integer"},
|
||||||
|
wilson_score: %{type: "float"},
|
||||||
|
galleries: %{
|
||||||
|
type: "nested",
|
||||||
|
properties: %{
|
||||||
|
id: %{type: "integer"},
|
||||||
|
position: %{type: "integer"}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
namespaced_tags: %{
|
||||||
|
properties: %{
|
||||||
|
name: %{type: "keyword"},
|
||||||
|
name_in_namespace: %{type: "keyword"},
|
||||||
|
namespace: %{type: "keyword"}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
end
|
||||||
|
|
||||||
|
def as_json(image) do
|
||||||
|
%{
|
||||||
|
id: image.id,
|
||||||
|
upvotes: image.upvotes_count,
|
||||||
|
downvotes: image.downvotes_count,
|
||||||
|
score: image.score,
|
||||||
|
faves: image.faves_count,
|
||||||
|
comment_count: image.comments_count,
|
||||||
|
width: image.image_width,
|
||||||
|
height: image.image_height,
|
||||||
|
tag_count: length(image.tags),
|
||||||
|
aspect_ratio: image.image_aspect_ratio,
|
||||||
|
wilson_score: wilson_score(image),
|
||||||
|
created_at: image.created_at,
|
||||||
|
updated_at: image.updated_at,
|
||||||
|
first_seen_at: image.first_seen_at,
|
||||||
|
ip: image.ip |> to_string,
|
||||||
|
tag_ids: image.tags |> Enum.map(& &1.id),
|
||||||
|
mime_type: image.image_mime_type,
|
||||||
|
uploader: if(!!image.user and !image.anonymous, do: String.downcase(image.user.name)),
|
||||||
|
true_uploader: if(!!image.user, do: String.downcase(image.user.name)),
|
||||||
|
source_url: image.source_url |> to_string |> String.downcase(),
|
||||||
|
file_name: image.image_name,
|
||||||
|
original_format: image.image_format,
|
||||||
|
fingerprint: image.fingerprint,
|
||||||
|
uploader_id: if(!!image.user_id and !image.anonymous, do: image.user_id),
|
||||||
|
true_uploader_id: image.user_id,
|
||||||
|
orig_sha512_hash: image.image_orig_sha512_hash,
|
||||||
|
sha512_hash: image.image_sha512_hash,
|
||||||
|
hidden_from_users: image.hidden_from_users,
|
||||||
|
anonymous: image.anonymous,
|
||||||
|
description: image.description,
|
||||||
|
deletion_reason: image.deletion_reason,
|
||||||
|
favourited_by_user_ids: image.favers |> Enum.map(& &1.id),
|
||||||
|
hidden_by_user_ids: image.hiders |> Enum.map(& &1.id),
|
||||||
|
upvoter_ids: image.upvoters |> Enum.map(& &1.id),
|
||||||
|
downvoter_ids: image.downvoters |> Enum.map(& &1.id),
|
||||||
|
deleted_by_user_id: image.deleter_id,
|
||||||
|
galleries:
|
||||||
|
image.gallery_interactions |> Enum.map(&%{id: &1.gallery_id, position: &1.position}),
|
||||||
|
namespaced_tags: %{
|
||||||
|
name: image.tags |> Enum.flat_map(&([&1] ++ &1.aliases)) |> Enum.map(& &1.name)
|
||||||
|
},
|
||||||
|
favourited_by_users: image.favers |> Enum.map(&String.downcase(&1.name)),
|
||||||
|
hidden_by_users: image.hiders |> Enum.map(&String.downcase(&1.name)),
|
||||||
|
upvoters: image.upvoters |> Enum.map(&String.downcase(&1.name)),
|
||||||
|
downvoters: image.downvoters |> Enum.map(&String.downcase(&1.name)),
|
||||||
|
deleted_by_user: if(!!image.deleter, do: image.deleter.name)
|
||||||
|
}
|
||||||
|
end
|
||||||
|
|
||||||
|
def wilson_score(%{upvotes_count: upvotes, downvotes_count: downvotes})
|
||||||
|
when upvotes > 0 or downvotes > 0 do
|
||||||
|
# Population size
|
||||||
|
n = (upvotes + downvotes) / 1
|
||||||
|
|
||||||
|
# Success proportion
|
||||||
|
p_hat = upvotes / n
|
||||||
|
|
||||||
|
# z and z^2 values for CI upper 99.5%
|
||||||
|
z = 2.57583
|
||||||
|
z2 = 6.634900189
|
||||||
|
|
||||||
|
(p_hat + z2 / (2 * n) - z * :math.sqrt((p_hat * (1 - p_hat) + z2 / (4 * n)) / n)) /
|
||||||
|
(1 + z2 / n)
|
||||||
|
end
|
||||||
|
|
||||||
|
def wilson_score(_), do: 0
|
||||||
|
end
|
19
lib/philomena/images/fave.ex
Normal file
19
lib/philomena/images/fave.ex
Normal file
|
@ -0,0 +1,19 @@
|
||||||
|
defmodule Philomena.Images.Fave do
|
||||||
|
use Ecto.Schema
|
||||||
|
import Ecto.Changeset
|
||||||
|
|
||||||
|
@primary_key false
|
||||||
|
|
||||||
|
schema "image_faves" do
|
||||||
|
belongs_to :user, Philomena.Users.User, primary_key: true
|
||||||
|
belongs_to :image, Philomena.Images.Image, primary_key: true
|
||||||
|
timestamps(inserted_at: :created_at, updated_at: false)
|
||||||
|
end
|
||||||
|
|
||||||
|
@doc false
|
||||||
|
def changeset(fave, attrs) do
|
||||||
|
fave
|
||||||
|
|> cast(attrs, [])
|
||||||
|
|> validate_required([])
|
||||||
|
end
|
||||||
|
end
|
19
lib/philomena/images/hide.ex
Normal file
19
lib/philomena/images/hide.ex
Normal file
|
@ -0,0 +1,19 @@
|
||||||
|
defmodule Philomena.Images.Hide do
|
||||||
|
use Ecto.Schema
|
||||||
|
import Ecto.Changeset
|
||||||
|
|
||||||
|
@primary_key false
|
||||||
|
|
||||||
|
schema "image_hides" do
|
||||||
|
belongs_to :user, Philomena.Users.User, primary_key: true
|
||||||
|
belongs_to :image, Philomena.Images.Image, primary_key: true
|
||||||
|
timestamps(inserted_at: :created_at, updated_at: false)
|
||||||
|
end
|
||||||
|
|
||||||
|
@doc false
|
||||||
|
def changeset(hide, attrs) do
|
||||||
|
hide
|
||||||
|
|> cast(attrs, [])
|
||||||
|
|> validate_required([])
|
||||||
|
end
|
||||||
|
end
|
|
@ -1,11 +1,26 @@
|
||||||
defmodule Philomena.Images.Image do
|
defmodule Philomena.Images.Image do
|
||||||
use Ecto.Schema
|
use Ecto.Schema
|
||||||
|
|
||||||
|
use Philomena.Elasticsearch,
|
||||||
|
definition: Philomena.Images.Elasticsearch,
|
||||||
|
index_name: "images"
|
||||||
|
|
||||||
import Ecto.Changeset
|
import Ecto.Changeset
|
||||||
|
|
||||||
schema "images" do
|
schema "images" do
|
||||||
belongs_to :user, Philomena.Users.User
|
belongs_to :user, Philomena.Users.User
|
||||||
belongs_to :deleter, Philomena.Users.User, source: :deleted_by_id
|
belongs_to :deleter, Philomena.Users.User, source: :deleted_by_id
|
||||||
many_to_many :tags, Philomena.Tags.Tag, join_through: "image_taggings"
|
has_many :upvotes, Philomena.Images.Vote, where: [up: true]
|
||||||
|
has_many :downvotes, Philomena.Images.Vote, where: [up: false]
|
||||||
|
has_many :faves, Philomena.Images.Fave
|
||||||
|
has_many :hides, Philomena.Images.Hide
|
||||||
|
has_many :taggings, Philomena.Images.Tagging
|
||||||
|
has_many :gallery_interactions, Philomena.Galleries.Interaction
|
||||||
|
has_many :tags, through: [:taggings, :tag]
|
||||||
|
has_many :upvoters, through: [:upvotes, :user]
|
||||||
|
has_many :downvoters, through: [:downvotes, :user]
|
||||||
|
has_many :favers, through: [:faves, :user]
|
||||||
|
has_many :hiders, through: [:hides, :user]
|
||||||
|
|
||||||
field :image, :string
|
field :image, :string
|
||||||
field :image_name, :string
|
field :image_name, :string
|
||||||
|
|
18
lib/philomena/images/tagging.ex
Normal file
18
lib/philomena/images/tagging.ex
Normal file
|
@ -0,0 +1,18 @@
|
||||||
|
defmodule Philomena.Images.Tagging do
|
||||||
|
use Ecto.Schema
|
||||||
|
import Ecto.Changeset
|
||||||
|
|
||||||
|
@primary_key false
|
||||||
|
|
||||||
|
schema "image_taggings" do
|
||||||
|
belongs_to :image, Philomena.Images.Image, primary_key: true
|
||||||
|
belongs_to :tag, Philomena.Tags.Tag, primary_key: true
|
||||||
|
end
|
||||||
|
|
||||||
|
@doc false
|
||||||
|
def changeset(tagging, attrs) do
|
||||||
|
tagging
|
||||||
|
|> cast(attrs, [])
|
||||||
|
|> validate_required([])
|
||||||
|
end
|
||||||
|
end
|
20
lib/philomena/images/vote.ex
Normal file
20
lib/philomena/images/vote.ex
Normal file
|
@ -0,0 +1,20 @@
|
||||||
|
defmodule Philomena.Images.Vote do
|
||||||
|
use Ecto.Schema
|
||||||
|
import Ecto.Changeset
|
||||||
|
|
||||||
|
@primary_key false
|
||||||
|
|
||||||
|
schema "image_votes" do
|
||||||
|
belongs_to :user, Philomena.Users.User, primary_key: true
|
||||||
|
belongs_to :image, Philomena.Images.Image, primary_key: true
|
||||||
|
field :up, :boolean
|
||||||
|
timestamps(inserted_at: :created_at, updated_at: false)
|
||||||
|
end
|
||||||
|
|
||||||
|
@doc false
|
||||||
|
def changeset(vote, attrs) do
|
||||||
|
vote
|
||||||
|
|> cast(attrs, [])
|
||||||
|
|> validate_required([])
|
||||||
|
end
|
||||||
|
end
|
|
@ -3,6 +3,9 @@ defmodule Philomena.Tags.Tag do
|
||||||
import Ecto.Changeset
|
import Ecto.Changeset
|
||||||
|
|
||||||
schema "tags" do
|
schema "tags" do
|
||||||
|
belongs_to :aliased_tag, Philomena.Tags.Tag, source: :aliased_tag_id
|
||||||
|
has_many :aliases, Philomena.Tags.Tag, foreign_key: :aliased_tag_id
|
||||||
|
|
||||||
field :slug, :string
|
field :slug, :string
|
||||||
field :name, :string
|
field :name, :string
|
||||||
field :category, :string
|
field :category, :string
|
||||||
|
|
|
@ -26,20 +26,21 @@ defmodule PhilomenaWeb.AppView do
|
||||||
months = abs(div(days, 30))
|
months = abs(div(days, 30))
|
||||||
years = abs(div(days, 365))
|
years = abs(div(days, 365))
|
||||||
|
|
||||||
words = cond do
|
words =
|
||||||
seconds < 45 -> String.replace(@time_strings[:seconds], "%d", to_string(seconds))
|
cond do
|
||||||
seconds < 90 -> String.replace(@time_strings[:minute], "%d", to_string(1))
|
seconds < 45 -> String.replace(@time_strings[:seconds], "%d", to_string(seconds))
|
||||||
minutes < 45 -> String.replace(@time_strings[:minutes], "%d", to_string(minutes))
|
seconds < 90 -> String.replace(@time_strings[:minute], "%d", to_string(1))
|
||||||
minutes < 90 -> String.replace(@time_strings[:hour], "%d", to_string(1))
|
minutes < 45 -> String.replace(@time_strings[:minutes], "%d", to_string(minutes))
|
||||||
hours < 24 -> String.replace(@time_strings[:hours], "%d", to_string(hours))
|
minutes < 90 -> String.replace(@time_strings[:hour], "%d", to_string(1))
|
||||||
hours < 42 -> String.replace(@time_strings[:day], "%d", to_string(1))
|
hours < 24 -> String.replace(@time_strings[:hours], "%d", to_string(hours))
|
||||||
days < 30 -> String.replace(@time_strings[:days], "%d", to_string(days))
|
hours < 42 -> String.replace(@time_strings[:day], "%d", to_string(1))
|
||||||
days < 45 -> String.replace(@time_strings[:month], "%d", to_string(1))
|
days < 30 -> String.replace(@time_strings[:days], "%d", to_string(days))
|
||||||
days < 365 -> String.replace(@time_strings[:months], "%d", to_string(months))
|
days < 45 -> String.replace(@time_strings[:month], "%d", to_string(1))
|
||||||
days < 548 -> String.replace(@time_strings[:year], "%d", to_string(1))
|
days < 365 -> String.replace(@time_strings[:months], "%d", to_string(months))
|
||||||
true -> String.replace(@time_strings[:years], "%d", to_string(years))
|
days < 548 -> String.replace(@time_strings[:year], "%d", to_string(1))
|
||||||
end
|
true -> String.replace(@time_strings[:years], "%d", to_string(years))
|
||||||
|
end
|
||||||
|
|
||||||
content_tag(:time, "#{words} #{relation}", datetime: time |> NaiveDateTime.to_iso8601())
|
content_tag(:time, "#{words} #{relation}", datetime: time |> NaiveDateTime.to_iso8601())
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
3
mix.exs
3
mix.exs
|
@ -48,7 +48,8 @@ defmodule Philomena.MixProject do
|
||||||
{:pow, "~> 1.0.11"},
|
{:pow, "~> 1.0.11"},
|
||||||
{:bcrypt_elixir, "~> 2.0"},
|
{:bcrypt_elixir, "~> 2.0"},
|
||||||
{:pot, "~> 0.10.1"},
|
{:pot, "~> 0.10.1"},
|
||||||
{:secure_compare, "~> 0.1.0"}
|
{:secure_compare, "~> 0.1.0"},
|
||||||
|
{:elastix, "~> 0.7.1"}
|
||||||
]
|
]
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
11
mix.lock
11
mix.lock
|
@ -1,5 +1,6 @@
|
||||||
%{
|
%{
|
||||||
"bcrypt_elixir": {:hex, :bcrypt_elixir, "2.0.3", "64e0792d5b5064391927bf3b8e436994cafd18ca2d2b76dea5c76e0adcf66b7c", [:make, :mix], [{:comeonin, "~> 5.1", [hex: :comeonin, repo: "hexpm", optional: false]}, {:elixir_make, "~> 0.4", [hex: :elixir_make, repo: "hexpm", optional: false]}], "hexpm"},
|
"bcrypt_elixir": {:hex, :bcrypt_elixir, "2.0.3", "64e0792d5b5064391927bf3b8e436994cafd18ca2d2b76dea5c76e0adcf66b7c", [:make, :mix], [{:comeonin, "~> 5.1", [hex: :comeonin, repo: "hexpm", optional: false]}, {:elixir_make, "~> 0.4", [hex: :elixir_make, repo: "hexpm", optional: false]}], "hexpm"},
|
||||||
|
"certifi": {:hex, :certifi, "2.5.1", "867ce347f7c7d78563450a18a6a28a8090331e77fa02380b4a21962a65d36ee5", [:rebar3], [{:parse_trans, "~>3.3", [hex: :parse_trans, repo: "hexpm", optional: false]}], "hexpm"},
|
||||||
"comeonin": {:hex, :comeonin, "5.1.2", "fbbbbbfcf0f0e9900c0336d16c8d462edf838ba1759577e29cc5fbd7c28a4540", [:mix], [], "hexpm"},
|
"comeonin": {:hex, :comeonin, "5.1.2", "fbbbbbfcf0f0e9900c0336d16c8d462edf838ba1759577e29cc5fbd7c28a4540", [:mix], [], "hexpm"},
|
||||||
"connection": {:hex, :connection, "1.0.4", "a1cae72211f0eef17705aaededacac3eb30e6625b04a6117c1b2db6ace7d5976", [:mix], [], "hexpm"},
|
"connection": {:hex, :connection, "1.0.4", "a1cae72211f0eef17705aaededacac3eb30e6625b04a6117c1b2db6ace7d5976", [:mix], [], "hexpm"},
|
||||||
"cowboy": {:hex, :cowboy, "2.6.3", "99aa50e94e685557cad82e704457336a453d4abcb77839ad22dbe71f311fcc06", [:rebar3], [{:cowlib, "~> 2.7.3", [hex: :cowlib, repo: "hexpm", optional: false]}, {:ranch, "~> 1.7.1", [hex: :ranch, repo: "hexpm", optional: false]}], "hexpm"},
|
"cowboy": {:hex, :cowboy, "2.6.3", "99aa50e94e685557cad82e704457336a453d4abcb77839ad22dbe71f311fcc06", [:rebar3], [{:cowlib, "~> 2.7.3", [hex: :cowlib, repo: "hexpm", optional: false]}, {:ranch, "~> 1.7.1", [hex: :ranch, repo: "hexpm", optional: false]}], "hexpm"},
|
||||||
|
@ -9,12 +10,19 @@
|
||||||
"ecto": {:hex, :ecto, "3.1.7", "fa21d06ef56cdc2fdaa62574e8c3ba34a2751d44ea34c30bc65f0728421043e5", [:mix], [{:decimal, "~> 1.6", [hex: :decimal, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: true]}], "hexpm"},
|
"ecto": {:hex, :ecto, "3.1.7", "fa21d06ef56cdc2fdaa62574e8c3ba34a2751d44ea34c30bc65f0728421043e5", [:mix], [{:decimal, "~> 1.6", [hex: :decimal, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: true]}], "hexpm"},
|
||||||
"ecto_network": {:hex, :ecto_network, "1.1.0", "7062004b9324ff13e50c02dab84877f8a55e06db9eabbf2d04bda21da6fc6e8a", [:mix], [{:ecto_sql, ">= 3.0.0", [hex: :ecto_sql, repo: "hexpm", optional: false]}, {:phoenix_html, ">= 0.0.0", [hex: :phoenix_html, repo: "hexpm", optional: true]}, {:postgrex, ">= 0.14.0", [hex: :postgrex, repo: "hexpm", optional: false]}], "hexpm"},
|
"ecto_network": {:hex, :ecto_network, "1.1.0", "7062004b9324ff13e50c02dab84877f8a55e06db9eabbf2d04bda21da6fc6e8a", [:mix], [{:ecto_sql, ">= 3.0.0", [hex: :ecto_sql, repo: "hexpm", optional: false]}, {:phoenix_html, ">= 0.0.0", [hex: :phoenix_html, repo: "hexpm", optional: true]}, {:postgrex, ">= 0.14.0", [hex: :postgrex, repo: "hexpm", optional: false]}], "hexpm"},
|
||||||
"ecto_sql": {:hex, :ecto_sql, "3.1.6", "1e80e30d16138a729c717f73dcb938590bcdb3a4502f3012414d0cbb261045d8", [:mix], [{:db_connection, "~> 2.0", [hex: :db_connection, repo: "hexpm", optional: false]}, {:ecto, "~> 3.1.0", [hex: :ecto, repo: "hexpm", optional: false]}, {:mariaex, "~> 0.9.1", [hex: :mariaex, repo: "hexpm", optional: true]}, {:myxql, "~> 0.2.0", [hex: :myxql, repo: "hexpm", optional: true]}, {:postgrex, "~> 0.14.0 or ~> 0.15.0", [hex: :postgrex, repo: "hexpm", optional: true]}, {:telemetry, "~> 0.4.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm"},
|
"ecto_sql": {:hex, :ecto_sql, "3.1.6", "1e80e30d16138a729c717f73dcb938590bcdb3a4502f3012414d0cbb261045d8", [:mix], [{:db_connection, "~> 2.0", [hex: :db_connection, repo: "hexpm", optional: false]}, {:ecto, "~> 3.1.0", [hex: :ecto, repo: "hexpm", optional: false]}, {:mariaex, "~> 0.9.1", [hex: :mariaex, repo: "hexpm", optional: true]}, {:myxql, "~> 0.2.0", [hex: :myxql, repo: "hexpm", optional: true]}, {:postgrex, "~> 0.14.0 or ~> 0.15.0", [hex: :postgrex, repo: "hexpm", optional: true]}, {:telemetry, "~> 0.4.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm"},
|
||||||
|
"elastix": {:hex, :elastix, "0.7.1", "8e199a764a0bc018e0a97afeea950a8069b988867d87f8d25ae121d8b3288612", [:mix], [{:httpoison, "~> 1.4", [hex: :httpoison, repo: "hexpm", optional: false]}, {:poison, "~> 3.1", [hex: :poison, repo: "hexpm", optional: true]}, {:retry, "~> 0.8", [hex: :retry, repo: "hexpm", optional: false]}], "hexpm"},
|
||||||
"elixir_make": {:hex, :elixir_make, "0.6.0", "38349f3e29aff4864352084fc736fa7fa0f2995a819a737554f7ebd28b85aaab", [:mix], [], "hexpm"},
|
"elixir_make": {:hex, :elixir_make, "0.6.0", "38349f3e29aff4864352084fc736fa7fa0f2995a819a737554f7ebd28b85aaab", [:mix], [], "hexpm"},
|
||||||
"file_system": {:hex, :file_system, "0.2.7", "e6f7f155970975789f26e77b8b8d8ab084c59844d8ecfaf58cbda31c494d14aa", [:mix], [], "hexpm"},
|
"file_system": {:hex, :file_system, "0.2.7", "e6f7f155970975789f26e77b8b8d8ab084c59844d8ecfaf58cbda31c494d14aa", [:mix], [], "hexpm"},
|
||||||
"gettext": {:hex, :gettext, "0.17.0", "abe21542c831887a2b16f4c94556db9c421ab301aee417b7c4fbde7fbdbe01ec", [:mix], [], "hexpm"},
|
"gettext": {:hex, :gettext, "0.17.0", "abe21542c831887a2b16f4c94556db9c421ab301aee417b7c4fbde7fbdbe01ec", [:mix], [], "hexpm"},
|
||||||
|
"hackney": {:hex, :hackney, "1.15.1", "9f8f471c844b8ce395f7b6d8398139e26ddca9ebc171a8b91342ee15a19963f4", [:rebar3], [{:certifi, "2.5.1", [hex: :certifi, repo: "hexpm", optional: false]}, {:idna, "6.0.0", [hex: :idna, repo: "hexpm", optional: false]}, {:metrics, "1.0.1", [hex: :metrics, repo: "hexpm", optional: false]}, {:mimerl, "~>1.1", [hex: :mimerl, repo: "hexpm", optional: false]}, {:ssl_verify_fun, "1.1.4", [hex: :ssl_verify_fun, repo: "hexpm", optional: false]}], "hexpm"},
|
||||||
|
"httpoison": {:hex, :httpoison, "1.5.1", "0f55b5b673b03c5c327dac7015a67cb571b99b631acc0bc1b0b98dcd6b9f2104", [:mix], [{:hackney, "~> 1.8", [hex: :hackney, repo: "hexpm", optional: false]}], "hexpm"},
|
||||||
|
"idna": {:hex, :idna, "6.0.0", "689c46cbcdf3524c44d5f3dde8001f364cd7608a99556d8fbd8239a5798d4c10", [:rebar3], [{:unicode_util_compat, "0.4.1", [hex: :unicode_util_compat, repo: "hexpm", optional: false]}], "hexpm"},
|
||||||
"jason": {:hex, :jason, "1.1.2", "b03dedea67a99223a2eaf9f1264ce37154564de899fd3d8b9a21b1a6fd64afe7", [:mix], [{:decimal, "~> 1.0", [hex: :decimal, repo: "hexpm", optional: true]}], "hexpm"},
|
"jason": {:hex, :jason, "1.1.2", "b03dedea67a99223a2eaf9f1264ce37154564de899fd3d8b9a21b1a6fd64afe7", [:mix], [{:decimal, "~> 1.0", [hex: :decimal, repo: "hexpm", optional: true]}], "hexpm"},
|
||||||
|
"metrics": {:hex, :metrics, "1.0.1", "25f094dea2cda98213cecc3aeff09e940299d950904393b2a29d191c346a8486", [:rebar3], [], "hexpm"},
|
||||||
"mime": {:hex, :mime, "1.3.1", "30ce04ab3175b6ad0bdce0035cba77bba68b813d523d1aac73d9781b4d193cf8", [:mix], [], "hexpm"},
|
"mime": {:hex, :mime, "1.3.1", "30ce04ab3175b6ad0bdce0035cba77bba68b813d523d1aac73d9781b4d193cf8", [:mix], [], "hexpm"},
|
||||||
|
"mimerl": {:hex, :mimerl, "1.2.0", "67e2d3f571088d5cfd3e550c383094b47159f3eee8ffa08e64106cdf5e981be3", [:rebar3], [], "hexpm"},
|
||||||
"neotoma": {:hex, :neotoma, "1.7.3", "d8bd5404b73273989946e4f4f6d529e5c2088f5fa1ca790b4dbe81f4be408e61", [:rebar], [], "hexpm"},
|
"neotoma": {:hex, :neotoma, "1.7.3", "d8bd5404b73273989946e4f4f6d529e5c2088f5fa1ca790b4dbe81f4be408e61", [:rebar], [], "hexpm"},
|
||||||
|
"parse_trans": {:hex, :parse_trans, "3.3.0", "09765507a3c7590a784615cfd421d101aec25098d50b89d7aa1d66646bc571c1", [:rebar3], [], "hexpm"},
|
||||||
"pbkdf2": {:hex, :pbkdf2, "2.0.0", "11c23279fded5c0027ab3996cfae77805521d7ef4babde2bd7ec04a9086cf499", [:rebar3], [], "hexpm"},
|
"pbkdf2": {:hex, :pbkdf2, "2.0.0", "11c23279fded5c0027ab3996cfae77805521d7ef4babde2bd7ec04a9086cf499", [:rebar3], [], "hexpm"},
|
||||||
"phoenix": {:hex, :phoenix, "1.4.9", "746d098e10741c334d88143d3c94cab1756435f94387a63441792e66ec0ee974", [:mix], [{:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: true]}, {:phoenix_pubsub, "~> 1.1", [hex: :phoenix_pubsub, repo: "hexpm", optional: false]}, {:plug, "~> 1.8.1 or ~> 1.9", [hex: :plug, repo: "hexpm", optional: false]}, {:plug_cowboy, "~> 1.0 or ~> 2.0", [hex: :plug_cowboy, repo: "hexpm", optional: true]}, {:telemetry, "~> 0.4", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm"},
|
"phoenix": {:hex, :phoenix, "1.4.9", "746d098e10741c334d88143d3c94cab1756435f94387a63441792e66ec0ee974", [:mix], [{:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: true]}, {:phoenix_pubsub, "~> 1.1", [hex: :phoenix_pubsub, repo: "hexpm", optional: false]}, {:plug, "~> 1.8.1 or ~> 1.9", [hex: :plug, repo: "hexpm", optional: false]}, {:plug_cowboy, "~> 1.0 or ~> 2.0", [hex: :plug_cowboy, repo: "hexpm", optional: true]}, {:telemetry, "~> 0.4", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm"},
|
||||||
"phoenix_ecto": {:hex, :phoenix_ecto, "4.0.0", "c43117a136e7399ea04ecaac73f8f23ee0ffe3e07acfcb8062fe5f4c9f0f6531", [:mix], [{:ecto, "~> 3.0", [hex: :ecto, repo: "hexpm", optional: false]}, {:phoenix_html, "~> 2.9", [hex: :phoenix_html, repo: "hexpm", optional: true]}, {:plug, "~> 1.0", [hex: :plug, repo: "hexpm", optional: false]}], "hexpm"},
|
"phoenix_ecto": {:hex, :phoenix_ecto, "4.0.0", "c43117a136e7399ea04ecaac73f8f23ee0ffe3e07acfcb8062fe5f4c9f0f6531", [:mix], [{:ecto, "~> 3.0", [hex: :ecto, repo: "hexpm", optional: false]}, {:phoenix_html, "~> 2.9", [hex: :phoenix_html, repo: "hexpm", optional: true]}, {:plug, "~> 1.0", [hex: :plug, repo: "hexpm", optional: false]}], "hexpm"},
|
||||||
|
@ -29,7 +37,10 @@
|
||||||
"pot": {:hex, :pot, "0.10.1", "af7dc220fd45478719b821fb4c1222975132516478483213507f95026298d8ab", [:rebar3], [], "hexpm"},
|
"pot": {:hex, :pot, "0.10.1", "af7dc220fd45478719b821fb4c1222975132516478483213507f95026298d8ab", [:rebar3], [], "hexpm"},
|
||||||
"pow": {:hex, :pow, "1.0.11", "f5ef721ac17d2bf8f9dd92f5d40fa0b96512d24b91a26603147754034e3a6101", [:mix], [{:ecto, "~> 2.2 or ~> 3.0", [hex: :ecto, repo: "hexpm", optional: false]}, {:phoenix, "~> 1.3.0 or ~> 1.4.0", [hex: :phoenix, repo: "hexpm", optional: false]}, {:phoenix_html, ">= 2.0.0 and <= 3.0.0", [hex: :phoenix_html, repo: "hexpm", optional: false]}, {:plug, ">= 1.5.0 and < 2.0.0", [hex: :plug, repo: "hexpm", optional: true]}], "hexpm"},
|
"pow": {:hex, :pow, "1.0.11", "f5ef721ac17d2bf8f9dd92f5d40fa0b96512d24b91a26603147754034e3a6101", [:mix], [{:ecto, "~> 2.2 or ~> 3.0", [hex: :ecto, repo: "hexpm", optional: false]}, {:phoenix, "~> 1.3.0 or ~> 1.4.0", [hex: :phoenix, repo: "hexpm", optional: false]}, {:phoenix_html, ">= 2.0.0 and <= 3.0.0", [hex: :phoenix_html, repo: "hexpm", optional: false]}, {:plug, ">= 1.5.0 and < 2.0.0", [hex: :plug, repo: "hexpm", optional: true]}], "hexpm"},
|
||||||
"ranch": {:hex, :ranch, "1.7.1", "6b1fab51b49196860b733a49c07604465a47bdb78aa10c1c16a3d199f7f8c881", [:rebar3], [], "hexpm"},
|
"ranch": {:hex, :ranch, "1.7.1", "6b1fab51b49196860b733a49c07604465a47bdb78aa10c1c16a3d199f7f8c881", [:rebar3], [], "hexpm"},
|
||||||
|
"retry": {:hex, :retry, "0.13.0", "bb9b2713f70f39337837852337ad280c77662574f4fb852a8386c269f3d734c4", [:mix], [], "hexpm"},
|
||||||
"secure_compare": {:hex, :secure_compare, "0.1.0", "01b3c93c8edb696e8a5b38397ed48e10958c8a5ec740606656445bcbec0aadb8", [:mix], [], "hexpm"},
|
"secure_compare": {:hex, :secure_compare, "0.1.0", "01b3c93c8edb696e8a5b38397ed48e10958c8a5ec740606656445bcbec0aadb8", [:mix], [], "hexpm"},
|
||||||
"slime": {:hex, :slime, "1.2.0", "d46ede53c96b743dfdd23821268dc9b01f04ffea65d9d57c4e3d9200b162df02", [:mix], [{:neotoma, "~> 1.7", [hex: :neotoma, repo: "hexpm", optional: false]}], "hexpm"},
|
"slime": {:hex, :slime, "1.2.0", "d46ede53c96b743dfdd23821268dc9b01f04ffea65d9d57c4e3d9200b162df02", [:mix], [{:neotoma, "~> 1.7", [hex: :neotoma, repo: "hexpm", optional: false]}], "hexpm"},
|
||||||
|
"ssl_verify_fun": {:hex, :ssl_verify_fun, "1.1.4", "f0eafff810d2041e93f915ef59899c923f4568f4585904d010387ed74988e77b", [:make, :mix, :rebar3], [], "hexpm"},
|
||||||
"telemetry": {:hex, :telemetry, "0.4.0", "8339bee3fa8b91cb84d14c2935f8ecf399ccd87301ad6da6b71c09553834b2ab", [:rebar3], [], "hexpm"},
|
"telemetry": {:hex, :telemetry, "0.4.0", "8339bee3fa8b91cb84d14c2935f8ecf399ccd87301ad6da6b71c09553834b2ab", [:rebar3], [], "hexpm"},
|
||||||
|
"unicode_util_compat": {:hex, :unicode_util_compat, "0.4.1", "d869e4c68901dd9531385bb0c8c40444ebf624e60b6962d95952775cac5e90cd", [:rebar3], [], "hexpm"},
|
||||||
}
|
}
|
||||||
|
|
62
test/philomena/galleries_test.exs
Normal file
62
test/philomena/galleries_test.exs
Normal file
|
@ -0,0 +1,62 @@
|
||||||
|
defmodule Philomena.GalleriesTest do
|
||||||
|
use Philomena.DataCase
|
||||||
|
|
||||||
|
alias Philomena.Galleries
|
||||||
|
|
||||||
|
describe "galleries" do
|
||||||
|
alias Philomena.Galleries.Gallery
|
||||||
|
|
||||||
|
@valid_attrs %{}
|
||||||
|
@update_attrs %{}
|
||||||
|
@invalid_attrs %{}
|
||||||
|
|
||||||
|
def gallery_fixture(attrs \\ %{}) do
|
||||||
|
{:ok, gallery} =
|
||||||
|
attrs
|
||||||
|
|> Enum.into(@valid_attrs)
|
||||||
|
|> Galleries.create_gallery()
|
||||||
|
|
||||||
|
gallery
|
||||||
|
end
|
||||||
|
|
||||||
|
test "list_galleries/0 returns all galleries" do
|
||||||
|
gallery = gallery_fixture()
|
||||||
|
assert Galleries.list_galleries() == [gallery]
|
||||||
|
end
|
||||||
|
|
||||||
|
test "get_gallery!/1 returns the gallery with given id" do
|
||||||
|
gallery = gallery_fixture()
|
||||||
|
assert Galleries.get_gallery!(gallery.id) == gallery
|
||||||
|
end
|
||||||
|
|
||||||
|
test "create_gallery/1 with valid data creates a gallery" do
|
||||||
|
assert {:ok, %Gallery{} = gallery} = Galleries.create_gallery(@valid_attrs)
|
||||||
|
end
|
||||||
|
|
||||||
|
test "create_gallery/1 with invalid data returns error changeset" do
|
||||||
|
assert {:error, %Ecto.Changeset{}} = Galleries.create_gallery(@invalid_attrs)
|
||||||
|
end
|
||||||
|
|
||||||
|
test "update_gallery/2 with valid data updates the gallery" do
|
||||||
|
gallery = gallery_fixture()
|
||||||
|
assert {:ok, %Gallery{} = gallery} = Galleries.update_gallery(gallery, @update_attrs)
|
||||||
|
end
|
||||||
|
|
||||||
|
test "update_gallery/2 with invalid data returns error changeset" do
|
||||||
|
gallery = gallery_fixture()
|
||||||
|
assert {:error, %Ecto.Changeset{}} = Galleries.update_gallery(gallery, @invalid_attrs)
|
||||||
|
assert gallery == Galleries.get_gallery!(gallery.id)
|
||||||
|
end
|
||||||
|
|
||||||
|
test "delete_gallery/1 deletes the gallery" do
|
||||||
|
gallery = gallery_fixture()
|
||||||
|
assert {:ok, %Gallery{}} = Galleries.delete_gallery(gallery)
|
||||||
|
assert_raise Ecto.NoResultsError, fn -> Galleries.get_gallery!(gallery.id) end
|
||||||
|
end
|
||||||
|
|
||||||
|
test "change_gallery/1 returns a gallery changeset" do
|
||||||
|
gallery = gallery_fixture()
|
||||||
|
assert %Ecto.Changeset{} = Galleries.change_gallery(gallery)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
|
@ -75,6 +75,7 @@ defmodule PhilomenaWeb.CommentControllerTest do
|
||||||
test "deletes chosen comment", %{conn: conn, comment: comment} do
|
test "deletes chosen comment", %{conn: conn, comment: comment} do
|
||||||
conn = delete(conn, Routes.comment_path(conn, :delete, comment))
|
conn = delete(conn, Routes.comment_path(conn, :delete, comment))
|
||||||
assert redirected_to(conn) == Routes.comment_path(conn, :index)
|
assert redirected_to(conn) == Routes.comment_path(conn, :index)
|
||||||
|
|
||||||
assert_error_sent 404, fn ->
|
assert_error_sent 404, fn ->
|
||||||
get(conn, Routes.comment_path(conn, :show, comment))
|
get(conn, Routes.comment_path(conn, :show, comment))
|
||||||
end
|
end
|
||||||
|
|
|
@ -75,6 +75,7 @@ defmodule PhilomenaWeb.TagControllerTest do
|
||||||
test "deletes chosen tag", %{conn: conn, tag: tag} do
|
test "deletes chosen tag", %{conn: conn, tag: tag} do
|
||||||
conn = delete(conn, Routes.tag_path(conn, :delete, tag))
|
conn = delete(conn, Routes.tag_path(conn, :delete, tag))
|
||||||
assert redirected_to(conn) == Routes.tag_path(conn, :index)
|
assert redirected_to(conn) == Routes.tag_path(conn, :index)
|
||||||
|
|
||||||
assert_error_sent 404, fn ->
|
assert_error_sent 404, fn ->
|
||||||
get(conn, Routes.tag_path(conn, :show, tag))
|
get(conn, Routes.tag_path(conn, :show, tag))
|
||||||
end
|
end
|
||||||
|
|
|
@ -24,9 +24,9 @@ fi
|
||||||
# Necessary for apt and elasticsearch to succeed
|
# Necessary for apt and elasticsearch to succeed
|
||||||
install_packages apt-transport-https default-jre-headless
|
install_packages apt-transport-https default-jre-headless
|
||||||
|
|
||||||
if [ ! -f /etc/apt/sources.list.d/elasticsearch-7.x.list ]; then
|
if [ ! -f /etc/apt/sources.list.d/elasticsearch-6.x.list ]; then
|
||||||
add_key https://packages.elastic.co/GPG-KEY-elasticsearch
|
add_key https://packages.elastic.co/GPG-KEY-elasticsearch
|
||||||
echo "deb https://artifacts.elastic.co/packages/7.x/apt stable main" > /etc/apt/sources.list.d/elasticsearch-7.x.list
|
echo "deb https://artifacts.elastic.co/packages/6.x/apt stable main" > /etc/apt/sources.list.d/elasticsearch-6.x.list
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if [ ! -f /etc/apt/sources.list.d/pgdg.list ]; then
|
if [ ! -f /etc/apt/sources.list.d/pgdg.list ]; then
|
||||||
|
|
Loading…
Reference in a new issue