我有两个型号 - Organization
和User
组织有许多用户,也属于一个所有者(老板是User
模型太)。在父对象的多个关联保存一个模型一次
我报名形式组织,在那里用户可以为组织和name
和password
为user
进入name
(user
是在形式上organization
嵌套对象)。成功注册后,我需要有一个Organization
及相关的owner
(User
模型),并且此user
应属于此组织。所以基本上,创建用户应该是owner
,并且在注册后应该在has_many :users
关联列表中。
我已成功创建以用户作为所有者关联的组织,但我希望用户在创建后也可以在has_many :users
关联中。在Rails中,我只需为此用户添加after_create
回调并设置organization_id
,但由于ecto没有回调,我应该如何执行此操作?我已经阅读了关于Ecto.Multi
,但我不确定它是否正确(对我来说看起来像是矫枉过正)并且不确定它如何用于这种情况。
为了以防万一,这里是我的模型和注册表单的代码。
defmodule HappyClient.Organization do
use HappyClient.Web, :model
schema "organizations" do
field :name, :string
belongs_to :owner, HappyClient.User, foreign_key: :owner_id
has_many :users, HappyClient.User
timestamps()
end
def changeset(struct, params \\ %{}) do
struct
|> cast(params, [:name])
|> validate_required([:name])
end
def registration_changeset(struct, params) do
struct
|> changeset(params)
|> cast_assoc(:owner, required: true, with: &HappyClient.User.registration_changeset/2)
end
end
用户模型
defmodule HappyClient.User do
use HappyClient.Web, :model
schema "users" do
field :email, :string
field :name, :string
field :password_hash, :string
field :is_admin, :boolean, default: false
field :is_operator, :boolean, default: false
belongs_to :organization, HappyClient.Organization
field :password, :string, virtual: true
timestamps()
end
@required_fields ~w(email name)a
@optional_fields ~w(is_admin is_operator)a
def changeset(struct, params \\ %{}) do
struct
|> cast(params, @required_fields)
|> validate_required([:email, :name])
|> validate_format(:email, ~r/@/)
|> assoc_constraint(:organization)
end
def registration_changeset(struct, params) do
struct
|> changeset(Map.merge(params, %{"is_admin" => true}))
|> cast(params, [:password], [])
|> validate_required([:password])
|> validate_length(:password, min: 6, max: 100)
|> hash_password
end
defp hash_password(changeset) do
case changeset do
%Ecto.Changeset{valid?: true,
changes: %{password: password}} ->
put_change(changeset,
:password_hash,
Comeonin.Bcrypt.hashpwsalt(password))
_ ->
changeset
end
end
end
注册形式
<h1>Registration</h1>
<%= form_for @changeset, organization_path(@conn, :create), fn f -> %>
<%= if @changeset.action do %>
<div class="alert alert-danger">
<p>There are some errors</p>
</div>
<% end %>
<div class="form-group">
<%= text_input f, :name, placeholder: "Organization Name", class: "form-control" %>
<%= error_tag f, :name %>
</div>
<div class="form-group">
<%= inputs_for f, :owner, fn of -> %>
<%= text_input of, :name, placeholder: "Name" %>
<%= error_tag of, :name %>
<%= text_input of, :email, placeholder: "Email" %>
<%= error_tag of, :email %>
<%= password_input of, :password, placeholder: "Password" %>
<%= error_tag of, :password %>
<% end %>
</div>
<%= submit "Create Organization", class: "btn btn-primary" %>
<% end %>