Rails 4 个范围 has_many
Rails 4 scope has_many
我有两个模型
class Portfolio < ActiveRecord::Base
has_many :project_types, dependent: :destroy
end
class ProjectType < ActiveRecord::Base
belongs_to :portfolio
end
ProjectType 模型有字段 ptype
。它可以是 'web' 或 'mobile' 等。
如何使用范围获取所有 'web' 或 'mobile' 投资组合?
按照 Rails 4.1 方法,我会将我的 ptype 字段视为一个枚举并写成:
class ProjectType < ActiveRecord::Base
belongs_to :portfolio
enum ptype: { web: 'web', mobile: 'mobile' }
end
这会给你:
ProjectType.web
ProjectType.mobile
基于 ptype 获取对象的范围,但也会为您提供其他有用的方法,例如:
@projectType.web?
@projectType.web!
请参考文档:http://api.rubyonrails.org/v4.1/classes/ActiveRecord/Enum.html
在这里您询问如何检索 "web" Portfolio
我假设您的意思是“所有项目类型至少为 ptype 'Web'.
然后我会这样写:
Portfolio.joins(:project_types).merge(ProjectType.web)
查看文档:http://apidock.com/rails/ActiveRecord/SpawnMethods/merge
在最后的改进中,您可以从中创建一个范围:
class Portfolio
has_many :project_types
scope :web, -> { joins(:project_types).merge(ProjectType.web) }
end
然后只调用
Portfolio.web
为您的模型添加适当的范围:
# in models/project_type.rb
class ProjectType < ActiveRecord::Base
belongs_to :portfolio
scope :web, -> { where(ptype: 'web') }
end
要加载类型为 web
的投资组合,仅使用该范围与控制器中的连接:
# in the controller
@web_portfolios = Portfolio.joins(:project_types).merge(ProjectType.web)
您可以对两者都有明确的范围,或者您可以有一个范围根据 ptype 为您选择,或者您可以为数据库中的每个唯一 ptype 元编程一个范围。如果您要添加各种不同的 "ptypes",您可以执行以下任一操作,这将为您提供处理任何 "ptypes":
的范围
scope :ptype, -> (ptype) { where(ptype: ptype) }
称为:
ProjectType.ptype('web')
或
class ProjectType < ActiveRecord::Base
self.pluck(:ptype).each do |ptype|
scope ptype.gsub(/\s+/,"_").downcase.to_sym, -> { where(ptype: ptype) }
end
end
我不推荐这个,我也不推荐其中的每个 "string"(例如 ProjectType.web 或 ProjectType.mobile)单独的范围。最好的平衡是将字符串值传递到一个范围内,该范围可检索您要查找的内容。只是我的意见,我相信其他人对此有不同的看法。
老实说,我认为 ptype 字段对于枚举器来说已经成熟了——这将使您的代码更加清晰,并定义该字段实际期望的内容,而不是允许将任何字符串随机放置在那里。所以像:
class ProjectType < ActiveRecord::Base
enum ptype: [:web, :mobile]
scope :ptype, -> (ptype) { where(ptype: self.ptypes[ptype] }
end
然后这样调用:
ProjectType.ptype(:web)
我认为这里或上面介绍的这些解决方案中的任何一个都不再存在 "right",除了为存储在数据库中的 ptype 字段中的每个字符串生成范围的元编程解决方案。
最后,这是您的投资组合范围:
class Portfolio < ActiveRecord::Base
scope :by_ptype, -> (ptype) { joins(:project_type).merge(ProjectType.ptype(ptype) }
end
然后这样调用:
Portfolio.by_ptype(:web)
你可以这样做
class Portfolio < ActiveRecord::Base
has_many :project_types, dependent: :destroy
scope :ptype, -> (p_type) { includes(:project_types).where(project_types: {ptype: p_type}) }
end
你可以打电话给
Portfolio.ptype('web')
我有两个模型
class Portfolio < ActiveRecord::Base
has_many :project_types, dependent: :destroy
end
class ProjectType < ActiveRecord::Base
belongs_to :portfolio
end
ProjectType 模型有字段 ptype
。它可以是 'web' 或 'mobile' 等。
如何使用范围获取所有 'web' 或 'mobile' 投资组合?
按照 Rails 4.1 方法,我会将我的 ptype 字段视为一个枚举并写成:
class ProjectType < ActiveRecord::Base
belongs_to :portfolio
enum ptype: { web: 'web', mobile: 'mobile' }
end
这会给你:
ProjectType.web
ProjectType.mobile
基于 ptype 获取对象的范围,但也会为您提供其他有用的方法,例如:
@projectType.web?
@projectType.web!
请参考文档:http://api.rubyonrails.org/v4.1/classes/ActiveRecord/Enum.html
在这里您询问如何检索 "web" Portfolio
我假设您的意思是“所有项目类型至少为 ptype 'Web'.
然后我会这样写:
Portfolio.joins(:project_types).merge(ProjectType.web)
查看文档:http://apidock.com/rails/ActiveRecord/SpawnMethods/merge
在最后的改进中,您可以从中创建一个范围:
class Portfolio
has_many :project_types
scope :web, -> { joins(:project_types).merge(ProjectType.web) }
end
然后只调用
Portfolio.web
为您的模型添加适当的范围:
# in models/project_type.rb
class ProjectType < ActiveRecord::Base
belongs_to :portfolio
scope :web, -> { where(ptype: 'web') }
end
要加载类型为 web
的投资组合,仅使用该范围与控制器中的连接:
# in the controller
@web_portfolios = Portfolio.joins(:project_types).merge(ProjectType.web)
您可以对两者都有明确的范围,或者您可以有一个范围根据 ptype 为您选择,或者您可以为数据库中的每个唯一 ptype 元编程一个范围。如果您要添加各种不同的 "ptypes",您可以执行以下任一操作,这将为您提供处理任何 "ptypes":
的范围scope :ptype, -> (ptype) { where(ptype: ptype) }
称为:
ProjectType.ptype('web')
或
class ProjectType < ActiveRecord::Base
self.pluck(:ptype).each do |ptype|
scope ptype.gsub(/\s+/,"_").downcase.to_sym, -> { where(ptype: ptype) }
end
end
我不推荐这个,我也不推荐其中的每个 "string"(例如 ProjectType.web 或 ProjectType.mobile)单独的范围。最好的平衡是将字符串值传递到一个范围内,该范围可检索您要查找的内容。只是我的意见,我相信其他人对此有不同的看法。
老实说,我认为 ptype 字段对于枚举器来说已经成熟了——这将使您的代码更加清晰,并定义该字段实际期望的内容,而不是允许将任何字符串随机放置在那里。所以像:
class ProjectType < ActiveRecord::Base
enum ptype: [:web, :mobile]
scope :ptype, -> (ptype) { where(ptype: self.ptypes[ptype] }
end
然后这样调用:
ProjectType.ptype(:web)
我认为这里或上面介绍的这些解决方案中的任何一个都不再存在 "right",除了为存储在数据库中的 ptype 字段中的每个字符串生成范围的元编程解决方案。
最后,这是您的投资组合范围:
class Portfolio < ActiveRecord::Base
scope :by_ptype, -> (ptype) { joins(:project_type).merge(ProjectType.ptype(ptype) }
end
然后这样调用:
Portfolio.by_ptype(:web)
你可以这样做
class Portfolio < ActiveRecord::Base
has_many :project_types, dependent: :destroy
scope :ptype, -> (p_type) { includes(:project_types).where(project_types: {ptype: p_type}) }
end
你可以打电话给
Portfolio.ptype('web')