我相信这是Rails 3中的一个错误.我希望有人能指引我朝着正确的方向前进.下面发布的代码纯粹是为了说明这个问题.希望这不会混淆问题.
鉴于我有一个Post模型和一个Comment模型.发表has_many评论,评论发表于发帖.
在Post模型上设置default_scope,定义join()和where()关系.在这种情况下,()依赖于连接().
通常帖子不依赖于评论.再说一遍,我只想举一个简单的例子.当where()依赖于join()时,这可能是任何情况.
class Post < ActiveRecord::Base
has_many :comments, :dependent => :destroy
default_scope joins(:comments).where("comments.id < 999")
end
class Comment < ActiveRecord::Base
belongs_to :post, :counter_cache => true
end
Run Code Online (Sandbox Code Playgroud)
运行以下命令:
Post.update_all(:title => Time.now)
Run Code Online (Sandbox Code Playgroud)
生成以下查询,并最终抛出ActiveRecord :: StatementInvalid:
UPDATE `posts` SET `title` = '2010-10-15 15:59:27' WHERE (comments.id < 999)
Run Code Online (Sandbox Code Playgroud)
同样,update_all,delete_all,destroy_all的行为方式相同.当我的应用程序在尝试更新counter_cache时抱怨时,我发现了这种行为.最终深入研究update_all.
我有一种情况,现有应用程序的行为正在发生变化,这让我头疼.
我的应用有照片.照片有一个状态:"batch", "queue", or "complete".应用中的所有现有照片都是"完整的".
99%的时间我只需要显示完整的照片,而在所有现有的代码库中,我需要每次调用照片仅限于完整的照片.
但是,在与上传和分类照片相关的屏幕中,我需要能够相当轻松地覆盖默认范围以显示批量或排队的照片.
像许多其他人一样,我需要找到一种在某些情况下轻松覆盖默认范围的方法.我看着这些问题(1,2),他们似乎并没有回答我要找的.
我希望的代码是这样的:
class Photo < ActiveRecord::Base
...
default_scope where(:status=>'complete')
scope :batch, unscoped.where(:status=>'batch')
scope :queue, unscoped.where(:status=>'queue')
...
end
Run Code Online (Sandbox Code Playgroud)
但是,这不起作用.我尝试在lambdas中包装范围方法,但这也不起作用.
我知道default_scope带有行李,但是如果我不能使用覆盖,那么我正在寻找添加scope :complete ...并且必须梳理我现有应用程序中每次调用照片并添加.complete以过滤未处理的照片.
你会如何解决这个问题?
activerecord named-scope ruby-on-rails default-scope ruby-on-rails-3
我已经看过很多关于这个的帖子,但似乎都没有解决我的问题.我有一个default_scope像这样的模型:
default_scope where(:is_active => true).order('LOWER(table.name)');
Run Code Online (Sandbox Code Playgroud)
我有其他(正常)范围,我想使用创建inactive范围unscoped.我想将它定义为范围,但只有在定义为类方法时才有效:
# works
def self.inactive
unscoped { where(:is_active => false) }
end
# none of these work
scope :inactive, unscoped { where(:is_active => false) }
scope :inactive, with_exclusive_scope { where(:is_active => true) }
scope :inactive, unscoped.where(:is_active => false)
scope :inactive, lambda { unscoped { where(:is_active => false) } }
scope :inactive, unscoped { lambda { where(:is_active => false) } }
unscoped do
scope :inactive, where(:is_active => false)
end
Run Code Online (Sandbox Code Playgroud)
有没有我错过的方法,或者我是否必须使用类方法来定义此范围?
在ActiveRecord中,有一个default_scope类方法来指定默认范围.例如
class User < ActiveRecord::Base
default_scope where(:deleted => false)
end
User.all # => SELECT * FROM users WHERE deleted = 0;
Run Code Online (Sandbox Code Playgroud)
我怎么能这样做Sequel::Model?
编辑:
经过一些谷歌搜索后,我终于找到了一些有用的信息.
class User < Sequel::Model
# Define some "scopes" (filters on the dataset)
dataset_module do
def existing
filter(deleted: false)
end
def active
filter(disabled: false)
end
end
# This is the equivalent to a default_scope. Set one of the datasets
# as the default dataset for this model.
set_dataset(self.active)
end
Run Code Online (Sandbox Code Playgroud)
生成的查询如下所示:
User.all # => …Run Code Online (Sandbox Code Playgroud) 我有一个如下模型设置:
class User
has_many :items
has_many :words, :through => :items
end
class Item
belongs_to :user
belongs_to :word
default_scope where(:active => true)
end
class Words
has_many :items
end
Run Code Online (Sandbox Code Playgroud)
我遇到的问题是default_scope没有应用于以下关联:
user.words
Run Code Online (Sandbox Code Playgroud)
而不是这个SQL:
SELECT `words`.* FROM `words` INNER JOIN `items` ON `words`.id = `items`.word_id WHERE ((`items`.user_id = 1)) AND ((`items.active = 1))
Run Code Online (Sandbox Code Playgroud)
我在日志中得到这个SQL:
SELECT `words`.* FROM `words` INNER JOIN `items` ON `words`.id = `items`.word_id WHERE ((`items`.user_id = 1))
Run Code Online (Sandbox Code Playgroud)
我认为这是因为默认范围适用于常规模型及其子关联,但不适用于连接表.
使连接表范围在关联之间工作而不需要指定它的正确Rails方法是什么?有人存在吗?
scope ruby-on-rails has-and-belongs-to-many has-many-through default-scope
我找不到太多关于在yii中将默认范围应用于模型的文档,我想知道是否有人可以解释或指出我正确的方向.
我的问题的快速版本:
是否可以向默认范围添加关系,或者默认情况下为模型上的每个AR搜索添加"with"条件?
我的问题的长版本:
我的应用程序的快速摘要:
我有两个型号,provider和item.它有:1关系,其中提供者可以有许多项目,但每个项目只能有一个提供者.
到目前为止,我有这些关系:
class Provider extends CActiveRecord
{
...
public function relations()
{
return array(
'items' => array(self::HAS_MANY, 'Item', 'id_provider', 'order'=>'rank DESC'),
);
}
...
}
class Item extends CActiveRecord
{
...
public function relations()
{
return array(
'provider' => array(self::BELONGS_TO, 'Provider', 'id_provider'),
);
}
...
}
Run Code Online (Sandbox Code Playgroud)
在我的项目模型中,我已经有了一个defaultScope来过滤掉所有离线项目(即只显示设置为的项目offline = false):
public function defaultScope()
{
$alias = $this->getTableAlias(false,false);
return array(
'condition'=>"`$alias`.`offline` = false",
);
}
Run Code Online (Sandbox Code Playgroud)
我现在要做的是,还过滤掉其提供者设置为离线的项目(即仅显示provider.offline = false当前项目旁边的项目item.offline …
我的应用不仅有用户,还有管理员和超级管理员.由于所有三个共享相同的属性,我只想使用一个具有附加属性"角色"的表,可以是"user","admin"或"super_admin":
class User < ActiveRecord::Base
# with nickname and password
end
class Admin < User
def power
puts "admin rights"
end
end
class SuperAdmin < Admin
def superpower
puts "I've got the #{power}!"
end
end
Run Code Online (Sandbox Code Playgroud)
现在我想做一些事情SuperAdmin.all,只得到SuperAdmins.使用default_scope似乎让我在那里:
class SuperAdmin < Admin
default_scope where(["role = ?", "super_admin"])
# ...
end
Run Code Online (Sandbox Code Playgroud)
现在我也将一个default_scope添加到Admin:
class Admin < User
default_scope where(["role = ?", "admin"])
# ...
end
Run Code Online (Sandbox Code Playgroud)
Aaaand ... SuperAdmin.all不再返回任何内容.这是为什么?
我正在使用paranoia gem 来“软删除”记录。现在,我需要为关联模型立即加载这些记录,其中一些记录可能已被删除。Paranoia 将其添加default_scope到“偏执”模型中:
default_scope :conditions => { :deleted_at => nil }
Run Code Online (Sandbox Code Playgroud)
所以实际上,我有这些(简化的)模型:
class Product
has_many :orders
default_scope :conditions => { :deleted_at => nil }
end
class Order
belongs_to :product
end
Run Code Online (Sandbox Code Playgroud)
我想要实现的是在访问订单时立即加载产品:
Order.includes(:product)
Run Code Online (Sandbox Code Playgroud)
这(来自如何在 Rails3 中的关联关系上使用无作用域?)在这里不起作用:
Product.unscoped { Order.includes(:product) }
Run Code Online (Sandbox Code Playgroud)
我知道我可以创建自定义belongs_to关系来添加条件(如“渴望加载嵌套关联和作用域”),但我找不到删除现有关系的方法(如果可能的话)。
问题:如何防止将默认范围应用于急切加载查询?
我有一个 Rails 4 应用程序,它使用 Devise 3.4 进行身份验证,我已经自定义了禁止用户的功能(使用简单的布尔列users.banned,默认为 false)。该User模型还有一个default_scope只返回非禁止用户的。
问题是——我仍然希望我的被禁用户能够登录,即使他们在登录后不能做任何事情。(他们基本上只是看到一个页面说“你被禁了”)。但似乎default_scope正在绊倒Devise。当您登录或调用 eg 时authenticate_user!,Devise 尝试使用基本 ActiveRecord 方法之一(如find或 )查找当前用户find_by,但不能,因为它们位于默认范围之外。因此,Devise 得出该用户不存在的结论,并且登录失败。
如何让设计忽略默认范围?
给定一个带有__附件的模型Post,附件有一个隐藏的标志.在整个应用程序中,我想轻松地说post.attachments并且只获得可见的,所以我在Attachment模型中设置了一个默认范围(使用squeel):
default_scope -> { where { (hidden != true) | (hidden == nil) } }
Run Code Online (Sandbox Code Playgroud)
但是管理页面需要能够查看帖子的所有附件,而不仅仅是可见的附件(因此您可以切换隐藏的复选框).执行此操作的默认方式(在admin/posts.rb中)使用default_scope,只允许我编辑可见的:
f.has_many :attachments do |a|
...
end
Run Code Online (Sandbox Code Playgroud)
我知道我可以不使用default_scope而是命名它:可见,然后到处(管理页面除外)说post.attachments.visible但我不喜欢这样做.
如何取消管理页面上的子附件?
我尝试以下列方式定义default_scope:
default_scope :joins => :product, :select => "catalog_products.*, products.*"
Run Code Online (Sandbox Code Playgroud)
我从Rails得到的是这样的:
SELECT catalog_products.* FROM `catalog_products` INNER JOIN `products` ON `products`.id = `catalog_products`.product_id
Run Code Online (Sandbox Code Playgroud)
当我将它定义为named_scope时,一切都很好:
named_scope :extended, :joins => :product, :select => "catalog_products.*, products.*"
SELECT catalog_products.*, products.* FROM `catalog_products` INNER JOIN `products` ON `products`.id = `catalog_products`.product_id
Run Code Online (Sandbox Code Playgroud)
这应该是一个错误还是一个正确的行为?
我正在使用Rails 2.3.4.
谢谢!
我想知道你如何在模型上有多个默认范围(排序),例如我有一个评论模型,需要按日期和批准进行排序:
default_scope :order => 'approved ASC', :order => 'date ASC'
Run Code Online (Sandbox Code Playgroud)
那么你如何将这两种订单都放在模型上,所以我首先按批准订购,然后按日期订购.
干杯!
我一直在寻找这个并且似乎无法找到答案,虽然我认为如果你对Rails比我更有经验,那应该是一个非常简单的解决方案.我正在尝试将多个default_scope条件添加到我的产品模型中.我的产品型号文件如下:
class Product < ApplicationRecord
has_many :order_items
default_scope { where(active: true) }
validates :name, presence: true, length: { maximum: 300 }
PRICE_REGEXP = /\A\d{1,4}(\.\d{0,2})?\z/
validates :price, presence: true,
numericality: true,
format: { with: PRICE_REGEXP }
validates :description, presence: true, length: { maximum: 1000 },
allow_nil: true
end
Run Code Online (Sandbox Code Playgroud)
我想补充一点
default_scope -> { order(created_at: desc) }
Run Code Online (Sandbox Code Playgroud)
所以产品索引页面上的新产品的格式是最新的.我在任何时候执行以下操作时都会收到语法错误消息:
default_scope -> { order(created_at: desc) }, { where(active: true) }
Run Code Online (Sandbox Code Playgroud)
要么
default_scope -> { order(created_at: desc), where(active: true) }
Run Code Online (Sandbox Code Playgroud)
要么
default_scope -> { order(created_at: desc) …Run Code Online (Sandbox Code Playgroud) default-scope ×13
activerecord ×6
named-scope ×2
activeadmin ×1
destroy ×1
devise ×1
inheritance ×1
model ×1
relation ×1
ruby ×1
scope ×1
scopes ×1
sequel ×1
sql ×1
warden ×1
yii ×1