使用多态关联时,是否可以在仅存在于某些类型中的子模型上运行包含?
例:
class Container
belongs_to :contents, :polymorphic => true
end
class Food
has_one :container
belongs_to :expiration
end
class Things
has_one :container
end
Run Code Online (Sandbox Code Playgroud)
在视图中我想要做的事情如下:
<% c = Containers.all %>
<% if c.class == Food %>
<%= food.expiration %>
<% end %>
Run Code Online (Sandbox Code Playgroud)
因此,当我加载c时,我想急切加载到期,因为我知道我将需要最后一个.有没有办法这样做?只定义一个常规:include得到我的错误,因为并非所有封闭类型都有子模型到期.
ruby-on-rails include polymorphic-associations eager-loading rails-activerecord
好的,我对这一点感到非常难过.我正在尝试构建按类别组织的已发布网页的菜单.
Category.rb:
belongs_to :parent, :class_name => "Category", :foreign_key => "parent_id"
has_many :children, :class_name => "Category", :foreign_key => "parent_id"
has_many :pages, :documents, :galleries
Run Code Online (Sandbox Code Playgroud)
Page.rb
belongs_to :category
Run Code Online (Sandbox Code Playgroud)
Page模型也有:is_published,所以我也试图对它进行过滤.我不愿意发布我的微弱查询尝试,但除了乞求更聪明的人之外,没有其他解决方案:
(自我是@current_website)
self.categories.includes(:children, :pages).where('pages.is_published = 1')
Run Code Online (Sandbox Code Playgroud)
这主要返回我需要的内容,但不返回没有发布页面的父类别.例如,如果我有:
Parent Category
- Published Page
- Child Category
-- Published Page
Run Code Online (Sandbox Code Playgroud)
失败的地方是我父母没有发布的页面,如下所示:
Parent Category
- Child Category
-- Published Page
- Child Category
-- Published Page
Run Code Online (Sandbox Code Playgroud)
在此先感谢任何帮助.我正在尽可能多地学习有关查询的内容,但我在这方面已经反对了.
更新:实现KandadaBoggu的建议已经产生了更好的结果,这被添加到Category.rb
has_many :published_pages, :class_name => "Page",
:conditions => {:is_published => true}
Run Code Online (Sandbox Code Playgroud)
但是,使用以下内容时:
self.categories.where(:parent_id => nil).includes({:children => :published_pages},
:published_pages)
Run Code Online (Sandbox Code Playgroud)
我得到了我需要的结果,但我也得到了空的父类别(没有published_pages,没有已发布页面的子类别.例如:
- Parent …Run Code Online (Sandbox Code Playgroud) 我怎样才能destroy_all在阵列上运行?
我有以下查询:
spam_users = User.find_by_sql("SELECT * FROM users WHERE email ~* '21cn.com'")
Run Code Online (Sandbox Code Playgroud)
我试过跑spam_users.destroy_all但是得到了undefined method 'destroy_all' for #<Array:0x10b09ce30>.
我在这个特定的应用程序中运行Rails 2.3.8以及PostgreSQL.
我在没有rails的ruby项目中使用ActiveRecord.我需要为表定义复合主键.通常,迁移会自动创建主键.是否可以使用活动记录为表定义自己的复合主键?
我开始使用Postgres UUID类型用于我所有模型的id字段.非常好用,并且在Rails 4中支持(大部分):
create_table :users, id: :uuid do |t|
# ...
end
Run Code Online (Sandbox Code Playgroud)
问题是,如果您尝试查找id为X的行,但Postgres将引发错误,但X不是格式正确的UUID字符串.
> User.find "3ac093e2-3a5e-4744-b49f-117b032adc6c"
ActiveRecord::RecordNotFound # good, will cause a 404
> User.find "foobar"
PG::InvalidTextRepresentation: ERROR # bad, will cause a 500
Run Code Online (Sandbox Code Playgroud)
因此,如果我的用户位于URL中UUID所在的页面上,然后他们尝试更改UUID,则会得到500错误而不是404.或者他们可能会获得一个不再存在的对象的链接.
我怎样才能以干燥的方式避免这种情况?我不能只是拯救PG::InvalidTextRepresentation和渲染404,因为其他东西也可能导致这个错误.
UPDATE
我认为ID参数格式的正则表达式是干净的,如果它不匹配则会引发404:
resources :users, id: /uuid-regex-here/
Run Code Online (Sandbox Code Playgroud)
但我仍然有待保持干燥的问题; 我不想把它放在我的路线中的每一个资源上.我可以在一个语句中声明多个资源,但前提是不要像成员操作那样使用其他选项.所以也许更好的问题是:有没有办法为所有路由设置id正则表达式?
postgresql ruby-on-rails rails-postgresql ruby-on-rails-4 rails-activerecord
我有以下ActiveRecord模型:
class Person
belongs_to :favourite_car, class_name: 'Car'
belongs_to :business_car, class_name: 'Car'
belongs_to :home_car, class_name: 'Car'
end
Run Code Online (Sandbox Code Playgroud)
当我想访问所有这三个关联时,它会生成三个选择查询:
SELECT * FROM cars WHERE cars.id = ?
Run Code Online (Sandbox Code Playgroud)
这基本上是N + 1问题.
理想情况下,我希望它只生成一个表单查询
SELECT * FROM cars WHERE cars.id IN (?, ?, ?)
Run Code Online (Sandbox Code Playgroud)
我可以将它移动到has_many :through => :join_table与连接表中的列的关联,以指示关联类型是什么,然后用于includes([:join_table, :cars])急切加载关联.但是,在这种情况下,它只将3个查询减少到2,并引入了一个额外的表.
另一种可能的解决方案是手动加载关联,如下所示:
module EagerLoader
def eager_load(*associations)
reflections = associations.map { |association| self.class.reflections[association.to_sym] }
raise 'Not all are valid associations' if reflections.any?(&:nil?)
reflections.group_by { |association| association.klass }.each do |klass, …Run Code Online (Sandbox Code Playgroud) 我知道如何在已创建的迁移文件中添加默认值.即
`rails generate migration AddTestColumnToTesttable test_status:boolean` to create it.
Run Code Online (Sandbox Code Playgroud)
它将生成此迁移:
class AddTestColumnToTable < ActiveRecord::Migration
def change
add_column :table, :test_status, :boolean, :default => true
end
end
Run Code Online (Sandbox Code Playgroud)
但是,我们可以通过rails g migration命令本身添加默认值吗?
我为角色定义了Enum:
enum role: {ordinary: 0, manager: 1, admin: 2}
Run Code Online (Sandbox Code Playgroud)
我想按以下顺序订购一组对象:
admin (first all admins)
ordinary (then all ordinaries)
manager (and lastly all managers)
Run Code Online (Sandbox Code Playgroud)
这有可能吗?
enums activerecord ruby-on-rails rails-activerecord ruby-on-rails-5
是否可以将一个方法委托给has_manyrails中的关联,并且仍然按照demeter定律保存该关联上的预加载数据?目前在我看来,你被迫选择其中一个.即:通过NOT委托保留预加载的数据,或丢失预加载的数据和委托.
示例:我有以下两个模型:
class User < ApplicationRecord
has_many :blogs
delegate :all_have_title?, to: :blogs, prefix: false, allow_nil: false
def all_blogs_have_title?
blogs.all? {|blog| blog.title.present?}
end
end
class Blog < ApplicationRecord
belongs_to :user
def self.all_have_title?
all.all? {|blog| blog.title.present?}
end
end
Run Code Online (Sandbox Code Playgroud)
注意:这User#all_blogs_have_title?与委托方法完全相同all_have_title?.
根据我的理解,以下内容违反了德米特定律.但是:它维护您的预加载数据:
user = User.includes(:blogs).first
User Load (0.1ms) SELECT "users".* FROM "users" ORDER BY "users"."id" ASC LIMIT ? [["LIMIT", 1]]
Blog Load (0.1ms) SELECT "blogs".* FROM "blogs" WHERE "blogs"."user_id" = 1
=> #<User id: 1, name: "all yes", …Run Code Online (Sandbox Code Playgroud) ruby activerecord ruby-on-rails associations rails-activerecord
我想要创建的是索引之一,其中一些列被索引,另一些列被包含。PostgreSQL 在其文档中描述了这种索引
创建索引的 SQL 查询看起来像CREATE INDEX tab_x_y ON tab(x) INCLUDE (y);
在此处查看 ActiveRecord PostgreSQL 适配器文档
我没有看到任何使用此INCLUDE列功能的选项。
我必须将其作为原始 SQL 查询运行吗?还有别的办法吗?
笔记
activerecord ×3
postgresql ×3
ruby ×3
associations ×1
enums ×1
include ×1
mysql ×1
rubygems ×1