Skip to content

Commit

Permalink
Add slug field to company
Browse files Browse the repository at this point in the history
  • Loading branch information
DouglasLutz committed Mar 5, 2020
1 parent 9a75727 commit c6bb282
Show file tree
Hide file tree
Showing 10 changed files with 75 additions and 32 deletions.
8 changes: 4 additions & 4 deletions lib/companies/companies.ex
Original file line number Diff line number Diff line change
Expand Up @@ -107,21 +107,21 @@ defmodule Companies.Companies do
## Examples
iex> get!("Valid name")
iex> get!("Valid slug")
%Company{}
iex> get!("Invalid name")
iex> get!("Invalid slug")
** (Ecto.NoResultsError)
"""
def get_by_name!(name, opts \\ []) do
def get_by_slug!(slug, opts \\ []) do
preloads = Keyword.get(opts, :preloads, [])

from(c in Company)
|> preload(^preloads)
|> from()
|> where([c], is_nil(c.removed_pending_change_id))
|> Repo.get_by!(name: name)
|> Repo.get_by!(slug: slug)
end

@doc """
Expand Down
19 changes: 18 additions & 1 deletion lib/companies/schema/company.ex
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,15 @@ defmodule Companies.Schema.Company do

alias Companies.Schema.{Industry, Job, PendingChange}

@derive {Phoenix.Param, key: :slug}
schema "companies" do
field :blog, :string
field :description, :string
field :github, :string
field :location, :string
field :name, :string
field :url, :string
field :slug, :string

belongs_to :industry, Industry
has_many :jobs, Job, defaults: [removed_pending_change_id: nil]
Expand All @@ -24,8 +26,23 @@ defmodule Companies.Schema.Company do

@doc false
def changeset(company, attrs) do
attrs = Map.merge(attrs, slug_map(attrs))

company
|> cast(attrs, [:name, :description, :url, :github, :location, :blog, :industry_id])
|> cast(attrs, [:name, :description, :url, :github, :location, :blog, :industry_id, :slug])
|> validate_required([:name, :description, :url, :industry_id])
end

