【问题标题】:How to write a custom model in elixir / phoenix without being object-oriented?如何在不面向对象的情况下在 elixir/phoenix 中编写自定义模型?
【发布时间】:2016-02-13 18:06:08
【问题描述】:

我正在使用 Phoenix 框架构建一个小测试应用程序。我不能使用 Ecto,因为我的数据库不受支持。但我仍然想要 MVC 模式。所以我需要一种方法来实现自定义模型。因为我来自 RoR,所以我总是发现自己在思考面向对象的编程模式,在这种模式中你有一个类定义和实例,这些实例具有你可以获取和设置的属性。所以这样的事情是可能的:

@mike = User.new
@mike.name = "Mike Power"
@mike.save

# ect

但这显然不是 Elixir 的工作原理。

我很难思考如何解决这个问题。实施应该允许我:

  • 有属性
  • 存储值
  • 处理值
  • 验证值
  • 将它们保存到我的数据库中

到目前为止,我想出的最好方法是使用结构。所以是这样的:

defmodule User do
  defstruct name: "", age: 0

  def sayhello do
    IO.puts "Hi, I am #{name}"
    # This is not working, I just put it here to make a point
  end
end 

tim = %User{}
# -> %User{age: 0, name: ""}
tim = %User{name: "Tim Turbo", age: 25}
# -> %User{age: 25, name: "Tim Turbo"}
tim.name
# -> "Tim Turbo"

# We can also change the values 
tim = %User{name: "Michael"}
# -> %User{age: 25, name: "Michael"}

# It also makes sure that only the values defined in the struct can be set (which is nice)

tom = %User{unknown: "something"}
# ** (CompileError) iex:11: unknown key :unknown for struct User

使用vex 我什至可以很容易地实现验证

defmodule User do
  defstruct username: nil, password: nil, password_confirmation: nil
  use Vex.Struct

  validates :username, presence: true,
                       length: [min: 4],
                       format: ~r/^[[:alpha:]][[:alnum:]]+$/
  validates :password, length: [min: 4],
                       confirmation: true
end

所以我基本上是在问:

  • 这是要走的路吗?还是有更好的?
  • 我是否会在我的用户模块中实现将用户实际保存到数据库的功能?我只是输入参数的地方

类似这样的:

user = %User{params}
User.create user

【问题讨论】:

标签: elixir phoenix-framework


【解决方案1】:

我对恢复 OO 父子化思维方式的想法:

尝试围绕数据以及您需要如何处理数据来构建您的逻辑。不是您需要创建和修改的对象。

以“Say Hello”为例:

defmodule UserWelcomer do
  def sayhello(user) do
    IO.puts "Hi, I am #{user.name}"
  end
end 

基本上,您一直在努力发挥作用,并通过不同的功能处理“用户”数据。

抱歉,这不是答案。只是超出评论限制的评论。

【讨论】:

    【解决方案2】:

    这已经有一年多了,但我认为一个好的答案会帮助其他在谷歌上偶然发现这个的人......

    这是要走的路吗?还是有更好的?

    你在正确的轨道上!数据存储在结构中,而不是对象中。看一下关于模型验证的Ecto.Changeset docs 和关于在结构中存储数据的Ecto.Schema docs。这与您正在做的事情非常相似。

    还需要注意的是,您可以使用您想要的 Ecto 组件(例如 ChangesetSchema),而不必使用不适用于您的应用程序的东西,例如 Ecto.Repo

    我是否会在我的用户模块中实现将用户实际保存到数据库的功能?我只是输入参数的地方

    在这一点上,这几乎是一个哲学问题。以 Ecto 为例:

    • 带有 Ecto 的“模型”(至少在 Phoenix 中使用,可能是最常见的情况)实际上只是一个 Ecto.Schema,它具有一些用于变更集和验证的额外功能。
    • 保存或更新(持久性)由使用 Ecto.Repo 的单独模块处理。

    将这些结果组合成更像 Ruby on Rails 的 ActiveRecord 的东西,人们发现它更难测试,而这种分离有助于使您的模型非常容易测试。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2014-05-02
      • 2012-04-10
      • 2017-10-17
      • 2017-10-29
      • 1970-01-01
      • 1970-01-01
      • 2010-10-03
      • 1970-01-01
      相关资源
      最近更新 更多