【问题标题】:Ecto.Repo.delete/2: When looking at a type specification, how do you know if there is a default value?Ecto.Repo.delete/2:查看类型规范时,如何知道是否存在默认值?
【发布时间】:2020-05-21 04:01:27
【问题描述】:

这是类型说明:

iex(1)> h Ecto.Repo.delete
No documentation for function Ecto.Repo.delete was found, but there is a callback with the same name.
You can view callback documentations with the b/1 helper.

iex(2)> b Ecto.Repo.delete
@callback delete(
            struct_or_changeset :: 
              Ecto.Schema.t() | Ecto.Changeset.t(),
            opts :: Keyword.t()
          ) ::
            {:ok, Ecto.Schema.t()}
            | {:error, Ecto.Changeset.t()}

Deletes a struct using its primary key.

If the struct has no primary key,
Ecto.NoPrimaryKeyFieldError will be raised. If the struct
has been removed from db prior to call,
Ecto.StaleEntryError will be raised.

It returns {:ok, struct} if the struct has been
successfully deleted or {:error, changeset} if there was a
validation or a known constraint error.

## Options

  • :prefix - The prefix to run the query on (such as
    the schema path in Postgres or the database in MySQL).
    This overrides the prefix set in the query and any
    @schema_prefix set in the schema.
  • :stale_error_field - The field where stale errors
    will be added in the returning changeset. This option
    can be used to avoid raising Ecto.StaleEntryError.
  • :stale_error_message - The message to add to the
    configured :stale_error_field when stale errors happen,
    defaults to "is stale".

See the "Shared options" section at the module
documentation.

## Example

    post = MyRepo.get!(Post, 42)
    case MyRepo.delete post do
      {:ok, struct}       -> # Deleted with success
      {:error, changeset} -> # Something went wrong
    end 

在最后的例子中,delete() 是用一个参数调用的。而且,我可以用一个参数成功调用delete()

  def delete_item(%Auction.Item{}=item) do
    @repo.delete(item)  #<=== HERE
  end

所以,这告诉我第二个参数必须有一个默认值。有没有办法以某种方式知道这一点?

【问题讨论】:

    标签: elixir phoenix-framework


    【解决方案1】:

    浏览文档和similar question's answer,类型规范似乎不支持默认参数。 2014 年的This Github issue 解释了对此类功能的一些权衡。

    如何知道第二个参数是可选的?除了对 Elixir 代码进行源代码挖掘之外,希望它被记录在案。对于这个版本的Ecto.Repo.delete,参数在类型规范中被命名为opts,并在标题“选项”下进行了描述,这对我来说强烈暗示它们是可选的。

    【讨论】:

      【解决方案2】:

      这取决于回调是如何实现的。

      您不能在回调规范中使用默认参数,但您可以使用实现回调的默认参数定义一个函数。

      defmodule Converter do
        @doc """
        Callback doc.
        """
        @callback convert(number(), any(), any()) :: number()
      end
      
      defmodule MyConverter do
        @behaviour Converter
      
        def convert(number, from_unit \\ :km, to_unit \\ :miles) do
          # ...
        end
      end
      
      

      但是,IEx.Helpers.h 宏无法实际显示默认参数是什么,因为它适用于明确定义的文档。

      在上面的例子中,只定义了回调规范的@doc,所以会显示出来。

      iex> h MyConverter.convert
      @callback convert(number(), any(), any()) :: number()
      
      Callback doc.
      

      您实际上需要为实现回调的函数定义@doc 以实现您想要的。

      defmodule MyConverter do
        @behaviour Converter
      
        @doc """
        Implementation docs.
        """
        def convert(number, from_unit \\ :km, to_unit \\ :miles) do
          # ...
        end
      end
      
      iex> h MyConverter.convert
      
                  def convert(number, from_unit \\ :km, to_unit \\ :miles)
      
      Implementation docs.
      

      现在与您的问题中概述的情况相关:使用Ecto.Repo 时,它在MyApp.Repo 模块中定义了一个实现delete 回调但没有模块文档的函数。这就是为什么您无法通过 IEx 帮助程序查看此函数的默认参数的原因。

      【讨论】:

        猜你喜欢
        • 2011-03-10
        • 2010-11-03
        • 2022-01-05
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2014-05-31
        • 1970-01-01
        • 2020-07-08
        相关资源
        最近更新 更多