使用 Ruby closure_tree gem 而不使用 rails

Use Ruby closure_tree gem without rails

我想尝试 gem closure_tree 为我的家谱数据库构建树。 我在 windows 7 盒子上安装了 Ruby MRI 2.3.0 下的 gem。 依赖项的版本在下面的错误日志中。

$ gem install closure_tree
Fetching: with_advisory_lock-3.0.0.gem (100%)
Successfully installed with_advisory_lock-3.0.0
Fetching: closure_tree-6.2.0.gem (100%)
Successfully installed closure_tree-6.2.0
2 gems installed

当我尝试最简约的代码时它失败了,我想是因为我没有使用 Rails 并且没有进行迁移,我认为这再次创建了 table tag_hierachies

我的问题是:我可以在没有 Rails 的情况下使用这个 gem 吗?如果可以的话怎么办?

require 'active_record'
require 'closure_tree'

ActiveRecord::Base.establish_connection(
    :adapter => "sqlite3",
    :database  => "sample.db"
)

if !ActiveRecord::Base.connection.table_exists?('tags')
  ActiveRecord::Schema.define do
    create_table :tags do |table|
      table.column :name, :string
      table.column :parent_id, :integer
    end
  end
end

class Tag < ActiveRecord::Base
  has_closure_tree
end

grandparent = Tag.create(name: 'Grandparent')

给予

d:/Ruby/lib/ruby/gems/2.3.0/gems/activerecord-4.2.6/lib/active_record/connection_adapters/sqlite3_adapter.rb:513:in `table_structure': Could not find table 'tag_hierarchies' (ActiveRecord::StatementInvalid)
    from d:/Ruby/lib/ruby/gems/2.3.0/gems/activerecord-4.2.6/lib/active_record/connection_adapters/sqlite3_adapter.rb:387:in `columns'
    from d:/Ruby/lib/ruby/gems/2.3.0/gems/activerecord-4.2.6/lib/active_record/connection_adapters/schema_cache.rb:43:in `columns'
    from d:/Ruby/lib/ruby/gems/2.3.0/gems/activerecord-4.2.6/lib/active_record/attributes.rb:93:in `columns'
    from d:/Ruby/lib/ruby/gems/2.3.0/gems/activerecord-4.2.6/lib/active_record/attributes.rb:98:in `columns_hash'
    from d:/Ruby/lib/ruby/gems/2.3.0/gems/activerecord-4.2.6/lib/active_record/inheritance.rb:205:in `subclass_from_attributes?'
    from d:/Ruby/lib/ruby/gems/2.3.0/gems/activerecord-4.2.6/lib/active_record/inheritance.rb:54:in `new'
    from d:/Ruby/lib/ruby/gems/2.3.0/gems/activerecord-4.2.6/lib/active_record/persistence.rb:50:in `create!'
    from d:/Ruby/lib/ruby/gems/2.3.0/gems/closure_tree-6.2.0/lib/closure_tree/hierarchy_maintenance.rb:65:in `block in rebuild!'
    from d:/Ruby/lib/ruby/gems/2.3.0/gems/closure_tree-6.2.0/lib/closure_tree/support.rb:108:in `block (2 levels) in with_advisory_lock'
    from d:/Ruby/lib/ruby/gems/2.3.0/gems/activerecord-4.2.6/lib/active_record/connection_adapters/abstract/database_statements.rb:211:in `transaction'
    from d:/Ruby/lib/ruby/gems/2.3.0/gems/activerecord-4.2.6/lib/active_record/transactions.rb:220:in `transaction'
    from d:/Ruby/lib/ruby/gems/2.3.0/gems/closure_tree-6.2.0/lib/closure_tree/support.rb:108:in `block in with_advisory_lock'
    from d:/Ruby/lib/ruby/gems/2.3.0/gems/with_advisory_lock-3.0.0/lib/with_advisory_lock/base.rb:77:in `yield_with_lock'
    from d:/Ruby/lib/ruby/gems/2.3.0/gems/with_advisory_lock-3.0.0/lib/with_advisory_lock/base.rb:65:in `yield_with_lock_and_timeout'
    from d:/Ruby/lib/ruby/gems/2.3.0/gems/with_advisory_lock-3.0.0/lib/with_advisory_lock/base.rb:48:in `with_advisory_lock_if_needed'
    from d:/Ruby/lib/ruby/gems/2.3.0/gems/with_advisory_lock-3.0.0/lib/with_advisory_lock/concern.rb:16:in `with_advisory_lock_result'
    from d:/Ruby/lib/ruby/gems/2.3.0/gems/with_advisory_lock-3.0.0/lib/with_advisory_lock/concern.rb:10:in `with_advisory_lock'
    from d:/Ruby/lib/ruby/gems/2.3.0/gems/closure_tree-6.2.0/lib/closure_tree/support.rb:107:in `with_advisory_lock'
    from d:/Ruby/lib/ruby/gems/2.3.0/gems/closure_tree-6.2.0/lib/closure_tree/hierarchy_maintenance.rb:63:in `rebuild!'
    from d:/Ruby/lib/ruby/gems/2.3.0/gems/closure_tree-6.2.0/lib/closure_tree/hierarchy_maintenance.rb:39:in `_ct_after_save'
    from d:/Ruby/lib/ruby/gems/2.3.0/gems/activesupport-4.2.6/lib/active_support/callbacks.rb:432:in `block in make_lambda'
    from d:/Ruby/lib/ruby/gems/2.3.0/gems/activesupport-4.2.6/lib/active_support/callbacks.rb:228:in `block in halting_and_conditional'
    from d:/Ruby/lib/ruby/gems/2.3.0/gems/activesupport-4.2.6/lib/active_support/callbacks.rb:506:in `block in call'
    from d:/Ruby/lib/ruby/gems/2.3.0/gems/activesupport-4.2.6/lib/active_support/callbacks.rb:506:in `each'
    from d:/Ruby/lib/ruby/gems/2.3.0/gems/activesupport-4.2.6/lib/active_support/callbacks.rb:506:in `call'
    from d:/Ruby/lib/ruby/gems/2.3.0/gems/activesupport-4.2.6/lib/active_support/callbacks.rb:92:in `__run_callbacks__'
    from d:/Ruby/lib/ruby/gems/2.3.0/gems/activesupport-4.2.6/lib/active_support/callbacks.rb:778:in `_run_save_callbacks'
    from d:/Ruby/lib/ruby/gems/2.3.0/gems/activerecord-4.2.6/lib/active_record/callbacks.rb:302:in `create_or_update'
    from d:/Ruby/lib/ruby/gems/2.3.0/gems/activerecord-4.2.6/lib/active_record/persistence.rb:120:in `save'
    from d:/Ruby/lib/ruby/gems/2.3.0/gems/activerecord-4.2.6/lib/active_record/validations.rb:37:in `save'
    from d:/Ruby/lib/ruby/gems/2.3.0/gems/activerecord-4.2.6/lib/active_record/attribute_methods/dirty.rb:21:in `save'
    from d:/Ruby/lib/ruby/gems/2.3.0/gems/activerecord-4.2.6/lib/active_record/transactions.rb:286:in `block (2 levels) in save'
    from d:/Ruby/lib/ruby/gems/2.3.0/gems/activerecord-4.2.6/lib/active_record/transactions.rb:351:in `block in with_transaction_returning_status'
    from d:/Ruby/lib/ruby/gems/2.3.0/gems/activerecord-4.2.6/lib/active_record/connection_adapters/abstract/database_statements.rb:213:in `block in transaction'
    from d:/Ruby/lib/ruby/gems/2.3.0/gems/activerecord-4.2.6/lib/active_record/connection_adapters/abstract/transaction.rb:184:in `within_new_transaction'
    from d:/Ruby/lib/ruby/gems/2.3.0/gems/activerecord-4.2.6/lib/active_record/connection_adapters/abstract/database_statements.rb:213:in `transaction'
    from d:/Ruby/lib/ruby/gems/2.3.0/gems/activerecord-4.2.6/lib/active_record/transactions.rb:220:in `transaction'
    from d:/Ruby/lib/ruby/gems/2.3.0/gems/activerecord-4.2.6/lib/active_record/transactions.rb:348:in `with_transaction_returning_status'
    from d:/Ruby/lib/ruby/gems/2.3.0/gems/activerecord-4.2.6/lib/active_record/transactions.rb:286:in `block in save'
    from d:/Ruby/lib/ruby/gems/2.3.0/gems/activerecord-4.2.6/lib/active_record/transactions.rb:301:in `rollback_active_record_state!'
    from d:/Ruby/lib/ruby/gems/2.3.0/gems/activerecord-4.2.6/lib/active_record/transactions.rb:285:in `save'
    from d:/Ruby/lib/ruby/gems/2.3.0/gems/activerecord-4.2.6/lib/active_record/persistence.rb:34:in `create'
    from C:/Users/Gebruiker/BoxSync/ruby_werk/acts_as_tree/closure_tree.rb:22:in `<main>'

