如何在不面向对象的情况下在 elixir / phoenix 中编写自定义模型?
How to write a custom model in elixir / phoenix without being object-oriented?
我正在使用 Phoenix Framework 构建一个小测试应用程序。我不能使用 Ecto,因为我的数据库不受支持。但我仍然想要 MVC 模式。所以我需要一种方法来实现自定义模型。因为我来自 RoR,所以我总是发现自己在思考面向对象的编程模式,在这种模式中,您有一个 class 定义和具有您可以获取和设置的属性的实例。所以这样的事情是可能的:
@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
我对恢复 OO 父子化思维方式的看法:
尝试围绕数据构建您的逻辑以及您需要对数据做什么。不是您需要创建和修改的对象。
以"Say Hello"为例:
defmodule UserWelcomer do
def sayhello(user) do
IO.puts "Hi, I am #{user.name}"
end
end
基本上,您一直在努力发挥作用,并通过不同的功能处理 "User" 数据。
抱歉,这不是答案。只是超出评论限制的评论。
这已经超过一年了,但我认为一个好的答案会帮助那些在 google...
上偶然发现这个问题的人
Is this the way to go? Or is there a better one?
你走对了!数据存储在结构中,而不是对象中。查看 Ecto.Changeset docs regarding model validations and Ecto.Schema docs 关于在结构中存储数据的内容。这与您正在做的非常相似。
同样重要的是要注意,您可以使用所需的 Ecto 组件(例如 Changeset
和 Schema
),而不必使用不适用于您的应用程序的组件,例如 Ecto.Repo
.
And would I implement the function to actually save the user to the database also in my User module? Where I just enter the parameters
在这一点上,这几乎更像是一个哲学问题。以 Ecto 为例:
- 带有 Ecto 的 "model"(至少在 Phoenix 中使用,可能是最常见的情况)实际上只是一个
Ecto.Schema
,它具有一些用于变更集和验证的额外功能。
- 保存或更新(持久性)由使用
Ecto.Repo
. 的单独模块处理
将这些结果组合成更像 Ruby on Rails' ActiveRecord 的东西,人们发现它更难测试,而这种分离有助于使您的模型非常容易测试。
我正在使用 Phoenix Framework 构建一个小测试应用程序。我不能使用 Ecto,因为我的数据库不受支持。但我仍然想要 MVC 模式。所以我需要一种方法来实现自定义模型。因为我来自 RoR,所以我总是发现自己在思考面向对象的编程模式,在这种模式中,您有一个 class 定义和具有您可以获取和设置的属性的实例。所以这样的事情是可能的:
@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
我对恢复 OO 父子化思维方式的看法:
尝试围绕数据构建您的逻辑以及您需要对数据做什么。不是您需要创建和修改的对象。
以"Say Hello"为例:
defmodule UserWelcomer do
def sayhello(user) do
IO.puts "Hi, I am #{user.name}"
end
end
基本上,您一直在努力发挥作用,并通过不同的功能处理 "User" 数据。
抱歉,这不是答案。只是超出评论限制的评论。
这已经超过一年了,但我认为一个好的答案会帮助那些在 google...
上偶然发现这个问题的人Is this the way to go? Or is there a better one?
你走对了!数据存储在结构中,而不是对象中。查看 Ecto.Changeset docs regarding model validations and Ecto.Schema docs 关于在结构中存储数据的内容。这与您正在做的非常相似。
同样重要的是要注意,您可以使用所需的 Ecto 组件(例如 Changeset
和 Schema
),而不必使用不适用于您的应用程序的组件,例如 Ecto.Repo
.
And would I implement the function to actually save the user to the database also in my User module? Where I just enter the parameters
在这一点上,这几乎更像是一个哲学问题。以 Ecto 为例:
- 带有 Ecto 的 "model"(至少在 Phoenix 中使用,可能是最常见的情况)实际上只是一个
Ecto.Schema
,它具有一些用于变更集和验证的额外功能。 - 保存或更新(持久性)由使用
Ecto.Repo
. 的单独模块处理
将这些结果组合成更像 Ruby on Rails' ActiveRecord 的东西,人们发现它更难测试,而这种分离有助于使您的模型非常容易测试。