defp slug_map(%{"name" => name}) do
slug =
name
|> String.replace(~r/['’]s/u, "s")
|> String.downcase()
|> String.replace(~r/([^a-z0-9가-힣])+/, "-")
|> String.replace(" ", "-")

%{"slug" => slug}
end

defp slug_map(_attrs), do: %{}
end
16 changes: 8 additions & 8 deletions lib/companies_web/controllers/company_controller.ex
Original file line number Diff line number Diff line change
Expand Up @@ -37,20 +37,20 @@ defmodule CompaniesWeb.CompanyController do
end
end

def show(conn, %{"name" => name}) do
company = Companies.get_by_name!(name, preloads: [:jobs, :industry])
def show(conn, %{"slug" => slug}) do
company = Companies.get_by_slug!(slug, preloads: [:jobs, :industry])
render(conn, "show.html", company: company)
end

def edit(conn, %{"id" => id}) do
company = Companies.get!(id)
def edit(conn, %{"slug" => slug}) do
company = Companies.get_by_slug!(slug)
changeset = Companies.change(company)
industries = Industries.all()
render(conn, "edit.html", company: company, changeset: changeset, industries: industries)
end

def update(conn, %{"id" => id, "company" => company_params}) do
company = Companies.get!(id)
def update(conn, %{"slug" => slug, "company" => company_params}) do
company = Companies.get_by_slug!(slug)

case Companies.update(company, company_params, current_user(conn)) do
{:ok, _company} ->
Expand All @@ -64,8 +64,8 @@ defmodule CompaniesWeb.CompanyController do
end
end

def delete(conn, %{"id" => id}) do
company = Companies.get!(id)
def delete(conn, %{"slug" => slug}) do
company = Companies.get_by_slug!(slug)
{:ok, _company} = Companies.delete(company, current_user(conn))

conn
Expand Down
5 changes: 2 additions & 3 deletions lib/companies_web/router.ex
Original file line number Diff line number Diff line change
Expand Up @@ -53,14 +53,13 @@ defmodule CompaniesWeb.Router do
scope "/" do
pipe_through [:auth]

resources "/companies", CompanyController, except: [:index, :show]
resources "/companies", CompanyController, except: [:index, :show], param: "slug"
resources "/jobs", JobController, except: [:index, :show]
resources "/users", UserController, only: [:edit, :update]
end

get "/", CompanyController, :recent
resources "/companies", CompanyController, only: [:index]
resources "/companies", CompanyController, only: [:show], param: "name"
resources "/companies", CompanyController, only: [:index, :show], param: "slug"
get "/jobs", JobController, :index
get "/profile", UserController, :profile
get "/for_hire", UserController, :for_hire
Expand Down
2 changes: 1 addition & 1 deletion lib/companies_web/templates/company/card.html.eex
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
</div>
<% end %>
<div class="content has-text-centered">
<p class="title is-4 thin"><%= link to: Routes.company_path(@conn, :show, locale(@conn), @company.name) do %><%= @company.name %><% end %></p>
<p class="title is-4 thin"><%= link to: Routes.company_path(@conn, :show, locale(@conn), @company) do %><%= @company.name %><% end %></p>
<%= if signed_in?(@conn) do %>
<div class="company-actions-wrapper">
<div class="toggle-company-actions">
Expand Down
11 changes: 11 additions & 0 deletions priv/repo/migrations/20200305171000_add_slug_to_companies.exs
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
defmodule Companies.Repo.Migrations.AddSlugToCompanies do
use Ecto.Migration

def change do
alter table(:companies) do
add :slug, :string
end

create index(:companies, [:slug], unique: true)
end
end
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
defmodule Companies.Repo.Migrations.AddSlugValueForExistingCompanies do
use Ecto.Migration

alias Companies.Repo
alias Companies.Schema.Company

def change do
Repo.all(Company)
|> Enum.map(fn company ->
slug =
company.name
|> String.replace(~r/['’]s/u, "s")
|> String.downcase()
|> String.replace(~r/([^a-z0-9가-힣])+/, "-")
|> String.replace(" ", "-")

changeset = Company.changeset(company, %{"slug" => slug})
changeset = unless changeset.valid?, do: Company.changeset(company, %{"slug" => "#{slug}-2"})

Repo.update(changeset)
end)
end
end
1 change: 1 addition & 0 deletions priv/repo/seeds.exs
Original file line number Diff line number Diff line change
Expand Up @@ -174,6 +174,7 @@ technology_consulting = Repo.insert!(%Industry{name: "Technology Consulting"})
plataformatec =
Repo.insert!(%Company{
name: "Plataformatec",
slug: "plataformatec",
description: """
Project inception, coaching, tailored projects, general consulting. Sponsor of Elixir, employer to Elixir's BDFL.
""",
Expand Down
21 changes: 6 additions & 15 deletions test/companies/companies_test.exs
Original file line number Diff line number Diff line change
Expand Up @@ -85,31 +85,22 @@ defmodule Companies.CompaniesTest do
end
end

describe "get_by_name!/2" do
describe "get_by_slug!/2" do
test "retrieves a company by it's name" do
%{name: name} = insert(:company, name: "ZULU")
%{id: id, slug: slug} = insert(:company, name: "ZULU")

assert %{name: ^name} = Companies.get_by_name!(name)
assert %{id: ^id} = Companies.get_by_slug!(slug)
end

test "preloads given associations" do
company = insert(:company, name: "ZULU")

assert %{jobs: []} = Companies.get_by_name!(company.name, preloads: [:jobs])
assert %{jobs: []} = Companies.get_by_slug!(company.slug, preloads: [:jobs])
end

test "raises for unknown name" do
test "raises for unknown slug" do
assert_raise Ecto.NoResultsError, fn ->
Companies.get_by_name!("NONAME", preloads: [:jobs])
end
end

test "raises for multiple companies with same name" do
insert(:company, name: "ZULU")
insert(:company, name: "ZULU")

assert_raise Ecto.MultipleResultsError, fn ->
Companies.get_by_name!("ZULU", preloads: [:jobs])
Companies.get_by_slug!("invalid-slug", preloads: [:jobs])
end
end
end
Expand Down
1 change: 1 addition & 0 deletions test/support/factories.ex
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ defmodule Companies.Factory do
description: "A test company",
industry: insert(:industry),
name: sequence(:name, &"Test Company #{&1}"),
slug: sequence(:slug, &"test-company-#{&1}"),
url: "www.example.com"
}
end
Expand Down

0 comments on commit c6bb282

Please sign in to comment.