Compare commits

...

2 Commits

Author SHA1 Message Date
Ryan Rix 2bea3d976c prevent Things from parenting themselves 2020-09-16 15:05:10 -07:00
Ryan Rix ac11c7292f add test rule to Makefile 2020-09-16 15:03:20 -07:00
3 changed files with 31 additions and 6 deletions

View File

@ -19,3 +19,6 @@ init: tangle
mix deps.compile
mix compile
cd assets; npm install
test: tangle
mix test

View File

@ -174,7 +174,7 @@ end
** =:new= and =:insert= present forms for creating Things
=new/2= is pretty simple, it just creates a form with an empty object in it; =insert/2= is also pretty simple, it creates an object that only has a container ID set.
=new/2= is pretty simple, it just creates a form with an empty object in it; =insert/2= is also pretty simple, it creates an object that only has a container ID set.
#+begin_src elixir :noweb-ref controller-new
def new(conn, _params) do
@ -220,7 +220,7 @@ end
<%= if @changeset.action do %>
<div class="alert callout">Please check errors below!</div>
<% end %>
<%# if it's shown in the UI and the changeset has the ID: %>
<%= if assigns[:container] && @changeset.changes.container_id do %>
<%= hidden_input f, :container_id %>
@ -475,9 +475,9 @@ end
** NEXT =:move= sets a new =Thing.container=
I'm not sure how to do this yet. I am thinking that this will be the arbitrary place where I'll integrate Phoenix LiveView: a dynamic search field for Things, with some action when I click them. If I build it properly, it can probably be used in the =:index= list too, so that I can have a filtered search of all my shite.
I'm not sure how to do this yet. I am thinking that this will be the arbitrary place where I'll integrate Phoenix LiveView: a dynamic search field for Things, with some action when I click them. If I build it properly, it can probably be used in the =:index= list too, so that I can have a filtered search of all my shite.
The =move= action is maybe misnamed -- it's not doing the movement just rendering a form where the user will be able to.
The =move= action is maybe misnamed -- it's not doing the movement just rendering a form where the user will be able to.
#+begin_src elixir :noweb-ref controller-move
def move(conn, %{"id" => id, "filter_str" => filter_str}) do
@ -521,7 +521,7 @@ def do_move(conn, %{"id" => id, "new_parent" => new_parent}) do
|> put_flash(:alert, "Changeset save failed: #{inspect(changeset.errors)}")
|> put_view(PokaIjoWeb.ThingView)
_ ->
_ ->
conn
|> put_flash(:success, "#{t.name} moved!")
end
@ -547,7 +547,7 @@ This relies on [[file:../javascript.org][§JavaScript]] to work; =Phoenix.HTML.L
</div>
</div>
<% end %>
<%= for thing <- @things do %>
<div class="callout grid-x">
<div class="small-8 medium-10 cell">
@ -645,6 +645,7 @@ the =:do_move= behavior is also pretty easy to test.
#+begin_src elixir :tangle test/poka_ijo_web/controllers/thing_controller_test.exs :noweb yes
defmodule WebControllersThingDoMoveTest do
use PokaIjoWeb.ConnCase
alias PokaIjo.Thing
alias WebControllersThingMoveTest
@ -658,6 +659,21 @@ defmodule WebControllersThingDoMoveTest do
assert Thing.get_by(id: t.id).container_id == container.id
assert get_flash(conn, :success) =~ "moved!"
end
test ":do_move cannot parent an object to itself", %{conn: conn} do
%{container: cur_container} = insert()
{:ok, t} =
%{name: "my_test", description: "hi", container_id: cur_container.id}
|> PokaIjo.Thing.new()
|> PokaIjo.Repo.insert()
conn = post(conn, "/things/#{t.id}/move", new_parent: t.id)
assert Thing.get_by(id: t.id).container_id != t.id
assert conn.status == 302
assert get_flash(conn, :alert) =~ "failed"
end
end
#+end_src

View File

@ -99,6 +99,12 @@ These functions aid in the creation and update of Things.
|> cast(params, all_keys)
|> cast_assoc(:container)
|> validate_required(required_keys)
|> validate_change(:container_id, fn :container_id, container_id ->
cond do
thing.id != nil && container_id == thing.id -> [container: "Cannot contain itself."]
true -> []
end
end)
end
#+end_src