0

我希望能够添加一个类似于符号链接的记录。换句话说,我希望能够存储一个记录/对象,它将大多数属性推迟到另一个记录/对象。

与符号链接指向另一个文件(它拥有数据)的文件系统相同,但将其他所有内容推迟到另一个文件。

class Document < ActiveRecord::Base
end

class Page < Document
end

class Folder < Document
end

class Symlink < ActiveRecord::Base
  set_table_name  :documents

  instance_methods.each { |m| undef_method m if (ActiveRecord::Base.instance_methods(false).include? m) && (!['link', 'link_id', 'link_id='].include? m) }

  def method_missing(sym, *args, &block)
    puts "Sending #{sym}(#{args.join(',')}) to obj"
    link.__send__(sym, *args, &block)
  end

  def save
    raise 'Symlink cant be saved' unless new_record?
    super
  end

  private

  def link
    @link ||= Document.find(self.link_id)
  end  
end

在我尝试创建新记录的那一刻,我的堆栈级别对于“链接”来说太深了。

我认为这将是解决问题的一种巧妙方法,可以提取到 gem ( acts_as_symlink :column => 'parent_id') 中。

另一个想法是保留原始记录的完整副本并使用 after_save 回调来更新任何符号链接,或者如果符号链接发生更改,则更新原始记录。所以不是真正的符号链接更像是同步的副本。

对我的代码或替代方案有什么想法吗?

4

1 回答 1

0

好的,我似乎已经破解了它,关键是用遵循另一个对象的方法替换访问数据库列的方法。通过覆盖 id 方法,我还可以确定是否save将属性保存到符号链接或原始记录。Document在我的情况下是一个acts_as_tree+ acts_as_list,所以我排除parent_idposition列被延迟,所以我可以将符号链接分配给不同的文件夹(否则无用)并将其放置在该文件夹中。

class Symlink < Document
  attr_accessor :save_to  


  self.columns.map { |c| c.name }.reject { |c| %w(position parent_id sync_id).include? c }.each do | col |
    self.send :define_method, col.to_sym do   
      source.send(col)
    end
  end

  def id
    if save_to == :symlink
      return read_attribute(:id)
    else
      return source.send :id
    end
  end

  def copy?
    !sync_id.nil?
  end


  private

  def source
    if sync_id
      @source ||= Document.find(sync_id)
    else
      Document.new
    end
  end
end

到目前为止只在控制台中进行了测试,但是为什么这不应该在整个堆栈上工作。

如果它成功,我会考虑将其抽象为通用的acts_as_symlink gem。

于 2009-10-22T13:52:48.290 回答