`
fyol
  • 浏览: 31773 次
  • 性别: Icon_minigender_1
社区版块
存档分类
最新评论

如何解决acts_as_list 多字段限定的问题?

    博客分类:
  • ROR
阅读更多
现在有一个model:(任务)
class Tasklist < ActiveRecord::Base
end


要实现act_as_list,如果不限定排序范围,最简单
class Tasklist < ActiveRecord::Base
acts_as_list
end
这样,所有记录的position根据记录数自己累加

如果要限定:position仅对同一个父节点(对任务分解后,父节点下有多个任务)下的tasklist进行排序,也非常简单
class Tasklist < ActiveRecord::Base
acts_as_list :scope => :parent_id
end


现在问题来了,如果任务属于多个project,在上面的基础上要再限定project_id
class Tasklist < ActiveRecord::Base
acts_as_list :scope => "project_id = #{project_id} AND parent_id = #{parent_id}"
end
这样,当parent_id为空时,生成的SQL语句会出错:
因为: "parent_id = AND"

为了处理 "parent_id IS NULL"的情况:

class Tasklist < ActiveRecord::Base
acts_as_list :scope => "project_id = #{project_id} AND parent_id #{parent_id ? '=' + parent_id.to_s : 'IS NULL'}"
end


这个里面应该没有问题了,但Tasklist.new时会提示project_id与parent_id都不存在,请

我参考了一面的一个链接,发现根据里面贴出来的代码并不能解决这个问题
http://dev.rubyonrails.org/ticket/3018
分享到:
评论
10 楼 blackanger 2007-07-05  
ruby for rails里有讲
9 楼 fyol 2006-10-27  
多谢!基本明白了,再多查些资料好好看看。
8 楼 qiezi 2006-10-27  
是这样的,后面有个部分会把scope_condition_method扩展开来并执行class_eval。

可以写一个简单的模拟:
class Foo
  attr_accessor :first_name
  attr_accessor :last_name

  def self.set_full_name(full_name)
    eval <<-EOS
    def full_name
      "#{full_name}"
    end
    EOS
  end

  set_full_name '#{first_name} #{last_name}'
end

foo = Foo.new
foo.first_name = "A"
foo.last_name = "B"
puts foo.full_name
7 楼 fyol 2006-10-27  
我想弄明白这句SQL被调用的先后顺序:
这段代码执行时,会调用两次MODEL

@tasklist = Tasklist.new #第一次
      @tasklist.task_name = @project.proj_name
      @tasklist.project_id = @project.id  
      @tasklist.task_start_date = Time.now
      @tasklist.task_finish_date = Time.now   
      @tasklist.save  #第二次


对不对?
先看第一次:

单引号里的内容先被acts_as_list(options = {})调用一下:
acts_as_list的源代码如下:

34:         def acts_as_list(options = {})
35:           configuration = { :column => "position", :scope => "1 = 1" }
36:           configuration.update(options) if options.is_a?(Hash)
37: 
38:           configuration[:scope] = "#{configuration[:scope]}_id".intern if configuration[:scope].is_a?(Symbol) && configuration[:scope].to_s !~ /_id$/
39:           
40:           if configuration[:scope].is_a?(Symbol)
41:             scope_condition_method = %(
42:               def scope_condition
43:                 if #{configuration[:scope].to_s}.nil?
44:                   "#{configuration[:scope].to_s} IS NULL"
45:                 else
46:                   "#{configuration[:scope].to_s} = \#{#{configuration[:scope].to_s}}"
47:                 end
48:               end
49:             )
50:           else
51:             scope_condition_method = "def scope_condition() \"#{configuration[:scope]}\" end"
52:           end
53:           
54:           class_eval "include ActiveRecord::Acts::List::InstanceMethods\n\ndef acts_as_list_class\n::\#{self.name}\nend\n\ndef position_column\n'\#{configuration[:column]}'\nend\n\n\#{scope_condition_method}\n\nafter_destroy  :remove_from_list\nbefore_create  :add_to_list_bottom\n"  #你说的eval在这儿了是不是?用@tasklist里的属性来替换#{}里的东西?重新生成SQL,发送到数据库?我还没到能看懂这段的程度,后面好好学习一下
55:         end


就是说,单引号里的字符串不是直接给数据库的,而是作为字符串参数传给acts_as_list的



6 楼 qiezi 2006-10-27  
这个是ruby知识。双引号里面的#{}里的内容在字符串取值时就要求值,单引号不处理里面的转义和求值部分,所以可以直接传递过去。

也不是非得单引号,你把双绰号里面的#{改成\#{效果也一样,就是多加了些转义字符,不好看。
5 楼 fyol 2006-10-27  
看来自己学习的深度还差的远,多谢
BTW,你说的这个在哪儿可以详细的看一下?
4 楼 qiezi 2006-10-27  
这实际上是个延缓求值,acts_as_list执行时这些属性都不存在,双引号自然是要失败。用单引号传递计算式过去,在查询时用eval把它求值出来。
3 楼 fyol 2006-10-27  
明明是这样的:
Ruby 不处理任何用单引号括起来的字符串信息。如果用双引号括起来,Ruby 会在运行代码的时候进行替换。

但为什么上面的代码里要用单引号呢?

'project_id = #{project_id} AND parent_id #{parent_id ? "=" + parent_id.to_s : "IS NULL"}'


岂不是直接把这句作为SQL传给数据库了?
2 楼 fyol 2006-10-27  
但还是很奇怪,我有点糊涂了,单双引号的用法再查一下
1 楼 fyol 2006-10-27  
嘿嘿,贴上来后,问题就解决了,是原文里单引号与双引号反了,正确代码如下:


 class Tasklist < ActiveRecord::Base
acts_as_list :scope => 'project_id = #{project_id} AND parent_id = #{parent_id}'
end
这样,当parent_id为空时,生成的SQL语句会出错:
因为: "parent_id = AND"

为了处理 "parent_id IS NULL"的情况:


 class Tasklist < ActiveRecord::Base
acts_as_list :scope => 'project_id = #{project_id} AND parent_id #{parent_id ? "=" + parent_id.to_s : "IS NULL"}'
end


这样问题应该算是解决了
只是这个scope写的复杂了点,有其他什么办法吗?如果act_as_list能简化一下就好了,像这样
 class Tasklist < ActiveRecord::Base
acts_as_list :scope => :project_id, :parent_id
end


相关推荐

    acts_as_list.rar

    acts_as_list.raracts_as_list.raracts_as_list.raracts_as_list.raracts_as_list.raracts_as_list.raracts_as_list.raracts_as_list.raracts_as_list.raracts_as_list.raracts_as_list.raracts_as_list.raracts_as_...

    acts_as_authenticated

    最后,虽然acts_as_authenticated在当时是一个流行的解决方案,但随着Rails的发展,现在有更多的现代认证解决方案出现,如devise和warden。这些现代库提供了更多功能,如邮件验证、密码重置、多因素认证等,并且社区...

    acts_as_list, 用于管理列表的ActiveRecord插件.zip

    acts_as_list, 用于管理列表的ActiveRecord插件 ActsAsList描述这个 acts_as 扩展提供了对列表中的多个对象进行排序和重新排序的功能。 具有指定的类的类需要在映射的数据库表上定义为整数的position 列。 0.8.0升级...

    acts_as_paranoid

    通过学习和使用"acts_as_paranoid",开发者能够提升数据安全性,同时保持数据库的整洁,避免了因错误操作导致的数据不可恢复问题。在实际项目中,尤其在需要严格管理数据的场景下,它是一个非常实用的工具。

    acts_as_nested_set的增强版BetterNestedSet

    - **兼容性提升**:支持Rails的更新版本,解决了旧版acts_as_nested_set在新环境下可能出现的问题。 - **灵活的配置**:允许自定义左值和右值字段名,以及额外的辅助字段,以适应不同的需求。 4. 使用示例 - ...

    rails_admin_acts_as_list:rails_admin插件以对记录进行排序

    介绍插件,用于对记录进行排序(使用 gem)安装要启用rails_admin_acts_as_list,请将以下内容添加到您的Gemfile : gem 'rails_admin_acts_as_list'gem 'rails_admin' 重要提示: rails_admin_acts_as_list之前必须...

    用acts_as_rateable实现简单的打分功能

    在安装和配置插件后,你可以在需要评分功能的模型上添加`acts_as_rateable`方法,这将自动为该模型添加必要的字段和关联。 安装`acts_as_rateable`插件通常通过以下步骤完成: 1. 在Gemfile中添加插件依赖: ```...

    acts_as_category:想想acts_as_tree +权限

    #ActsAsCategory acts_as_category (Version 2.0 beta)acts_as_category,是acts_as插件在acts_as_tree风格的Ruby on Rails的ActiveRecord的模式,但有一些额外的功能,以及多种便捷视图助手。例子(有关实例方法和...

    acts_as_restful_list:就像acts_as_list一样,但很安静

    就像acts_as_list 一样,但不必使用非标准方法调用(如insert_at)来弄乱您的代码,acts_as_restful_list 使管理列表变得简单。 您可以像更新其他任何内容一样更新 position 属性,其余的都由您来处理。 特点 通过...

    active_record-acts_as, 模拟activerecord模型的多表继承.zip

    active_record-acts_as, 模拟activerecord模型的多表继承 插件开发已经移动这个项目的积极发展已经转移到了的krautcomputing fork 。 请在那里报告问题并打开 PRs ! ActiveRecord::ActsAs这是对 acts_as_relation的...

    Api-acts_as_api.zip

    Api-acts_as_api.zip,使在rails中创建api响应变得简单和有趣,一个api可以被认为是多个软件设备之间通信的指导手册。例如,api可用于web应用程序之间的数据库通信。通过提取实现并将数据放弃到对象中,api简化了编程...

    acts_as_paranoid:ActiveRecord插件可让您隐藏和还原记录,而无需实际删除它们

    已知的问题在同一模型上使用acts_as_paranoid和ActiveStorage 。 您不能直接以已删除状态创建模型,也不能在删除后更新模型。用法安装gem: gem 'acts_as_paranoid' , '~&gt; 0.7.0' bundle install创建迁移bin/rails ...

    acts_as_liked:向任何 Active Record 模型添加类似功能

    gem 'acts_as_liked' 然后执行: $ bundle 运行生成器: $ rails generate acts_as_liked 并且不要忘记迁移您的数据库 $ rake db:migrate 用法 可爱的模特 将acts_as_likeable添加到任何模型,它的实例可以被...

    acts_as_commentable_with_threading:类似于acts_as_commentable; 然而,利用 awesome_nested_set 提供线程评论

    与acts_as_commentable 兼容(但需要更改数据库架构) 要求 此 gem 的 2.x 版本仅适用于 Rails 4 及更高版本。 对于此 gem 的 Rails 3.x 兼容版本,请使用版本 1.2.0。 这个宝石取决于 CollectiveIdea 的 Awesome ...

    acts_as_xapian:Xapian全文搜索插件,适用于Ruby on Rails

    其中,“acts_as_xapian”是一款专门为Rails设计的全文搜索插件,它利用Xapian搜索引擎库,为开发者提供了高效且灵活的全文搜索解决方案。 Xapian是一款开源的、高性能的全文搜索引擎库,被广泛应用于各种项目,其...

    actions_as_commentable:ActiveRecord acts_as_commentable插件

    gem 'acts_as_commentable' Rails gem 'acts_as_commentable' , '3.0.1' Rails gem 'acts_as_commentable' , git: 'git@github.com:jackdempsey/acts_as_commentable.git' , branch: '2.x' 生成器 Rails 3+ ...

    acts_as_aliased:扩展 ActiveRecord

    gem 'acts_as_aliased' 更新包后,运行 rails generate acts_as_aliased:install rake db:migrate 这将创建一个新表aliases 。 用法 假设您有一个需要别名的模型Company ,因为公司名称有不同的版本。 使用acts_as...

    acts_as_shopping_cart:简单的购物车实施

    acts_as_shopping_cart 一个简单的购物车实现。 您可以找到示例应用程序。 安装 滑轨3 从0.2.0版开始,不再支持Rails 3。 如果您仍需要在Rails 3应用程序中实现此gem,请使用0-1-x分支 将其包含在您的Gemfile中 ...

    acts_as_reference_data

    文档基本用法例如, SubscriptionType是一个 ActiveRecord: require 'acts_as_reference_data'class SubscriptionType &lt; ActiveRecord::Base acts_as_reference_dataend假设已创建迁移以使用各种类型填充此表,...

    acts_as_snapchat:使您的 Active Record 模型表现得像 Snapchat 上的内容

    为了使任何模型充当snapchat,只包括acts_as_snapchat在类定义: class User &lt; ActiveRecord xss=removed&gt; 1 sleep 10 User . count # =&gt; 0 如果您是 Node.js 开发人员,您可能更喜欢使用别名acts_as_mongodb 。 ...

Global site tag (gtag.js) - Google Analytics