Phoenix / Ecto中的薄控制器/厚模型

时间:2017-04-19 18:25:39

标签: phoenix-framework ecto

我试图弄清楚我通常(在Rails / ActiveRecord中)放置在模型类中的常用函数的放置位置。具体来说,我UserCompany之间存在多对多关系,但用户有一个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查询,这似乎也是错误的。

1 个答案:

答案 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的信息,并认为我也可以发帖给任何感兴趣的人。)