我遇到动态有效管理范围的问题。我正在尝试为每个"经理"创建一个范围。一个"项目"在我的应用程序中但是,在创建(或分配给项目)新管理器时,范围似乎不会更新,但如果我重新启动服务器,它们会更新。所以代码"工作"本身但显然不是我想要的方式。我是一个ruby / rails noob所以我不确定我是否需要做些什么来刷新"范围在某种程度上。
作为一个FYI,我在Heroku Cedar上使用Rails 3.2和ActiveAdmin
这是有问题的代码(有效但只在服务器重启后引入新管理器):
Manager.find_each do |m|
scope m.first_name do |projects|
projects.where(:manager_id => m.id)
end
end
整个Active Admin Project模型:
ActiveAdmin.register Project do
menu :priority => 1
index do
column :name
column :company_name
column :status
column :projection do |project|
number_to_currency project.projection
end
column :updated_at
default_actions
end
scope :all
scope :working, :default => true do |projects|
projects.where(:status => 'working')
end
Manager.find_each do |m|
scope m.first_name do |projects|
projects.where(:manager_id => m.id)
end
end
end
答案 0 :(得分:10)
以下是此问题的实际解决方案......使用过滤器代替更理想的稳定性和维护性,这在ActiveAdmin中看起来更好,并且更加用户友好,因为范围变得很好看。
这有点像黑客,但在适当的情况下它是一个可行的解决方案:
诀窍是更新控制器索引操作上的before_filter中的范围。
如果您在资源上创建了许多范围(例如,您可以轻松设置一些限制),这可能会变坏。
ActiveAdmin.register Project do
menu :priority => 1
index do
column :name
column :company_name
column :status
column :projection do |project|
number_to_currency project.projection
end
column :updated_at
default_actions
end
scope :all
scope :working, :default => true do |projects|
projects.where(:status => 'working')
end
controller do
before_filter :update_scopes, :only => :index
def update_scopes
resource = active_admin_config
Manager.all.each do |m|
next if resource.scopes.any? { |scope| scope.name == m.first_name }
resource.scopes << (ActiveAdmin::Scope.new m.first_name do |projects|
projects.where(:manager_id => m.id)
end)
end
# try something like this for deletions (untested)
resource.scopes.delete_if do |scope|
!(Manager.all.any? { |m| scope.name == m.first_name } || ['all', 'working'].include?(scope.name)) # don't delete other scopes you have defined
end
end
end
end
答案 1 :(得分:3)
我发现这对我有用:
ActiveAdmin文件
scope :working, :default => true do |projects|
Project.working
end
模型
scope :working, -> { where(:status => 'working') }
回复有点晚,但希望能帮助别人。
答案 2 :(得分:2)
AA寄存器块内的真实动态范围不起作用。我的意思是Manager表中的更改不会反映在'初始化'时创建的动态范围中。另见:https://github.com/gregbell/active_admin/wiki/Creating-dynamic-scopes。您可以尝试使用过滤器而不是范围。然后你可以写下这样的东西:
filter :managers, :as => :select, :collection => proc { Manager.order('name ASC').map(&:first_name) }
并且管理器属性中的更改将显示(页面刷新后)而不重新启动服务器。还检查一下 https://github.com/gregbell/active_admin/issues/1261#issuecomment-5296549
另请注意,活动记录范围是不同的!来自活动管理员范围。你可能想检查
http://apidock.com/rails/ActiveRecord/NamedScope/ClassMethods/scope
答案 3 :(得分:1)
Rails仅在生产模式下加载一次类。这意味着您的范围只被调用一次然后被缓存。这就是为什么新的作用域在重新启动之后才会显示的原因。如果您在案例中编辑了经理的名字,情况也是如此。
我认为解决方案可能是使用lambda或Proc,但是在我用它玩的几分钟内,我没有成功。也可能无法以activeadmin的方式编写。
答案 4 :(得分:0)
这是我根据布兰特·斯特林·韦德尔的回答而优化的解决方案。
此解决方案包含以下附加增强功能:
### Default scope must be set in advance
scope "Jeff", default: true do |x|
x.joins(:manager).where(manager: {name: "Jeff"})
end
controller do
before_action :reload_scopes, only: :index
def reload_scopes
resource_config = active_admin_config
resource_config.instance_variable_set(:@scopes, [
resource_config.scopes.first ### Default scope
])
Manager.all.each do |m|
next if resource_config.scopes.first.name == m.name
resource_config.scopes << ActiveAdmin::Scope.new(m.name){|scope| scope.where(manager_id: m.id) }
end
end
end
答案 5 :(得分:0)
韦斯顿·冈格(Weston Ganger)提到的解决方案就像一个魅力。 如果没有默认范围,则可以将所有范围用作默认范围。
scope :all, default: true