で私は2つのモデルを持っている - Organization
とUser
機関は、多くのユーザーを持っており、また(所有者があまりにもUser
モデルである)1つの所有者に属します。保存一つのモデルに一度
Iは、ユーザが組織とname
とuser
ためpassword
ためname
を入力することができる組織、(user
フォームでorganization
ためのネストされたオブジェクトである)のためのフォームをサインアップしています。登録に成功した後、owner
(User
モデル)のOrganization
が必要です。また、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
Userモデル
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 %>