说`Post`是一个模型,一个class继承自rails中的`ApplicationRecord`。那么,Post.arel_table.create_table_alias 有什么作用呢?
say `Post` is a model, a class that inherits from `ApplicationRecord`, in rails. Then, what does Post.arel_table.create_table_alias does?
假设我有这个代码:
new_and_updated = Post.where(:published_at => nil).union(Post.where(:draft => true))
post = Post.arel_table
Post.from(post.create_table_alias(new_and_updated, :posts))
我从关于 arel 的 post 中获得了这段代码,但并没有真正解释 create_table_alias
的作用。只有最后的结果是一个活动的 activeRecord::Relation
对象,这是先前定义的联合的结果。为什么需要传递 :posts
作为 create_table_alias
的第二个参数,这是数据库中 table 的名称吗?
来自Rails官方文档,from
查询方法是这样做的:
Specifies table from which the records will be fetched.
因此,为了从 new_and_updated
关系中获取帖子,我们需要一个别名 table,这就是 post.create_table_alias(new_and_updated, :posts)
所做的。
Rubydoc for Arel's create_table_alias
方法告诉我们实例方法包含在Table
模块中。
此处 :posts
参数指定要创建的别名 table 的名称,而 new_and_updated
提供 ActiveRecord::Relation 对象。
希望对您有所帮助。
Arel
的本质如下
alias = Arel::Table.new(table_name)
table = Arel::Nodes::As.new(table_definition,alias)
这为新的 table 定义创建了一个 SQL 别名,以便我们可以在查询中引用它。
TL;DR
让我们根据您发布的代码解释这是如何工作的。
new_and_updated= Post.where(:published_at => nil).union(Post.where(:draft => true))
这个语句可以转换成下面的SQL
SELECT
posts.*
FROM
posts
WHERE
posts.published_at IS NULL
UNION
SELECT
posts.*
FROM
posts
WHERE
posts.draft = 1
这是一个很好的查询,但是您不能 select 从它作为子查询而没有语法错误。这是别名出现的地方,所以这一行(如上文所述 Arel
)
post.create_table_alias(new_and_updated, :posts)
变成
(SELECT
posts.*
FROM
posts
WHERE
posts.published_at IS NULL
UNION
SELECT
posts.*
FROM
posts
WHERE
posts.draft = 1) AS posts -- This is the alias
现在包装 Post.from
可以从这个子查询 select 这样最终的查询是
SELECT
posts.*
FROM
(SELECT
posts.*
FROM
posts
WHERE
posts.published_at IS NULL
UNION
SELECT
posts.*
FROM
posts
WHERE
posts.draft = 1) AS posts
顺便说一句,如果您使用 rails 5,您的查询可以稍微简化,这也消除了对其余代码的需要,例如
Post.where(:published_at => nil).or(Post.where(:draft => true))
会变成
SELECT
posts.*
FROM
posts
WHERE
posts.published_at IS NULL OR posts.draft = 1
假设我有这个代码:
new_and_updated = Post.where(:published_at => nil).union(Post.where(:draft => true))
post = Post.arel_table
Post.from(post.create_table_alias(new_and_updated, :posts))
我从关于 arel 的 post 中获得了这段代码,但并没有真正解释 create_table_alias
的作用。只有最后的结果是一个活动的 activeRecord::Relation
对象,这是先前定义的联合的结果。为什么需要传递 :posts
作为 create_table_alias
的第二个参数,这是数据库中 table 的名称吗?
来自Rails官方文档,from
查询方法是这样做的:
Specifies table from which the records will be fetched.
因此,为了从 new_and_updated
关系中获取帖子,我们需要一个别名 table,这就是 post.create_table_alias(new_and_updated, :posts)
所做的。
Rubydoc for Arel's create_table_alias
方法告诉我们实例方法包含在Table
模块中。
此处 :posts
参数指定要创建的别名 table 的名称,而 new_and_updated
提供 ActiveRecord::Relation 对象。
希望对您有所帮助。
Arel
的本质如下
alias = Arel::Table.new(table_name)
table = Arel::Nodes::As.new(table_definition,alias)
这为新的 table 定义创建了一个 SQL 别名,以便我们可以在查询中引用它。
TL;DR
让我们根据您发布的代码解释这是如何工作的。
new_and_updated= Post.where(:published_at => nil).union(Post.where(:draft => true))
这个语句可以转换成下面的SQL
SELECT
posts.*
FROM
posts
WHERE
posts.published_at IS NULL
UNION
SELECT
posts.*
FROM
posts
WHERE
posts.draft = 1
这是一个很好的查询,但是您不能 select 从它作为子查询而没有语法错误。这是别名出现的地方,所以这一行(如上文所述 Arel
)
post.create_table_alias(new_and_updated, :posts)
变成
(SELECT
posts.*
FROM
posts
WHERE
posts.published_at IS NULL
UNION
SELECT
posts.*
FROM
posts
WHERE
posts.draft = 1) AS posts -- This is the alias
现在包装 Post.from
可以从这个子查询 select 这样最终的查询是
SELECT
posts.*
FROM
(SELECT
posts.*
FROM
posts
WHERE
posts.published_at IS NULL
UNION
SELECT
posts.*
FROM
posts
WHERE
posts.draft = 1) AS posts
顺便说一句,如果您使用 rails 5,您的查询可以稍微简化,这也消除了对其余代码的需要,例如
Post.where(:published_at => nil).or(Post.where(:draft => true))
会变成
SELECT
posts.*
FROM
posts
WHERE
posts.published_at IS NULL OR posts.draft = 1