work on pipelines
This commit is contained in:
		| @@ -4,21 +4,88 @@ defmodule Memex.Pipelines do | ||||
|   """ | ||||
|  | ||||
|   import Ecto.Query, warn: false | ||||
|   alias Memex.Repo | ||||
|  | ||||
|   alias Memex.Pipelines.Pipeline | ||||
|   alias Ecto.Changeset | ||||
|   alias Memex.{Accounts.User, Pipelines.Pipeline, Repo} | ||||
|  | ||||
|   @doc """ | ||||
|   Returns the list of pipelines. | ||||
|  | ||||
|   ## Examples | ||||
|  | ||||
|       iex> list_pipelines() | ||||
|       iex> list_pipelines(%User{id: 123}) | ||||
|       [%Pipeline{}, ...] | ||||
|  | ||||
|       iex> list_pipelines("my pipeline", %User{id: 123}) | ||||
|       [%Pipeline{title: "my pipeline"}, ...] | ||||
|  | ||||
|   """ | ||||
|   def list_pipelines do | ||||
|     Repo.all(Pipeline) | ||||
|   @spec list_pipelines(User.t()) :: [Pipeline.t()] | ||||
|   @spec list_pipelines(search :: String.t() | nil, User.t()) :: [Pipeline.t()] | ||||
|   def list_pipelines(search \\ nil, user) | ||||
|  | ||||
|   def list_pipelines(search, %{id: user_id}) when search |> is_nil() or search == "" do | ||||
|     Repo.all(from p in Pipeline, where: p.user_id == ^user_id, order_by: p.title) | ||||
|   end | ||||
|  | ||||
|   def list_pipelines(search, %{id: user_id}) when search |> is_binary() do | ||||
|     trimmed_search = String.trim(search) | ||||
|  | ||||
|     Repo.all( | ||||
|       from p in Pipeline, | ||||
|         where: p.user_id == ^user_id, | ||||
|         where: | ||||
|           fragment( | ||||
|             "search @@ to_tsquery(websearch_to_tsquery(?)::text || ':*')", | ||||
|             ^trimmed_search | ||||
|           ), | ||||
|         order_by: { | ||||
|           :desc, | ||||
|           fragment( | ||||
|             "ts_rank_cd(search, to_tsquery(websearch_to_tsquery(?)::text || ':*'), 4)", | ||||
|             ^trimmed_search | ||||
|           ) | ||||
|         } | ||||
|     ) | ||||
|   end | ||||
|  | ||||
|   @doc """ | ||||
|   Returns the list of public pipelines for viewing | ||||
|  | ||||
|   ## Examples | ||||
|  | ||||
|       iex> list_public_pipelines() | ||||
|       [%Pipeline{}, ...] | ||||
|  | ||||
|       iex> list_public_pipelines("my pipeline") | ||||
|       [%Pipeline{title: "my pipeline"}, ...] | ||||
|   """ | ||||
|   @spec list_public_pipelines() :: [Pipeline.t()] | ||||
|   @spec list_public_pipelines(search :: String.t() | nil) :: [Pipeline.t()] | ||||
|   def list_public_pipelines(search \\ nil) | ||||
|  | ||||
|   def list_public_pipelines(search) when search |> is_nil() or search == "" do | ||||
|     Repo.all(from p in Pipeline, where: p.visibility == :public, order_by: p.title) | ||||
|   end | ||||
|  | ||||
|   def list_public_pipelines(search) when search |> is_binary() do | ||||
|     trimmed_search = String.trim(search) | ||||
|  | ||||
|     Repo.all( | ||||
|       from p in Pipeline, | ||||
|         where: p.visibility == :public, | ||||
|         where: | ||||
|           fragment( | ||||
|             "search @@ to_tsquery(websearch_to_tsquery(?)::text || ':*')", | ||||
|             ^trimmed_search | ||||
|           ), | ||||
|         order_by: { | ||||
|           :desc, | ||||
|           fragment( | ||||
|             "ts_rank_cd(search, to_tsquery(websearch_to_tsquery(?)::text || ':*'), 4)", | ||||
|             ^trimmed_search | ||||
|           ) | ||||
|         } | ||||
|     ) | ||||
|   end | ||||
|  | ||||
|   @doc """ | ||||
| @@ -28,31 +95,47 @@ defmodule Memex.Pipelines do | ||||
|  | ||||
|   ## Examples | ||||
|  | ||||
|       iex> get_pipeline!(123) | ||||
|       iex> get_pipeline!(123, %User{id: 123}) | ||||
|       %Pipeline{} | ||||
|  | ||||
|       iex> get_pipeline!(456) | ||||
|       iex> get_pipeline!(456, %User{id: 123}) | ||||
|       ** (Ecto.NoResultsError) | ||||
|  | ||||
|   """ | ||||
|   def get_pipeline!(id), do: Repo.get!(Pipeline, id) | ||||
|   @spec get_pipeline!(Pipeline.id(), User.t()) :: Pipeline.t() | ||||
|   def get_pipeline!(id, %{id: user_id}) do | ||||
|     Repo.one!( | ||||
|       from p in Pipeline, | ||||
|         where: p.id == ^id, | ||||
|         where: p.user_id == ^user_id or p.visibility in [:public, :unlisted] | ||||
|     ) | ||||
|   end | ||||
|  | ||||
|   def get_pipeline!(id, _invalid_user) do | ||||
|     Repo.one!( | ||||
|       from p in Pipeline, | ||||
|         where: p.id == ^id, | ||||
|         where: p.visibility in [:public, :unlisted] | ||||
|     ) | ||||
|   end | ||||
|  | ||||
|   @doc """ | ||||
|   Creates a pipeline. | ||||
|  | ||||
|   ## Examples | ||||
|  | ||||
|       iex> create_pipeline(%{field: value}) | ||||
|       iex> create_pipeline(%{field: value}, %User{id: 123}) | ||||
|       {:ok, %Pipeline{}} | ||||
|  | ||||
|       iex> create_pipeline(%{field: bad_value}) | ||||
|       iex> create_pipeline(%{field: bad_value}, %User{id: 123}) | ||||
|       {:error, %Ecto.Changeset{}} | ||||
|  | ||||
|   """ | ||||
|   def create_pipeline(attrs \\ %{}) do | ||||
|     %Pipeline{} | ||||
|     |> Pipeline.changeset(attrs) | ||||
|     |> Repo.insert() | ||||
|   @spec create_pipeline(User.t()) :: {:ok, Pipeline.t()} | {:error, Pipeline.changeset()} | ||||
|   @spec create_pipeline(attrs :: map(), User.t()) :: | ||||
|           {:ok, Pipeline.t()} | {:error, Pipeline.changeset()} | ||||
|   def create_pipeline(attrs \\ %{}, user) do | ||||
|     Pipeline.create_changeset(attrs, user) |> Repo.insert() | ||||
|   end | ||||
|  | ||||
|   @doc """ | ||||
| @@ -60,16 +143,18 @@ defmodule Memex.Pipelines do | ||||
|  | ||||
|   ## Examples | ||||
|  | ||||
|       iex> update_pipeline(pipeline, %{field: new_value}) | ||||
|       iex> update_pipeline(pipeline, %{field: new_value}, %User{id: 123}) | ||||
|       {:ok, %Pipeline{}} | ||||
|  | ||||
|       iex> update_pipeline(pipeline, %{field: bad_value}) | ||||
|       iex> update_pipeline(pipeline, %{field: bad_value}, %User{id: 123}) | ||||
|       {:error, %Ecto.Changeset{}} | ||||
|  | ||||
|   """ | ||||
|   def update_pipeline(%Pipeline{} = pipeline, attrs) do | ||||
|   @spec update_pipeline(Pipeline.t(), attrs :: map(), User.t()) :: | ||||
|           {:ok, Pipeline.t()} | {:error, Pipeline.changeset()} | ||||
|   def update_pipeline(%Pipeline{} = pipeline, attrs, user) do | ||||
|     pipeline | ||||
|     |> Pipeline.changeset(attrs) | ||||
|     |> Pipeline.update_changeset(attrs, user) | ||||
|     |> Repo.update() | ||||
|   end | ||||
|  | ||||
| @@ -78,15 +163,24 @@ defmodule Memex.Pipelines do | ||||
|  | ||||
|   ## Examples | ||||
|  | ||||
|       iex> delete_pipeline(pipeline) | ||||
|       iex> delete_pipeline(%Pipeline{user_id: 123}, %User{id: 123}) | ||||
|       {:ok, %Pipeline{}} | ||||
|  | ||||
|       iex> delete_pipeline(pipeline) | ||||
|       iex> delete_pipeline(%Pipeline{}, %User{role: :admin}) | ||||
|       {:ok, %Pipeline{}} | ||||
|  | ||||
|       iex> delete_pipeline(%Pipeline{}, %User{id: 123}) | ||||
|       {:error, %Ecto.Changeset{}} | ||||
|  | ||||
|   """ | ||||
|   def delete_pipeline(%Pipeline{} = pipeline) do | ||||
|     Repo.delete(pipeline) | ||||
|   @spec delete_pipeline(Pipeline.t(), User.t()) :: | ||||
|           {:ok, Pipeline.t()} | {:error, Pipeline.changeset()} | ||||
|   def delete_pipeline(%Pipeline{user_id: user_id} = pipeline, %{id: user_id}) do | ||||
|     pipeline |> Repo.delete() | ||||
|   end | ||||
|  | ||||
|   def delete_pipeline(%Pipeline{} = pipeline, %{role: :admin}) do | ||||
|     pipeline |> Repo.delete() | ||||
|   end | ||||
|  | ||||
|   @doc """ | ||||
| @@ -94,11 +188,30 @@ defmodule Memex.Pipelines do | ||||
|  | ||||
|   ## Examples | ||||
|  | ||||
|       iex> change_pipeline(pipeline) | ||||
|       iex> change_pipeline(pipeline, %User{id: 123}) | ||||
|       %Ecto.Changeset{data: %Pipeline{}} | ||||
|  | ||||
|       iex> change_pipeline(pipeline, %{title: "new title"}, %User{id: 123}) | ||||
|       %Ecto.Changeset{data: %Pipeline{}} | ||||
|  | ||||
|   """ | ||||
|   def change_pipeline(%Pipeline{} = pipeline, attrs \\ %{}) do | ||||
|     Pipeline.changeset(pipeline, attrs) | ||||
|   @spec change_pipeline(Pipeline.t(), User.t()) :: Pipeline.changeset() | ||||
|   @spec change_pipeline(Pipeline.t(), attrs :: map(), User.t()) :: Pipeline.changeset() | ||||
|   def change_pipeline(%Pipeline{} = pipeline, attrs \\ %{}, user) do | ||||
|     pipeline |> Pipeline.update_changeset(attrs, user) | ||||
|   end | ||||
|  | ||||
|   @doc """ | ||||
|   Gets a canonical string representation of the `:tags` field for a Pipeline | ||||
|   """ | ||||
|   @spec get_tags_string(Pipeline.t() | Pipeline.changeset() | [String.t()] | nil) :: String.t() | ||||
|   def get_tags_string(nil), do: "" | ||||
|   def get_tags_string(tags) when tags |> is_list(), do: tags |> Enum.join(",") | ||||
|   def get_tags_string(%Pipeline{tags: tags}), do: tags |> get_tags_string() | ||||
|  | ||||
|   def get_tags_string(%Changeset{} = changeset) do | ||||
|     changeset | ||||
|     |> Changeset.get_field(:tags) | ||||
|     |> get_tags_string() | ||||
|   end | ||||
| end | ||||
|   | ||||
| @@ -1,21 +1,68 @@ | ||||
| defmodule Memex.Pipelines.Pipeline do | ||||
|   @moduledoc """ | ||||
|   Represents a chain of considerations to take to accomplish a task | ||||
|   """ | ||||
|   use Ecto.Schema | ||||
|   import Ecto.Changeset | ||||
|   alias Ecto.{Changeset, UUID} | ||||
|   alias Memex.Accounts.User | ||||
|  | ||||
|   @primary_key {:id, :binary_id, autogenerate: true} | ||||
|   @foreign_key_type :binary_id | ||||
|   schema "pipelines" do | ||||
|     field :description, :string | ||||
|     field :title, :string | ||||
|     field :description, :string | ||||
|     field :tags, {:array, :string} | ||||
|     field :tags_string, :string, virtual: true | ||||
|     field :visibility, Ecto.Enum, values: [:public, :private, :unlisted] | ||||
|  | ||||
|     belongs_to :user, User | ||||
|  | ||||
|     timestamps() | ||||
|   end | ||||
|  | ||||
|   @type t :: %__MODULE__{ | ||||
|           title: String.t(), | ||||
|           description: String.t(), | ||||
|           tags: [String.t()] | nil, | ||||
|           tags_string: String.t(), | ||||
|           visibility: :public | :private | :unlisted, | ||||
|           user: User.t() | Ecto.Association.NotLoaded.t(), | ||||
|           user_id: User.id(), | ||||
|           inserted_at: NaiveDateTime.t(), | ||||
|           updated_at: NaiveDateTime.t() | ||||
|         } | ||||
|   @type id :: UUID.t() | ||||
|   @type changeset :: Changeset.t(t()) | ||||
|  | ||||
|   @doc false | ||||
|   def changeset(pipeline, attrs) do | ||||
|     pipeline | ||||
|     |> cast(attrs, [:title, :description, :visibility]) | ||||
|     |> validate_required([:title, :description, :visibility]) | ||||
|   @spec create_changeset(attrs :: map(), User.t()) :: changeset() | ||||
|   def create_changeset(attrs, %User{id: user_id}) do | ||||
|     %__MODULE__{} | ||||
|     |> cast(attrs, [:title, :description, :tags, :visibility]) | ||||
|     |> change(user_id: user_id) | ||||
|     |> cast_tags_string(attrs) | ||||
|     |> validate_required([:title, :user_id, :visibility]) | ||||
|   end | ||||
|  | ||||
|   @spec update_changeset(t(), attrs :: map(), User.t()) :: changeset() | ||||
|   def update_changeset(%{user_id: user_id} = pipeline, attrs, %User{id: user_id}) do | ||||
|     pipeline | ||||
|     |> cast(attrs, [:title, :description, :tags, :visibility]) | ||||
|     |> cast_tags_string(attrs) | ||||
|     |> validate_required([:title, :visibility]) | ||||
|   end | ||||
|  | ||||
|   defp cast_tags_string(changeset, %{"tags_string" => tags_string}) | ||||
|        when tags_string |> is_binary() do | ||||
|     tags = | ||||
|       tags_string | ||||
|       |> String.split(",", trim: true) | ||||
|       |> Enum.map(fn str -> str |> String.trim() end) | ||||
|       |> Enum.sort() | ||||
|  | ||||
|     changeset |> change(tags: tags) | ||||
|   end | ||||
|  | ||||
|   defp cast_tags_string(changeset, _attrs), do: changeset | ||||
| end | ||||
|   | ||||
		Reference in New Issue
	
	Block a user