我试图弄清楚我通常(在Rails / ActiveRecord中)放置在模型类中的常用函数的放置位置。具体来说,我User
和Company
之间存在多对多关系,但用户有一个default_company
,它在user_companies
上只有一个布尔标志加入表。
ActiveRecord的
class User < ActiveRecord::Base
belongs_to :user_companies
has_many :companies, through: :user_companies
def default_company
# Filter through companies to find the one that I want
end
end
(注意,这可能是一种更简单的方法,但这是基本的想法。)
外生
我可以在Ecto中做类似的事情,如下:
defmodule MyApp.User do
use MyApp.Web, :model
alias MyApp.{Company, CompaniesUser}
schema "users" do
has_many :companies_users, CompaniesUser, on_delete: :delete_all
many_to_many :companies, Company, join_through: "companies_users"
end
def default_company(%User{} = user) do
from(company in Company,
join: cu in CompaniesUser,
where: cu.company_id == company.id
and cu.user_id == ^user.id
and cu.default_company == true
) |> first() |> Repo.one()
end
end
然而,根据我有限的经验,这似乎是不正确的。我看到的所有示例都保持Ecto模型非常有限,只是一堆changeset
方法和一些验证代码,但严格来说没有任何业务相关。有人谈到将业务逻辑与数据库逻辑分开。我得到了并尊重它,但大多数示例都显示将原始Ecto查询放在控制器中,或者在整个应用程序中散布Ecto查询,这似乎也是错误的。
答案 0 :(得分:4)
凤凰1.3
从我所读到的the upcoming 1.3开始,看起来期望这将通过上下文来处理,或者具体地说,是允许您进行逻辑分组的模块您的Ecto架构模型以及定义(手动:您定义它)API以访问持久层的相关模块。因此,使用我上面的示例,它将类似于:
defmodule MyApp.Account do
alias MyApp.Account.User
alias MyApp.Corporate.{Company, CompaniesUser}
def default_company(%User{} = user) do
from(company in Company,
join: cu in CompaniesUser,
where: cu.company_id == company.id
and cu.user_id == ^user.id
and cu.default_company == true
) |> first() |> Repo.one()
end
end
defmodule MyApp.Account.User do
use MyApp.Web, :model
alias MyApp.Corporate.{Company, CompaniesUser}
schema "users" do
has_many :companies_users, CompaniesUser, on_delete: :delete_all
many_to_many :companies, Company, join_through: "companies_users"
end
end
它有2个模块,其中一个(MyApp.Account.User
)是我的原始Ecto架构。另一个(MyApp.Account
)是我的应用程序中所有其他逻辑的API /入口点,如控制器。
我想我喜欢这个理论,但是我担心要弄清楚应该去哪些模型,比如这个示例:Company
是否属于Account
上下文,或者创建新的Corporate
上下文?
(很抱歉提出/回答我自己的问题,但在研究这个问题时,我找到了凤凰1.3的信息,并认为我也可以发帖给任何感兴趣的人。)