Giter VIP home page Giter VIP logo

params's People

Contributors

accua avatar andykingking avatar astery avatar greg-rychlewski avatar iamjarvo avatar jgautsch avatar johnhamelink avatar kianmeng avatar lasseebert avatar mahcloud avatar nirev avatar take-five avatar tiagopog avatar vic avatar ziinc avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

params's Issues

Modules defined in `nofile`

Consider this example:

defmodule MyParams do
  use Params.Schema, %{
    nested: %{
      foo: :integer
    }
  }
end

It will define a nested schema in a module called MyParams.Nested.

However, it seems that it will be defined in a "wrong" context. It's source is set to "nofile", which I have had a few problems with:

  • Sometimes when I compile my app, it will warn about redefining the nested module
  • Code coverage tools does not handle it (errors on missing nofile file).

I have tried to fix it in Params.Def but was not able to get something working.

I think the main problem is that the macro chain is "broken" by some normal functions, which means that the module is actually created on runtime and not compiletime (because the macro expansion stopped).

I see different solutions but was not able to implement them without messing with the current code more than I wanted to:

  • Get the __CALLER__ in the original __using__ macro and pass that on to Params.Def. Then create module with something like Module.create(name, quoted_content, Macro.Env.location(caller))
  • Use macros all the way down to where the module is created, so that it will be fuilly expanded on compiletime.

Release latest version to hex

Hi,

i'd like to use #30 in our codebase. For this it would be great to have a new release on hex.
The last one there is 2.1.1 which is from january 2019.

Thanks in advance.

Default value for time/dates?

Is there any way to specify a default value for a field of type time? e..g Set ~T[16:30:00] as a default value?

I tried:

[field: :time, default: ~T[16:30:00]]

But it throws an error: ** (CompileError) nofile: invalid quoted expression: ~T[16:30:00]

String booleans do not get converted

Hi i've uncovered a bug relating to booleans.

String booleans do not get converted (although normal behaviour of Ecto.Changeset is to convert "true" into true)

# in MyController
defmodule MyController do
  defparams(
    index_params(%{
      page: [field: :integer, default: 1],
      per_page: [field: :integer, default: 15],
      has_errors: :boolean,
      is_approved: [field: :boolean, default: false]
    })
  )
end

# check params received by controller
iex> IO.inspect(params)
%{"is_approved" => "true"}

# check changeset data
iex> IO.inspect(changeset.data)
%Params.MyController.IndexParams{
  __meta__: #Ecto.Schema.Metadata<:built, "params Elixir.Params.MyController.IndexParams">,
  _id: nil,
  has_errors: nil,
  is_approved: false,     <--- this should be true
  page: 1,
  per_page: 15
}

I've checked params_test.exs and there is no test suite that coveres booleans

:atom not included in the types

Hi, big fan of this library for typecasting.

I notice that the atom type is not provided and raises an invalid type error, is this expected behaviour? Was hoping to cast strings to atoms automatically.

(ArgumentError) invalid or unknown type :atom for field :status

Stacktrace:
  │ (ecto 3.7.1) lib/ecto/schema.ex:2201: Ecto.Schema.check_field_type!/4
  │ (ecto 3.7.1) lib/ecto/schema.ex:1881: Ecto.Schema.__field__/4
  │ (stdlib 3.16.1) erl_eval.erl:685: :erl_eval.do_apply/6
  │ (stdlib 3.16.1) erl_eval.erl:123: :erl_eval.exprs/5
  │ (stdlib 3.16.1) erl_eval.erl:919: :erl_eval.try_clauses/8
  │ (stdlib 3.16.1) erl_eval.erl:123: :erl_eval.exprs/5Elixir

Compile error when using defparams macro in module that uses Phoenix.Component

Phoenix.Component overrides the def and defp macros to annotate function heads with some pattern matching.
I believe because defparams creates a new method by calling Module.eval_quoted/2 this is somehow evaluating the ast returned by Phoenix.Component's def macro prematurely(? - tbh, I don't grok this perfectly yet)

But the error can be seen with code like the following:

defmodule MyMod do
  use Phoenix.Component
  use Params

  defparams fleeno %{some: :string}

  def hi do
    IO.puts("Hello")
  end
end
error: cannot invoke remote function Phoenix.Component.Declarative.__pattern__!/2 inside a match
  nofile:1: MyMod.util_2/1

Is there a reason I'm not understanding that the defparams macro is using Module.eval_quoted/2 rather than just defining the method directly?

In other words, can't

  Module.eval_quoted(__MODULE__, quote do
     def unquote(name)(params) do
       unquote(module_name).from(params)
     end
  end)

Just be written as

  def unquote(name)(params) do
    unquote(module_name).from(params)
  end

In my own experiments it seems to work fine, but I'm not sure if I'm missing something.

