Skip to content

Commit

Permalink
fix: Use ecto schema assocs to determine if the viaRelationship is a …
Browse files Browse the repository at this point in the history
…reverse. (#244)

* fix: Use Ecto relationship keys to look up and lock viaRelationship

* assets
  • Loading branch information
staylorwr authored Nov 17, 2023
1 parent 9915752 commit 075632f
Show file tree
Hide file tree
Showing 19 changed files with 167 additions and 26 deletions.
15 changes: 11 additions & 4 deletions assets/src/components/Form/BelongsTo.vue
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
>
<template slot="field">
<search-input
:disabled="creatingViaRelatedResource"
:disabled="disabled"
:error="hasError"
:value="selectedResource"
:data="availableResources"
Expand Down Expand Up @@ -125,7 +125,7 @@ export default {
* Determine if we are creating a new resource via a parent relation
*/
creatingViaRelatedResource () {
return (
return Boolean(
this.viaResource == this.field.options.belongs_to_relationship &&
this.field.options.reverse &&
this.viaResourceId
Expand All @@ -137,7 +137,7 @@ export default {
*/
shouldSelectInitialResource () {
return Boolean(
this.editingExistingResource || this.creatingViaRelatedResource
this.editingExistingResource || this.creatingViaRelatedResource || this.field.value
);
},
Expand All @@ -149,10 +149,17 @@ export default {
params: {
current: this.selectedResourceId,
first: this.initializingWithExistingResource,
search: this.search
search: this.search,
viaResource: this.viaResource,
viaResourceId: this.viaResourceId,
viaRelationship: this.viaRelationship
}
};
},
disabled () {
return !!this.creatingViaRelatedResource;
}
},
/**
Expand Down
11 changes: 10 additions & 1 deletion assets/src/components/Index/ResourceTableRow.vue
Original file line number Diff line number Diff line change
Expand Up @@ -96,7 +96,8 @@
v-if="shouldShowUpdateButton"
:to="{
name: 'edit',
params: editLinkParams
params: editLinkParams,
query: editLinkQuery,
}"
title="Edit"
class="table-action-link primary"
Expand Down Expand Up @@ -242,6 +243,14 @@ export default {
editLinkParams () {
const { resource_name: resourceName, resource_id: resourceId } = this.resource.meta.edit_link;
return { resourceName, resourceId };
},
editLinkQuery () {
const query = {};
if (this.viaResource) { query.viaResource = this.viaResource; }
if (this.viaResourceId) { query.viaResourceId = this.viaResourceId; }
if (this.viaRelationship) { query.viaRelationship = this.viaRelationship; }
return query;
}
},
Expand Down
5 changes: 4 additions & 1 deletion assets/src/router/routes.js
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,10 @@ export default [
props: route => {
return {
resourceName: route.params.resourceName,
resourceId: Number.parseInt(route.params.resourceId)
resourceId: Number.parseInt(route.params.resourceId),
viaResource: route.query.viaResource,
viaResourceId: Number.parseInt(route.query.viaResourceId),
viaRelationship: route.query.viaRelationship
};
}
},
Expand Down
9 changes: 8 additions & 1 deletion assets/src/views/Create.vue
Original file line number Diff line number Diff line change
Expand Up @@ -119,7 +119,14 @@ export default {
const {
data: { fields, panels }
} = await ExTeal.request().get(
`/api/${this.resourceName}/creation-fields`
`/api/${this.resourceName}/creation-fields`,
{
params: {
viaResource: this.viaResource,
viaResourceId: this.viaResourceId,
viaRelationship: this.viaRelationship
}
}
);
this.fields = fields;
Expand Down
22 changes: 19 additions & 3 deletions assets/src/views/Update.vue
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,18 @@ export default {
resourceId: {
required: true,
type: Number
},
viaResource: {
default: '',
type: String
},
viaResourceId: {
default: null,
type: Number
},
viaRelationship: {
default: '',
type: String
}
},
Expand All @@ -96,12 +108,10 @@ export default {
* Create the form data for creating the resource.
*/
updateResourceFormData () {
console.log('is broke');
return _.tap(new FormData(), formData => {
_(this.fields).each(field => {
field.fill(formData);
});
console.log('hi');
formData.append('_method', 'PUT');
formData.append('_retrieved_at', this.lastRetrievedAt);
Expand Down Expand Up @@ -141,7 +151,13 @@ export default {
const {
data: { fields, panels }
} = await ExTeal.request()
.get(`/api/${this.resourceName}/${this.resourceId}/update-fields`)
.get(`/api/${this.resourceName}/${this.resourceId}/update-fields`, {
params: {
viaResource: this.viaResource,
viaResourceId: this.viaResourceId,
viaRelationship: this.viaRelationship
}
})
.catch(error => {
if (error.response.status == 404) {
this.$router.push({ name: '404' });
Expand Down
28 changes: 26 additions & 2 deletions lib/ex_teal/fields/belongs_to.ex
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ defmodule ExTeal.Fields.BelongsTo do
end

@impl true
def apply_options_for(field, model, _conn, _type) do
def apply_options_for(field, model, conn, _type) do
id =
case Map.get(model, field.field) do
nil -> nil
Expand All @@ -54,7 +54,7 @@ defmodule ExTeal.Fields.BelongsTo do
belongs_to_key: rel.owner_key,
belongs_to_relationship: resource.uri(),
belongs_to_id: id,
reverse: rel.field == rel.relationship
reverse: is_reverse_relationship(resource, rel, conn)
})

Map.put(field, :options, opts)
Expand All @@ -73,4 +73,28 @@ defmodule ExTeal.Fields.BelongsTo do
IO.warn("searchable/1 is deprecated. BelongsTo fields are always searchable")
field
end

defp is_reverse_relationship(resource, rel, conn) do
via_resource = Map.get(conn.params, "viaResource")
via_relationship = Map.get(conn.params, "viaRelationship")

if is_nil(via_resource) || via_resource != resource.uri() do
false
else
matches_relationship?(rel, via_relationship)
end
end

defp matches_relationship?(rel, via_relationship) do
all_relationships = rel.related.__schema__(:associations)

if Enum.any?(all_relationships, fn assoc -> Atom.to_string(assoc) == via_relationship end) do
known_relationship =
rel.related.__schema__(:association, String.to_existing_atom(via_relationship))

rel.owner_key == known_relationship.related_key
else
false
end
end
end
1 change: 0 additions & 1 deletion priv/static/teal/js/75e00c2905ee40bb104d.js

This file was deleted.

Binary file removed priv/static/teal/js/75e00c2905ee40bb104d.js.gz
Binary file not shown.
1 change: 1 addition & 0 deletions priv/static/teal/js/c5a2a3991a08372f403a.js

Large diffs are not rendered by default.

Binary file added priv/static/teal/js/c5a2a3991a08372f403a.js.gz
Binary file not shown.
6 changes: 3 additions & 3 deletions priv/static/teal/manifest.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"npm.babel.js": "/js/0.e53acd4a3b6f3dddb993.chunk.js",
"main.css": "/css/main.css",
"main.js": "/js/75e00c2905ee40bb104d.js",
"main.js": "/js/c5a2a3991a08372f403a.js",
"npm.axios.js": "/js/2.b5681d8781a013e3a46a.chunk.js",
"npm.chart.js.js": "/js/3.5e6b2fe6b95b03fdd807.chunk.js",
"npm.core-js.js": "/js/4.e93b620fa8cc3701e33e.chunk.js",
Expand Down Expand Up @@ -53,7 +53,7 @@
"js/30.042b195e0929ed4396d1.chunk.js.gz": "/js/30.042b195e0929ed4396d1.chunk.js.gz",
"js/4.e93b620fa8cc3701e33e.chunk.js.gz": "/js/4.e93b620fa8cc3701e33e.chunk.js.gz",
"js/5.6b71956b7656aa029b3f.chunk.js.gz": "/js/5.6b71956b7656aa029b3f.chunk.js.gz",
"js/75e00c2905ee40bb104d.js.gz": "/js/75e00c2905ee40bb104d.js.gz",
"js/8.99b3024d9ac1ce535a8d.chunk.js.gz": "/js/8.99b3024d9ac1ce535a8d.chunk.js.gz",
"js/9.551d6dd6fd261f870ac3.chunk.js.gz": "/js/9.551d6dd6fd261f870ac3.chunk.js.gz"
"js/9.551d6dd6fd261f870ac3.chunk.js.gz": "/js/9.551d6dd6fd261f870ac3.chunk.js.gz",
"js/c5a2a3991a08372f403a.js.gz": "/js/c5a2a3991a08372f403a.js.gz"
}
3 changes: 2 additions & 1 deletion test/ex_teal/field_filter_test.exs
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,8 @@ defmodule ExTeal.FieldFilterTest do
"contributor",
"published_at",
"deleted_at",
"user"
"user",
"editor"
]
end

Expand Down
70 changes: 70 additions & 0 deletions test/ex_teal/fields/belongs_to_test.exs
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
defmodule ExTeal.Fields.BelongsToTest do
use TestExTeal.ConnCase
alias ExTeal.Fields.BelongsTo
alias TestExTeal.{Post, User}

describe "apply_options_for/4" do
@tag manifest: TestExTeal.DefaultManifest
test "sets related values for an existing belongs to relationship" do
user = insert(:user)
post = insert(:post, user: user)
f = BelongsTo.make(:user, User)
conn = build_conn(:get, "/posts", %{})

f = BelongsTo.apply_options_for(f, post, conn, nil)

assert f.options == %{
belongs_to_id: user.id,
belongs_to_key: :user_id,
belongs_to_relationship: "users",
reverse: false
}
end

@tag manifest: TestExTeal.DefaultManifest
test "sets reverse to true when via relationship values are passed" do
post = %Post{}
user = insert(:user)
f = BelongsTo.make(:user, User)

conn =
build_conn(:get, "/resources/posts/creation-fields", %{
"viaResource" => "users",
"viaResourceId" => "#{user.id}",
"viaRelationship" => "posts"
})

f = BelongsTo.apply_options_for(f, post, conn, nil)

assert f.options == %{
belongs_to_id: nil,
belongs_to_key: :user_id,
belongs_to_relationship: "users",
reverse: true
}
end

@tag manifest: TestExTeal.DefaultManifest
test "sets reverse to false when via relationship doesn't correspond" do
post = %Post{}
user = insert(:user)
f = BelongsTo.make(:editor, User)

conn =
build_conn(:get, "/resources/posts/creation-fields", %{
"viaResource" => "users",
"viaResourceId" => "#{user.id}",
"viaRelationship" => "posts"
})

f = BelongsTo.apply_options_for(f, post, conn, nil)

assert f.options == %{
belongs_to_id: nil,
belongs_to_key: :editor_id,
belongs_to_relationship: "users",
reverse: false
}
end
end
end
6 changes: 3 additions & 3 deletions test/ex_teal/resource/export_test.exs
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,7 @@ defmodule ExTeal.Resource.ExportTest do
[header, p1_csv, p2_csv] = String.split(data, "\r\n", trim: true)

assert header ==
"id,name,body,author,contributor,published,published_at,deleted_at,features,location,user_id,inserted_at,updated_at"
"id,name,body,author,contributor,published,published_at,deleted_at,features,location,user_id,editor_id,inserted_at,updated_at"

assert String.contains?(p1_csv, "#{p1.id},#{p1.name}")
assert String.contains?(p2_csv, "#{p2.id},#{p2.name}")
Expand Down Expand Up @@ -156,7 +156,7 @@ defmodule ExTeal.Resource.ExportTest do
[header, p1_csv, p2_csv] = String.split(data, "\r\n", trim: true)

assert header ==
"id,name,body,author,contributor,published,published_at,deleted_at,features,location,user_id,inserted_at,updated_at"
"id,name,body,author,contributor,published,published_at,deleted_at,features,location,user_id,editor_id,inserted_at,updated_at"

assert String.contains?(p1_csv, "#{p2.id},#{p2.name}")
assert String.contains?(p2_csv, "#{p1.id},#{p1.name}")
Expand Down Expand Up @@ -194,7 +194,7 @@ defmodule ExTeal.Resource.ExportTest do
fields = TestExTeal.PostResource.export_fields()

expected =
~w(id name body author contributor published published_at deleted_at features location user_id inserted_at updated_at)a
~w(id name body author contributor published published_at deleted_at features location user_id editor_id inserted_at updated_at)a

assert fields == expected
end
Expand Down
2 changes: 1 addition & 1 deletion test/ex_teal/resource/fields_test.exs
Original file line number Diff line number Diff line change
Expand Up @@ -153,7 +153,7 @@ defmodule ExTeal.Resource.FieldsTest do
fields = Fields.fields_for_has_many(PostResource, conn)

assert Enum.map(fields, & &1.field) ==
~w(id name published author contributor published_at deleted_at user features)a
~w(id name published author contributor published_at deleted_at user editor features)a
end

@tag manifest: TestExTeal.PostCountManifest
Expand Down
2 changes: 1 addition & 1 deletion test/ex_teal/resource/index_test.exs
Original file line number Diff line number Diff line change
Expand Up @@ -246,6 +246,6 @@ defmodule ExTeal.Resource.IndexTest do

method
|> build_conn(path, params)
|> fetch_query_params
|> fetch_query_params()
end
end
1 change: 1 addition & 0 deletions test/support/migrations.exs
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ defmodule TestExTeal.Migrations do
add(:features, :map)
add(:location, :map)
add(:user_id, references(:users))
add(:editor_id, references(:users))
add(:published, :boolean, default: false, null: false)
add(:published_at, :naive_datetime)
add(:deleted_at, :utc_datetime)
Expand Down
7 changes: 4 additions & 3 deletions test/support/resources.exs
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ defmodule TestExTeal.UserResource do
Text.make(:email),
Select.make(:role),
HasMany.make(:posts),
HasMany.make(:edited_posts),
HasMany.make(:post_likes),
ManyToMany.make(:preferred_tags, TestExTeal.Tag)
|> ManyToMany.with_index_fields([
Expand Down Expand Up @@ -53,7 +54,7 @@ defmodule TestExTeal.PostResource do

def model, do: TestExTeal.Post

def with, do: [:user]
def with, do: [:user, :editor]

def fields,
do: [
Expand All @@ -65,7 +66,8 @@ defmodule TestExTeal.PostResource do
Select.make(:contributor) |> Select.options(~w(foo bar)),
DateTime.make(:published_at),
DateTime.make(:deleted_at),
BelongsTo.make(:user),
BelongsTo.make(:user, TestExTeal.User),
BelongsTo.make(:editor, TestExTeal.User),
BooleanGroup.make(:features)
|> BooleanGroup.options(%{
"show_cta" => "Show CTA",
Expand Down Expand Up @@ -312,7 +314,6 @@ defmodule TestExTeal.Forever.PostResource do
Select.make(:contributor) |> Select.options(~w(foo bar)),
DateTime.make(:published_at),
DateTime.make(:deleted_at),
BelongsTo.make(:user),
BooleanGroup.make(:features)
|> BooleanGroup.options(%{
"show_cta" => "Show CTA",
Expand Down
Loading

0 comments on commit 075632f

Please sign in to comment.