(ArgumentError)无法为<association>生成输入

时间:2019-05-28 18:32:54

标签: elixir phoenix-framework ecto

在嵌套表单上呈现变更集错误时存在一些问题。

表单呈现:

def new(conn, _) do
  changeset = Organizations.Organization.create_organization_changeset(%Organization{workspace: %Workspace{}})
  render(conn, "new.html", changeset: changeset)
end

表单最初呈现良好:

<%= form_for @changeset, signup_path(@conn, :create), fn f -> %>

  <%= text_input f, :name, class: "form-control", required: true, autofocus: true %>
  <%= label f, :organization_name %>
  <%= error_tag f, :name %>

  <%= inputs_for f, :workspace, fn w -> %>
    <%= text_input w, :subdomain, required: true %>
    <%= error_tag w, :subdomain %>
  <% end %>

<% end %>

提交此表单将调用create_organization/1

def create_organization(attrs) do
  Ecto.Multi.new()
  |> Ecto.Multi.run(:organization, fn(_repo, _result) ->
    changeset = Organization.create_organization_changeset(%Organization{}, attrs)
    tenant = Ecto.Changeset.get_field(changeset, :slug)
    Repo.insert(changeset, prefix: TenantActions.build_prefix(tenant))
  end)
  |> Ecto.Multi.run(:workspace, fn(_repo, %{organization: organization}) ->
    attrs = %{subdomain: attrs["workspace"]["subdomain"}, organization_id: organization.id}

    %Workspace{}
    |> Workspace.changeset(attrs)
    |> put_assoc(:organization, organization)
    |> Repo.insert()
  end)
  |> Repo.transaction()
end

“幸福的道路”行之有效。但是,如果workspace发生变更集错误,例如:

#Ecto.Changeset<
  action: :insert,
  changes: %{
    name: "test",
    organization: #Ecto.Changeset<action: :update, changes: %{}, errors: [],
     data: #Organizations.Organization<>, valid?: true>,
    organization_id: 1,
    subdomain: "democompany",
    tenant: "test"
  },
  errors: [
    unique_subdomains: {"That workspace URL is not available.",
     [constraint: :unique, constraint_name: "unique_subdomains"]}
  ],
  data: #Workspaces.Workspace<>,
  valid?: false
>

结果是:

(ArgumentError) could not generate inputs for :workspace from Workspaces.Workspace. Check the field exists and it is one of embeds_one, embeds_many, has_one, has_many, belongs_to or many_to_many

工作区架构:

schema "workspaces" do
  field :subdomain, :string
  belongs_to :organization, Pricetable.Organizations.Organization

  timestamps(type: :utc_datetime_usec)
end

组织架构:

schema "organizations" do
  ...
  field :workspace_id, :integer
  has_one :workspace, Workspaces.Workspace
end

1 个答案:

答案 0 :(得分:0)

错误消息显示:

** (ArgumentError) could not generate inputs for :workspace from Workspaces.Workspace

因此,我假设您正在传递@changeset中的工作区,而不是组织。然后inputs_for尝试从工作空间获取工作空间。因此,我将确保@changeset实际上是一个组织。

此外,对于multi和inputs_for来说使用起来都有些尴尬。 inputs_for通常与cast_assoc/cast_embed一起使用,后者会在内部为您设置多重播放,因此您无需手动进行操作。此处更多信息:http://blog.plataformatec.com.br/2015/08/working-with-ecto-associations-and-embeds/

或者,您放下inputs_for并分别使用两个变更集。