diff --git a/.credo.exs b/.credo.exs new file mode 100644 index 0000000..41fcd28 --- /dev/null +++ b/.credo.exs @@ -0,0 +1,190 @@ +# This file contains the configuration for Credo and you are probably reading +# this after creating it with `mix credo.gen.config`. +# +# If you find anything wrong or unclear in this file, please report an +# issue on GitHub: https://github.com/rrrene/credo/issues +# +%{ + # + # You can have as many configs as you like in the `configs:` field. + configs: [ + %{ + # + # Run any config using `mix credo -C `. If no config name is given + # "default" is used. + # + name: "default", + # + # These are the files included in the analysis: + files: %{ + # + # You can give explicit globs or simply directories. + # In the latter case `**/*.{ex,exs}` will be used. + # + included: [ + "lib/", + "src/", + "test/", + "web/", + "apps/*/lib/", + "apps/*/src/", + "apps/*/test/", + "apps/*/web/" + ], + excluded: [~r"/_build/", ~r"/deps/", ~r"/node_modules/"] + }, + # + # Load and configure plugins here: + # + plugins: [], + # + # If you create your own checks, you must specify the source files for + # them here, so they can be loaded by Credo before running the analysis. + # + requires: [], + # + # If you want to enforce a style guide and need a more traditional linting + # experience, you can change `strict` to `true` below: + # + strict: false, + # + # To modify the timeout for parsing files, change this value: + # + parse_timeout: 5000, + # + # If you want to use uncolored output by default, you can change `color` + # to `false` below: + # + color: true, + # + # You can customize the parameters of any check by adding a second element + # to the tuple. + # + # To disable a check put `false` as second element: + # + # {Credo.Check.Design.DuplicatedCode, false} + # + checks: [ + # + ## Consistency Checks + # + {Credo.Check.Consistency.ExceptionNames, []}, + {Credo.Check.Consistency.LineEndings, []}, + {Credo.Check.Consistency.ParameterPatternMatching, []}, + # This check was erroring on sigils so I had to disable it + {Credo.Check.Consistency.SpaceAroundOperators, false}, + {Credo.Check.Consistency.SpaceInParentheses, []}, + {Credo.Check.Consistency.TabsOrSpaces, []}, + + + # + ## Design Checks + # + # You can customize the priority of any check + # Priority values are: `low, normal, high, higher` + # + {Credo.Check.Design.AliasUsage, false}, + # You can also customize the exit_status of each check. + # If you don't want TODO comments to cause `mix credo` to fail, just + # set this value to 0 (zero). + # + {Credo.Check.Design.TagTODO, false}, + {Credo.Check.Design.TagFIXME, []}, + + # + ## Readability Checks + # + {Credo.Check.Readability.AliasOrder, []}, + {Credo.Check.Readability.FunctionNames, []}, + {Credo.Check.Readability.LargeNumbers, []}, + {Credo.Check.Readability.MaxLineLength, [priority: :low, max_length: 120]}, + {Credo.Check.Readability.ModuleAttributeNames, []}, + {Credo.Check.Readability.ModuleDoc, []}, + {Credo.Check.Readability.ModuleNames, []}, + {Credo.Check.Readability.ParenthesesInCondition, false}, + {Credo.Check.Readability.ParenthesesOnZeroArityDefs, []}, + {Credo.Check.Readability.PredicateFunctionNames, []}, + {Credo.Check.Readability.PreferImplicitTry, []}, + {Credo.Check.Readability.RedundantBlankLines, []}, + {Credo.Check.Readability.Semicolons, []}, + {Credo.Check.Readability.SpaceAfterCommas, []}, + {Credo.Check.Readability.StringSigils, []}, + {Credo.Check.Readability.TrailingBlankLine, []}, + {Credo.Check.Readability.TrailingWhiteSpace, []}, + {Credo.Check.Readability.UnnecessaryAliasExpansion, []}, + {Credo.Check.Readability.VariableNames, []}, + + # + ## Refactoring Opportunities + # + {Credo.Check.Refactor.CondStatements, []}, + {Credo.Check.Refactor.CyclomaticComplexity, false}, + {Credo.Check.Refactor.FunctionArity, false}, + {Credo.Check.Refactor.LongQuoteBlocks, false}, + {Credo.Check.Refactor.MapInto, false}, + {Credo.Check.Refactor.MatchInCondition, []}, + {Credo.Check.Refactor.NegatedConditionsInUnless, []}, + {Credo.Check.Refactor.NegatedConditionsWithElse, []}, + {Credo.Check.Refactor.Nesting, [max_nesting: 5]}, + {Credo.Check.Refactor.UnlessWithElse, []}, + {Credo.Check.Refactor.WithClauses, []}, + + # + ## Warnings + # + {Credo.Check.Warning.BoolOperationOnSameValues, []}, + {Credo.Check.Warning.ExpensiveEmptyEnumCheck, []}, + {Credo.Check.Warning.IExPry, []}, + {Credo.Check.Warning.IoInspect, []}, + {Credo.Check.Warning.LazyLogging, false}, + {Credo.Check.Warning.MixEnv, false}, + {Credo.Check.Warning.OperationOnSameValues, []}, + {Credo.Check.Warning.OperationWithConstantResult, []}, + {Credo.Check.Warning.RaiseInsideRescue, []}, + {Credo.Check.Warning.UnusedEnumOperation, []}, + {Credo.Check.Warning.UnusedFileOperation, []}, + {Credo.Check.Warning.UnusedKeywordOperation, []}, + {Credo.Check.Warning.UnusedListOperation, []}, + {Credo.Check.Warning.UnusedPathOperation, []}, + {Credo.Check.Warning.UnusedRegexOperation, []}, + {Credo.Check.Warning.UnusedStringOperation, []}, + {Credo.Check.Warning.UnusedTupleOperation, []}, + {Credo.Check.Warning.UnsafeExec, []}, + + # + # Checks scheduled for next check update (opt-in for now, just replace `false` with `[]`) + + # + # Controversial and experimental checks (opt-in, just replace `false` with `[]`) + # + # {Credo.Check.Readability.StrictModuleLayout, + # order: [:shortdoc, :moduledoc, :behaviour, :use, :defstruct, :type, :import, :alias, :require], + # ignore: [:module_attribute, :type]}, + {Credo.Check.Readability.StrictModuleLayout, false}, + {Credo.Check.Consistency.MultiAliasImportRequireUse, false}, + {Credo.Check.Consistency.UnusedVariableNames, false}, + {Credo.Check.Design.DuplicatedCode, false}, + {Credo.Check.Readability.AliasAs, false}, + {Credo.Check.Readability.MultiAlias, false}, + {Credo.Check.Readability.Specs, false}, + {Credo.Check.Readability.SinglePipe, false}, + {Credo.Check.Readability.WithCustomTaggedTuple, false}, + {Credo.Check.Refactor.ABCSize, false}, + {Credo.Check.Refactor.Apply, false}, + {Credo.Check.Refactor.AppendSingleItem, false}, + {Credo.Check.Refactor.DoubleBooleanNegation, false}, + {Credo.Check.Refactor.ModuleDependencies, false}, + {Credo.Check.Refactor.NegatedIsNil, false}, + {Credo.Check.Refactor.PipeChainStart, false}, + {Credo.Check.Refactor.VariableRebinding, false}, + {Credo.Check.Warning.LeakyEnvironment, false}, + {Credo.Check.Warning.MapGetUnsafePass, false}, + {Credo.Check.Warning.UnsafeToAtom, false} + + # + # Custom checks can be created using `mix credo.gen.check`. + # + ] + } + ] +} diff --git a/lib/data_layer/data_layer.ex b/lib/data_layer/data_layer.ex index 6828c02..89dd7f5 100644 --- a/lib/data_layer/data_layer.ex +++ b/lib/data_layer/data_layer.ex @@ -535,25 +535,6 @@ defmodule AshBlog.DataLayer do apply(m, f, [changeset | a]) end - defp put_or_insert_new(table, {pkey, record}, resource) do - attributes = resource |> Ash.Resource.Info.attributes() - - case dump_to_native(record, attributes) do - {:ok, casted} -> - case ETS.Set.put(table, {pkey, casted}) do - {:ok, set} -> - {_key, record} = ETS.Set.get!(set, pkey) - cast_record(record, resource) - - other -> - other - end - - other -> - other - end - end - @doc false def dump_to_native(record, attributes) do Enum.reduce_while(attributes, {:ok, %{}}, fn attribute, {:ok, attrs} -> @@ -585,8 +566,7 @@ defmodule AshBlog.DataLayer do @doc false @impl true def update(resource, changeset) do - with {:ok, record} <- Ash.Changeset.apply_attributes(changeset), - {:ok, record} <- + with {:ok, record} <- do_update(changeset, resource), {:ok, record} <- cast_record(record, resource) do file_path = @@ -612,7 +592,7 @@ defmodule AshBlog.DataLayer do {:ok, record - |> Ash.Resource.put_metadata(:ash_blog_file, changeset.data.__metadata__[:ash_blog_file]) + |> Ash.Resource.put_metadata(:ash_blog_file, file_path) |> Ash.Resource.set_meta(%Ecto.Schema.Metadata{state: :loaded, schema: resource})} else {:error, error} -> @@ -630,14 +610,12 @@ defmodule AshBlog.DataLayer do end defp do_update(changeset, resource) do - attributes = resource |> Ash.Resource.Info.attributes() - file_path = changeset.data.__metadata__[:ash_blog_file] || raise "Missing `ash_blog_file` metadata for record, cannot update!" with {:ok, record} <- Ash.Changeset.apply_attributes(changeset), - recore <- + record <- Ash.Resource.set_meta(record, %Ecto.Schema.Metadata{state: :loaded, schema: resource}), {:ok, yaml} <- yaml_frontmatter(record) do File.mkdir_p!(Path.dirname(file_path)) diff --git a/lib/data_layer/file_namer.ex b/lib/data_layer/file_namer.ex index b623732..9162f41 100644 --- a/lib/data_layer/file_namer.ex +++ b/lib/data_layer/file_namer.ex @@ -1,8 +1,13 @@ defmodule AshBlog.FileNamer do + @moduledoc """ + The default file namer, uses the current timestamp and the title attribute of the post in the form `YYYY/YYYY-MM-DD-name.md` + """ def name_file(changeset) do name = - case Ash.Changeset.get_attribute(changeset, :title) || - Ash.Changeset.get_attribute(changeset, :name) do + case Ash.Changeset.get_attribute( + changeset, + AshBlog.DataLayer.Info.title_attribute(changeset.resource) + ) do nil -> nil diff --git a/lib/data_layer/info.ex b/lib/data_layer/info.ex index 03b144b..297c0a8 100644 --- a/lib/data_layer/info.ex +++ b/lib/data_layer/info.ex @@ -53,8 +53,4 @@ defmodule AshBlog.DataLayer.Info do """ end end - - def full_file_name(resource) do - Path.join([folder(resource), file_name(resource)]) - end end diff --git a/mix.lock b/mix.lock index b33f5fb..a936cb7 100644 --- a/mix.lock +++ b/mix.lock @@ -1,5 +1,5 @@ %{ - "ash": {:git, "https://github.com/ash-project/ash.git", "e52d7187d889d3ec3403e7d8bb411f12bed3b103", []}, + "ash": {:git, "https://github.com/ash-project/ash.git", "1718314f40dd9ebad0e169b5c98d9894f45a7f27", []}, "bunt": {:hex, :bunt, "0.2.1", "e2d4792f7bc0ced7583ab54922808919518d0e57ee162901a16a1b6664ef3b14", [:mix], [], "hexpm", "a330bfb4245239787b15005e66ae6845c9cd524a288f0d141c148b02603777a5"}, "certifi": {:hex, :certifi, "2.9.0", "6f2a475689dd47f19fb74334859d460a2dc4e3252a3324bd2111b8f0429e7e21", [:rebar3], [], "hexpm", "266da46bdb06d6c6d35fde799bcb28d36d985d424ad7c08b5bb48f5b5cdd4641"}, "comparable": {:hex, :comparable, "1.0.0", "bb669e91cedd14ae9937053e5bcbc3c52bb2f22422611f43b6e38367d94a495f", [:mix], [{:typable, "~> 0.1", [hex: :typable, repo: "hexpm", optional: false]}], "hexpm", "277c11eeb1cd726e7cd41c6c199e7e52fa16ee6830b45ad4cdc62e51f62eb60c"}, @@ -35,7 +35,7 @@ "providers": {:hex, :providers, "1.8.1", "70b4197869514344a8a60e2b2a4ef41ca03def43cfb1712ecf076a0f3c62f083", [:rebar3], [{:getopt, "1.0.1", [hex: :getopt, repo: "hexpm", optional: false]}], "hexpm", "e45745ade9c476a9a469ea0840e418ab19360dc44f01a233304e118a44486ba0"}, "sobelow": {:hex, :sobelow, "0.11.1", "23438964486f8112b41e743bbfd402da3e5b296fdc9eacab29914b79c48916dd", [:mix], [{:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: false]}], "hexpm", "9897363a7eff96f4809304a90aad819e2ad5e5d24db547af502885146746a53c"}, "sourceror": {:hex, :sourceror, "0.11.2", "549ce48be666421ac60cfb7f59c8752e0d393baa0b14d06271d3f6a8c1b027ab", [:mix], [], "hexpm", "9ab659118896a36be6eec68ff7b0674cba372fc8e210b1e9dc8cf2b55bb70dfb"}, - "spark": {:hex, :spark, "0.2.2", "782989111ef63c76ab02779c1f996f0139b644a688a9f08445a33623f4737ff1", [:mix], [{:nimble_options, "~> 0.4.0", [hex: :nimble_options, repo: "hexpm", optional: false]}, {:sourceror, "~> 0.1", [hex: :sourceror, repo: "hexpm", optional: false]}], "hexpm", "998684022e932b18c1512d2d1ac34938eb719df617e982281a50e4a4ea3fdf93"}, + "spark": {:hex, :spark, "0.2.3", "3678177ca1f1f4c7919da90b49f5e378c39e1bdf2f59ad8909c0c3591fe8dbb6", [:mix], [{:nimble_options, "~> 0.4.0", [hex: :nimble_options, repo: "hexpm", optional: false]}, {:sourceror, "~> 0.1", [hex: :sourceror, repo: "hexpm", optional: false]}], "hexpm", "933dadc7fcce93198104e7d88243772bbde9e54b001929a4c04bc733812e8e3b"}, "ssl_verify_fun": {:hex, :ssl_verify_fun, "1.1.6", "cf344f5692c82d2cd7554f5ec8fd961548d4fd09e7d22f5b62482e5aeaebd4b0", [:make, :mix, :rebar3], [], "hexpm", "bdb0d2471f453c88ff3908e7686f86f9be327d065cc1ec16fa4540197ea04680"}, "stream_data": {:hex, :stream_data, "0.5.0", "b27641e58941685c75b353577dc602c9d2c12292dd84babf506c2033cd97893e", [:mix], [], "hexpm", "012bd2eec069ada4db3411f9115ccafa38540a3c78c4c0349f151fc761b9e271"}, "telemetry": {:hex, :telemetry, "1.1.0", "a589817034a27eab11144ad24d5c0f9fab1f58173274b1e9bae7074af9cbee51", [:rebar3], [], "hexpm", "b727b2a1f75614774cff2d7565b64d0dfa5bd52ba517f16543e6fc7efcc0df48"}, diff --git a/test/support/api.ex b/test/support/api.ex index 2e7cd42..c1ff358 100644 --- a/test/support/api.ex +++ b/test/support/api.ex @@ -1,4 +1,5 @@ defmodule AshBlog.Test.Api do + @moduledoc false use Ash.Api resources do diff --git a/test/support/blog/post.ex b/test/support/blog/post.ex index 6dd8bd7..260c021 100644 --- a/test/support/blog/post.ex +++ b/test/support/blog/post.ex @@ -1,4 +1,5 @@ defmodule AshBlog.Test.Post do + @moduledoc false use Ash.Resource, otp_app: :ash_blog, data_layer: AshBlog.DataLayer