README 中的安装说明似乎只针对 Rails。然而,它确实告诉您您需要另一个 table(除了您当前的 tags table),名称为 tag_hierarchies

在 Rails 中,这个 table 的生成似乎是安装步骤的一部分;链接文档中的第 5 步。

因此,您应该使用以下内容创建 tag_hierarchies table,就 table 结构而言,这是 rails g closure_tree:migration tag 生成的内容。请参阅 create_hierarchies_table.rb.erb,因为您可能还想添加索引,如此链接文件中所示。

因此,将您的脚本更新为以下对我来说工作正常:

require 'active_record'                                                                                                
require 'closure_tree'                                                                                                 

ActiveRecord::Base.establish_connection(                                                                               
    :adapter => "sqlite3",                                                                                             
    :database  => "sample.db"                                                                                          
)                                                                                                                      

if !ActiveRecord::Base.connection.data_source_exists?('tags')                                                          
  ActiveRecord::Schema.define do                                                                                       
    create_table :tags do |table|                                                                                      
      table.column :name, :string                                                                                      
      table.column :parent_id, :integer                                                                                
    end                                                                                                                
  end                                                                                                                  
end                                                                                                                    

# You also need a corresponding model's table name followed by "_hierarchies" table.                                   
#                                                                                                                      
# Migration created based on                                                                                           
# `https://github.com/mceachen/closure_tree/blob/master/lib/generators/closure_tree/templates/create_hierarchies_table.rb.erb`
if !ActiveRecord::Base.connection.data_source_exists?(:tag_hierarchies)                                                
  ActiveRecord::Schema.define do                                                                                       
    create_table :tag_hierarchies do |table|                                                                           
      table.integer :ancestor_id, null: false                                                                          
      table.integer :descendant_id, null: false                                                                        
      table.integer :generations, null: false                                                                          
    end                                                                                                                
  end                                                                                                                  
end                                                                                                                    

class Tag < ActiveRecord::Base                                                                                         
  has_closure_tree                                                                                                     
end                                                                                                                    

grandparent = Tag.create(name: 'Grandparent')                                                                          

grandparent.children.create(name: 'Father')                                                                            
grandparent.children.create(name: 'Uncle')