【问题标题】:Thin controller / Thick model in Phoenix/EctoPhoenix/Ecto 中的薄控制器/厚模型
【发布时间】:2017-04-20 02:25:38
【问题描述】:

我试图找出在哪里放置我通常会(在 Rails/ActiveRecord 中)放在模型类中的常用函数。具体来说,我有UserCompany,它们之间存在多对多关系,但用户有一个default_company,它在user_companies 连接表上只有一个布尔标志。

活动记录

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

我可以在 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 查询散布到您的应用程序中,这似乎也是错误的。

【问题讨论】:

    标签: phoenix-framework ecto


    【解决方案1】:

    凤凰 1.3

    从我读到的关于 the upcoming 1.3 的内容来看,似乎期望这将由 Contexts 处理,或者特别是允许您对 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 上下文,还是我创建一个新的@ 987654327@上下文?

    (很抱歉问/回答了我自己的问题,但在研究问题时,我找到了 Phoenix 1.3 的信息,并认为我不妨为任何感兴趣的人发帖。)

    【讨论】:

    • 为什么要道歉?你做了免费的研究。感谢您的努力。
    • 我认为 phx 1.3 中模式的想法是,您可以根据正在使用的上下文为同一个数据库表拥有多个模式。例如,您可能在 Profile 上下文中有一个用户模式,其中包括所有与帐户相关的信息,包括密码哈希。然后,您可能在 Blog 上下文中有一个用户模式,它只定义与帖子所需内容相关的 DB 列。通过将变更集移动到上下文中,我们摆脱了一个包含多个关注点的大型模式文件
    猜你喜欢
    • 1970-01-01
    • 2017-06-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-07-28
    相关资源
    最近更新 更多