2016-01-07 47 views

回答

4

有幾種方法可以做到這一點。其中一人需要外生主(即將外生V2.0),是通過簡單直接更新父:

# Assuming a child_changeset with the parent loaded 
child_changset = Ecto.Changeset.put_assoc(child_changeset, :parent, %{updated_at: Ecto.DateTime.utc}) 

現在,當孩子堅持着,它會自動更改傳播到父。

或者,你可以使用外生V1.1與prepare_changes和update_all傳播的變化:

# Assuming a child_changeset 
Ecto.Changeset.prepare_changes child_changeset, fn changeset -> 
    query = Ecto.assoc(changeset.model, :parent) 
    changeset.repo.update_all query, set: [updated_at: ^Ecto.DateTime.utc] 
    changeset 
end 

在這個例子中,我們使用的是在一個事務中沿着孩子的變化建立一個執行prepare_changes表示父模型的查詢,併爲與查詢匹配的模塊發出update_all更新所有updated_at列。

1

您可以向變更集中添加一個函數來檢查變更以及它們是否有效(這是通過父變更集更新關聯)。

def touch_parent(%{changes: changes, valid: true}=changeset) when map_size(changes) > 0 do 
    updated_at = DateTime.utc_now() |> DateTime.to_naive() 
    cast(changeset, %{updated_at: updated_at}, [:updated_at]) 
end 
def touch_parent(changeset), do: changeset 

你可以把你的update_changeset函數模型的結尾。

def update_changeset(%Model{}=model, attrs) do 
    model 
    # casting 
    |> touch_parent() 
end 

如果你想只是做你會做這樣的事情的具體關聯:

def touch_parent(%{changes: changes, valid: true) when map_size(changes) > 0 do 
    updated_at = DateTime.utc_now() |> DateTime.to_naive() 
    changed_fields = Map.keys(changes) 
    cond do 
    :association in changed_fields -> 
     cast(changeset, %{updated_at: updated_at}, [:updated_at]) 
    true -> changeset 
    end 
end 

:)