精华帖 (0) :: 良好帖 (0) :: 新手帖 (0) :: 隐藏帖 (0)
|
|
---|---|
作者 | 正文 |
发表时间:2006-10-27
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 声明:ITeye文章版权属于作者,受法律保护。没有作者书面许可不得转载。
推荐链接
|
|
返回顶楼 | |
发表时间: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 |
|
返回顶楼 | |
发表时间:2006-10-27
但还是很奇怪,我有点糊涂了,单双引号的用法再查一下
|
|
返回顶楼 | |
发表时间:2006-10-27
明明是这样的:
Ruby 不处理任何用单引号括起来的字符串信息。如果用双引号括起来,Ruby 会在运行代码的时候进行替换。 但为什么上面的代码里要用单引号呢? 'project_id = #{project_id} AND parent_id #{parent_id ? "=" + parent_id.to_s : "IS NULL"}' 岂不是直接把这句作为SQL传给数据库了? |
|
返回顶楼 | |
发表时间:2006-10-27
这实际上是个延缓求值,acts_as_list执行时这些属性都不存在,双引号自然是要失败。用单引号传递计算式过去,在查询时用eval把它求值出来。
|
|
返回顶楼 | |
发表时间:2006-10-27
看来自己学习的深度还差的远,多谢
BTW,你说的这个在哪儿可以详细的看一下? |
|
返回顶楼 | |
发表时间:2006-10-27
这个是ruby知识。双引号里面的#{}里的内容在字符串取值时就要求值,单引号不处理里面的转义和求值部分,所以可以直接传递过去。
也不是非得单引号,你把双绰号里面的#{改成\#{效果也一样,就是多加了些转义字符,不好看。 |
|
返回顶楼 | |
发表时间: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的 |
|
返回顶楼 | |
发表时间: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 |
|
返回顶楼 | |
发表时间:2006-10-27
多谢!基本明白了,再多查些资料好好看看。
|
|
返回顶楼 | |