我最近开始实习.我的雇主在轨道上使用ruby,我经常遇到我需要了解的新语法.我已经google了解了对named_scope的一个很好的解释,但到目前为止我发现的主要是博客文章,对它给予高度赞扬,而不是直接的定义或介绍.
在rails上的ruby中究竟是named_scope(现在简称为scope)?
我有一个Rails 3项目.有了Rails 3,Arel就能够重用一个范围来构建另一个范围.我想知道在定义关系时是否有办法使用范围(例如"has_many").
我有记录,其中有权限列.我想构建一个default_scope,它将我的权限列考虑在内,以便过滤记录(甚至通过关系访问的记录).
目前,在Rails 3中,default_scope(包括我发现的补丁)没有提供传递proc的可行方法(我需要后期变量绑定).是否可以定义一个可以传递命名范围的has_many?
重用命名范围的想法如下:
Orders.scope :my_orders, lambda{where(:user_id => User.current_user.id)}
has_many :orders, :scope => Orders.my_orders
Run Code Online (Sandbox Code Playgroud)
或隐式编码关系中命名范围的内容如下所示:
has_many :orders, :scope => lambda{where(:user_id => User.current_user.id)}
Run Code Online (Sandbox Code Playgroud)
我只是尝试将default_scope应用于后期绑定.我更喜欢使用Arel方法(如果有的话),但会使用任何可行的选项.
由于我指的是当前用户,因此我不能依赖于最后一刻未评估的条件,例如:
has_many :orders, :conditions => ["user_id = ?", User.current_user.id]
Run Code Online (Sandbox Code Playgroud) 我的班级有以下范围Collection:
scope :with_missing_coins, joins(:coins).where("coins.is_missing = ?", true)
Run Code Online (Sandbox Code Playgroud)
我可以跑步Collection.with_missing_coins.count并得到一个结果 - 它很棒!目前,如果我想获得不丢失硬币的收藏品,我会添加另一个范围:
scope :without_missing_coins, joins(:coins).where("coins.is_missing = ?", false)
Run Code Online (Sandbox Code Playgroud)
我发现自己写了很多这些"相反"的范围.是否有可能在不牺牲可读性或求助于lambda /方法(需要true或false作为参数)的情况下获得范围的反面?
像这样的东西:
Collection.!with_missing_coins
Run Code Online (Sandbox Code Playgroud) 如何测试Rails命名范围?您是否测试从作用域返回的结果,或者您的查询是否正确配置?
如果我有一个User类如下的.admins方法:
class User < ActiveRecord::Base
def self.admins
where(admin: true)
end
end
Run Code Online (Sandbox Code Playgroud)
我可能会确保我得到我期望的结果:
describe '.admins' do
let(:admin) { create(:user, admin: true) }
let(:non_admin) { create(:user, admin: false) }
let(:admins) { User.admins }
it 'returns admin users' do
expect(admins).to include(admin)
expect(admins).to_not include(non_admin)
end
end
Run Code Online (Sandbox Code Playgroud)
我知道这会导致对数据库的命中,但如果我想测试范围的行为,我真的没有看到任何其他选择.
但是,最近我看到通过确认它们的配置正确而不是返回的结果集来确定范围.对于此示例,类似于:
describe '.admins' do
let(:query) { User.admins }
let(:filter) { query.where_values_hash.symbolize_keys }
let(:admin_filter) { { admin: true } }
it 'filters for admin users' do
expect(filter).to eq(admin_filter) # …Run Code Online (Sandbox Code Playgroud) 假设有3个模型:A,B和C.这些模型中的每一个都具有该x属性.
是否可以在模块中定义命名范围并将此模块包含在A,B和C中?
我试图这样做,并收到一条错误消息,scope表示无法识别...
我正在尝试创建一个使用连接的named_scope,但是虽然生成的SQL看起来正确,但结果却是垃圾.例如:
class Clip < ActiveRecord::Base
named_scope :visible, {
:joins => "INNER JOIN series ON series.id = clips.owner_id INNER JOIN shows on shows.id = series.show_id",
:conditions=>"shows.visible = 1 AND clips.owner_type = 'Series' "
}
Run Code Online (Sandbox Code Playgroud)
(一个Clip由一个系列拥有,一个系列属于一个Show,一个Show可以是可见的或不可见的).
Clip.all:
SELECT * FROM `clips`
Run Code Online (Sandbox Code Playgroud)
Clip.visible.all:
SELECT * FROM `clips` INNER JOIN series ON series.id = clips.owner_id INNER JOIN shows on shows.id = series.show_id WHERE (shows.visible = 1 AND clips.owner_type = 'Series' )
Run Code Online (Sandbox Code Playgroud)
这看起来还不错.但是得到的Clip模型数组包含一个ID不在数据库中的Clip - 它取而代之的是一个show ID.我哪里错了?
我正在使用最新的mongoid ......
我如何做这个活动记录named_scope的mongoid等价物:
class Comment
include Mongoid::Document
include Mongoid::Timestamps
embedded_in :post
field :body, :type => String
named_scope :recent, :limit => 100, :order => 'created_at DESC'
...
end
Run Code Online (Sandbox Code Playgroud) 我在访问范围时遇到此错误.
这是AR模型
class StatisticVariable < ActiveRecord::Base
attr_accessible :code, :name
has_many :statistic_values
scope :logins, where(code: 'logins').first
scope :unique_logins, where(code: 'unique_logins').first
scope :registrations, where(code: 'registrations').first
end
Run Code Online (Sandbox Code Playgroud)
当我尝试使用StatisticVariable.logins或任何其他范围时,它给出:
NoMethodError: undefined method `default_scoped?'
Run Code Online (Sandbox Code Playgroud)
如果我将范围配置为类方法,那么它可以完美地工作.
def self.registrations
where(code: 'registrations').first
end
Run Code Online (Sandbox Code Playgroud)
请指导我理解并解决这个问题.
我正在使用will_paginate进行分页,到目前为止一直运行良好,除了这一件事.
例如,如果我尝试对范围进行分页
class User < ActiveRecord::Base
named_scope :scope, lambda { etc }
end
User.scope.paginate({:page => params[:page], :per_page => 10})
Run Code Online (Sandbox Code Playgroud)
这将告诉我paginate是一个未定义的方法.我宁愿不仅仅为这个范围使用第二种解决方案,我能在这做些什么吗?
以下问题:
我需要类似空范围的东西.这意味着此范围是emtpy,但响应范围通常响应的所有方法.我目前正在使用一些肮脏的黑客.我只是提供"1 = 0"作为条件.我觉得这很难看,因为它击中了数据库.简单地返回一个空数组是行不通的,因为结果必须响应作用域方法.
有没有更好的现有解决方案或我需要自己编码?
也许一些示例代码可以帮助解释我需要的东西:
class User < ActiveRecord::Base
named_scope :admins, :conditions => {:admin => true }
named_scope :none_dirty, :conditions => "1=0" # this scope is always empty
def none_broken
[]
end
def self.sum_score # okay, a bit simple, but a method like this should work!
total = 0
self.all.each do |user|
total += user.score
end
return total
end
end
User.admin.sum_score # the score i want to know
User.none_drity.sum_score # works, but hits the db
User.none_broken.sum_score # ...error, since …Run Code Online (Sandbox Code Playgroud) named-scope ×10
ruby-on-rails ×10
activerecord ×3
ruby ×2
arel ×1
class-method ×1
mongodb ×1
mongoid ×1
rspec ×1
scope ×1