Repository: jeregrine/jsonapi
Pull request #126 (2018-08-29 13:43:35)

Allows for conditionally hiding fields
Why:

* It is useful to be able to show or hide fields based on some condition
  on the data being passed to the serializer

This change addresses the need by:

* Passing `data` to the `hidden/1` function
* Deprecating the `hidden/0` function with a warning, since it needs to
  be changed in all the serializers that use it. It keeps the existing
  behavior if a `hidden/0` function is found, so not to break any
  application


Patch:
diff --git a/lib/jsonapi/deprecation.ex b/lib/jsonapi/deprecation.ex
index 09733e0..dcbd3c3 100644
--- a/lib/jsonapi/deprecation.ex
+++ b/lib/jsonapi/deprecation.ex
@@ -13,4 +13,11 @@ defmodule Deprecation do
       Macro.Env.stacktrace(__ENV__)
     )
   end
+
+  def warn(:hidden) do
+    IO.warn(
+      "`JSONAPI.View.hidden/0` is deprecated; use `JSONAPI.View.hidden/1` instead.",
+      Macro.Env.stacktrace(__ENV__)
+    )
+  end
 end
diff --git a/lib/jsonapi/view.ex b/lib/jsonapi/view.ex
index 7a41dbd..b8c720a 100644
--- a/lib/jsonapi/view.ex
+++ b/lib/jsonapi/view.ex
@@ -107,7 +107,15 @@ defmodule JSONAPI.View do
       end
 
       def attributes(data, conn) do
-        visible_fields = fields() -- hidden()
+        hidden =
+          if Enum.member?(__MODULE__.__info__(:functions), {:hidden, 0}) do
+            Deprecation.warn(:hidden)
+            __MODULE__.hidden()
+          else
+            hidden(data)
+          end
+
+        visible_fields = fields() -- hidden
 
         Enum.reduce(visible_fields, %{}, fn field, intermediate_map ->
           value =
@@ -128,7 +136,7 @@ defmodule JSONAPI.View do
 
       def fields, do: raise("Need to implement fields/0")
 
-      def hidden, do: []
+      def hidden(data), do: []
 
       def show(model, conn, _params, meta \\ nil), do: serialize(__MODULE__, model, conn, meta)
       def index(models, conn, _params, meta \\ nil), do: serialize(__MODULE__, models, conn, meta)
@@ -197,7 +205,7 @@ defmodule JSONAPI.View do
       defoverridable attributes: 2,
                      links: 2,
                      fields: 0,
-                     hidden: 0,
+                     hidden: 1,
                      id: 1,
                      meta: 2,
                      relationships: 0,


Test patch:
diff --git a/test/jsonapi/view_test.exs b/test/jsonapi/view_test.exs
index 7e920a6..de07094 100644
--- a/test/jsonapi/view_test.exs
+++ b/test/jsonapi/view_test.exs
@@ -15,6 +15,16 @@ defmodule JSONAPI.ViewTest do
 
   defmodule PostView do
     use JSONAPI.View, type: "posts", namespace: "/api"
+
+    def fields do
+      [:title, :body]
+    end
+
+    def hidden(%{title: "Hidden body"}) do
+      [:body]
+    end
+
+    def hidden(_), do: []
   end
 
   defmodule UserView do
@@ -91,7 +101,7 @@ defmodule JSONAPI.ViewTest do
     refute {:render, 2} in PostView.__info__(:functions)
   end
 
-  test "attributes/2 does not display hidden fields" do
+  test "attributes/2 does not display hidden fields with deprecated hidden/0" do
     expected_map = %{age: 100, first_name: "Jason", last_name: "S", full_name: "Jason S"}
 
     assert expected_map ==
@@ -100,4 +110,21 @@ defmodule JSONAPI.ViewTest do
                nil
              )
   end
+
+  test "attributes/2 does not display hidden fields based on a condition" do
+    hidden_expected_map = %{title: "Hidden body"}
+    normal_expected_map = %{title: "Other title", body: "Something"}
+
+    assert hidden_expected_map ==
+             PostView.attributes(
+               %{title: "Hidden body", body: "Something"},
+               nil
+             )
+
+    assert normal_expected_map ==
+             PostView.attributes(
+               %{title: "Other title", body: "Something"},
+               nil
+             )
+  end
 end