-
Notifications
You must be signed in to change notification settings - Fork 372
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[WIP] Change url companies param on :show route to name attribute #594
Changes from all commits
fd9cca2
b4d66f0
87168dd
d093ae0
30a35a0
014a304
6288667
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -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] | ||
|
@@ -25,7 +27,26 @@ defmodule Companies.Schema.Company do | |
@doc false | ||
def changeset(company, attrs) do | ||
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]) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The slug is unique in the database by a constraint but this constraint is not handled in the changeset. Another thing to deal with is how pending changes are managed in the code. When a company is created a pending_change is inserted in the database. When that change is approved, the company will be inserted in the companies table and could fail on the uniqueness constraint. It would be preferable imo to deal with duplicate slugs earlier, perhaps by adding an unsafe_validate_unique and adding postfixes to the slugs to make them unique. This would not entirely be foolproof (e.g. multiple pending changes could have the same slug) but could go a long way. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. we could add the company id in the slug just to be safe. e.g. Plataformatec turns into 1-plataformatec (the id here is random). There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Crazy idea feel free to shoot this down: what if we don't enforce the uniqueness in the changeset (or we create a changeset without it) and instead defer the work of creating unique slugs onto admins approving changes. In the UI to approve a company we could show whether the slug was already taken and require the admin to make a unique one. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @maartenvanvliet / @gemantzu how do you both feel about moving generation of things like slugs (or password hashes) into the changeset pipeline like such? def changeset(company, attrs) do
company
|> cast(attrs, [:name, :description, :url, :github, :location, :blog, :industry_id, :slug])
|> validate_required([:name, :description, :url, :industry_id])
|> generate_slug()
|> unique_constraint(:slug)
end
# when there is an existing non-nil `id` in the data, we don't want to regenerate a slug even on name change
# that would break any potential backlinks.
defp generate_slug(%Ecto.Changeset{data: %{id: id}} = changeset) when not is_nil(id) do
changeset
end
defp generate_slug(%Ecto.Changeset{changes: %{name: name}} = changeset) do
slug =
name
|> String.replace(~r/['’]s/u, "s")
|> String.downcase()
|> String.replace(~r/([^a-z0-9가-힣])+/, "-")
|> String.replace(" ", "-")
put_change(changeset, :slug, slug)
end |
||
|> generate_slug() | ||
|> unique_constraint(:slug, message: "Company slug already exists") | ||
end | ||
|
||
defp generate_slug(%Ecto.Changeset{data: %{id: id}} = changeset) when not is_nil(id) do | ||
changeset | ||
end | ||
|
||
defp generate_slug(%Ecto.Changeset{changes: %{name: name}} = changeset) do | ||
slug = | ||
name | ||
|> String.replace(~r/['’]s/u, "s") | ||
|> String.downcase() | ||
|> String.replace(~r/([^a-z0-9가-힣])+/, "-") | ||
|> String.replace(" ", "-") | ||
|
||
put_change(changeset, :slug, slug) | ||
end | ||
|
||
defp generate_slug(changeset), do: changeset | ||
end |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -53,13 +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, :show] | ||
resources "/companies", CompanyController, only: [:index, :show], param: "slug" | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Just to be aware of this, the old url's based on integers would no longer work with this change. We could implement a fallback but this is also fine. |
||
get "/jobs", JobController, :index | ||
get "/profile", UserController, :profile | ||
get "/for_hire", UserController, :for_hire | ||
|
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 unique_index(:companies, [:slug]) | ||
end | ||
end |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I like this :)