(Of course, I could just call the macro before I use Phoenix.Component, but perhaps there's a more comprehensive fix)

No longer working with Ecto 2.0-beta

Hey there,

The breaking changes introduced in 2.0-beta have caused params to break (thankfully its tests also break in the same way). I'm working on a PR to fix this right now, but in the meantime, here's the sort of errors I'm experiencing:

Compiled lib/params/def.ex
** (Protocol.UndefinedError) protocol Enumerable not implemented for :id
    (elixir) lib/enum.ex:1: Enumerable.impl_for!/1
    (elixir) lib/enum.ex:116: Enumerable.reduce/3
    (elixir) lib/enum.ex:1486: Enum.reduce/3
    test/params_test.exs:10: (module)
    test/params_test.exs:8: (module)
== Compilation error on file lib/params.ex ==
** (CompileError) lib/params.ex:77: unknown key :model for struct Ecto.Changeset
    (elixir) src/elixir_map.erl:185: :elixir_map."-assert_struct_keys/5-lc$^0/1-0-"/5
    (elixir) src/elixir_map.erl:62: :elixir_map.translate_struct/4
    (stdlib) lists.erl:1353: :lists.mapfoldl/3

Reusable embeds in `use Params.Schema, %{}`

Just as suggestion or maybe I missing something and this can be already achieved:

defmodule SomeIdentityParams do
  use Params.Schema
  import App.Params.Helpers

  @fields ~w(id code)
  schema do
    field :id, :id
    field :code, :string
    # more here
  end

  def changeset(changeset, params) do
    cast(changeset, params, @fields)
    |> at_least_one_should_be_present([:id, :code])
  end
end

# this one looks fine
defmodule SomeControllerParams do
  use Params.Schema
  @fields ~w(tarif_id some_identity)a

  schema do
    field :tarif_id, :id
    embeds_one :some_identity, SomeIdentityParams
  end

  def changeset(cs, params) do
    cast(cs, params, @fields)
    |> validate_required(@fields)
    |> cast_embed(:passenger, required: true)
  end
end

# but it can be much shorter
defmodule SomeControllerParams do
  use Params.Schema, %{
    tarif_id: :id,
    some_identity: SomeIdentityParams
  }
end

Params.to_map behaviour for missing fields.

Both to_map and data have the behaviour that it's not possible to see if nil was submitted for a field or if that field was not submitted at all.

It makes sense that data behaves that way, since it returns a struct. But with to_map, I would expect it to use the schema as whitelist and not add extra fields unless default is used.

Maybe this should be a different function than to_map?

My usecase is an API endpoint that can update a resource. Something like this:

defmodule MyAPIEndpoint do
  defmodule MyParams do
    use Params.Schema, %{
      id!: :integer,
      name: string,
      owner_id: :integer
    }
  end

  def call(params) do
    changeset = MyParams.from(params)
    if changeset.valid? do
      attributes = Params.to_map(changeset)
      MyRepo.update_attributes(attributes)
    end
  end
end

So I want to update only the submitted keys. In this case it should be possible to update owner_id to the value nil.

Again, I will be happy to help with the implementation. Just wanted your oppinion before getting started ;)

Default values?

Thanks for a great library. I'm just learning Elixir, so I might miss something obvious here.

Is it possible to somehow specify default values in a schema?

I have something like this:

defparams index_params %{
  filter: %{
    foo_id: :integer,
    bar_id: :integer
  },
  page: %{
    number: :integer,
    size: :integer
  },
  sort: :string
}

filter is not required, but it should default to %{}.
page is not required, but it should default to e.g. %{number: 1, size: 20}.
sort is not required, and should default to e.g. "id"

I could of course write a function that adds the default values, but since Ecto.Schema supports this it could be nice to somehow specify it directly in the schema.

Feature Request: Put functions in the schema values

I love this library, but I almost never build my own changeset validation functions because it's too cumbersome. I usually just use with after using params validation for types.

However, I think that it would be awesome if we could put validation functions in the schema. Could we somehow detect those and build a changeset validation out of functions, as long as they have the right call signature?

defparams asdf %{
  x!: fn :x, x -> is_integer(x) and x > 0 end,
  y!: :string,
}

This would satisfy the other 20% of api validation that I need. I'm happy to take a stab at this, if you guys think that it's feasible and desirable.

Default params with plain `use Params.Schema`

Hello, here is my issue:

defmodule MyParams do
  use Params.Schema

  schema do
    field :count, :integer, default: 1
  end
end

changeset = MyParams.from(%{})
assert %{count: 1} = Params.to_map(changeset) # but it is %{}

Restructure README

In my opinion, the README contains too much back story that you have to wade through before getting to the basic usage of the package. Everybody is interested in the basic usage, but only some people are interested in the back story. I suggest moving the "Usage" section to near the top of the document.

I'd be happy to make this into a PR.

Becoming a maintainer

Hi, vic.

I'm interested in to be a maintainer of params.

I:

  • love open source.
  • love Elixir.

Know more about me at my website.

If there are any other requirements, let me know. ;)

Elixir 1.11 Compiler Warning

When compiling this library using Elixir v 1.11 you get the following warning:

warning: Ecto.Changeset.validate_required/2 defined in application :ecto is used by the current application but the current application does not depend on :ecto. To fix this, you must do one of:
  1. If :ecto is part of Erlang/Elixir, you must include it under :extra_applications inside "def application" in your mix.exs
  2. If :ecto is a dependency, make sure it is listed under "def deps" in your mix.exs
  3. In case you don't want to add a requirement to :ecto, you may optionally skip this warning by adding [xref: [exclude: [Ecto.Changeset]]] to your "def project" in mix.exs
  lib/params.ex:145: Params.changeset/2

This can be solved by changing

def application do
    [applications: [:logger]]
  end

to

def application do
    [extra_applications: [:logger]]
  end

in mix.exs. Please see here for more info: https://hexdocs.pm/mix/1.11.4/Mix.Tasks.Compile.App.html

I will submit a pull request to fix this.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.