Rails将选项哈希转换为字符串

时间:2013-10-29 04:45:47

标签: ruby-on-rails ruby activerecord hash rails-migrations

好吧,这是一个非常奇怪的问题。我正在尝试编写一个扩展ActiveRecord :: Migrations的库,以便我可以在我的Rails迁移中编写这样的代码:

class TestEnterprise < ActiveRecord::Migration
  def up
    enterprise_mti_up superclass_table: 'test_superclasses', subclass_tables: ['test_subclass_ones', 'test_subclass_twos']
  end
  def down
    enterprise_mti_down superclass_table: 'test_superclasses', subclass_tables: ['test_subclass_ones', 'test_subclass_twos']
  end
end

以下是库代码示例:

def enterprise_mti_up(*args)
  enterprise_mti args.extract_options!, direction: :up
end

def enterprise_mti_down(*args)
  enterprise_mti args.extract_options!, direction: :down
end

当我向任何一个方向运行迁移时,的所有内容都可以正常工作:

==  TestEnterprise: migrating =================================================
-- enterprise_mti_up({:superclass_table=>"test_superclasses", :subclass_tables=>["test_subclass_ones", "test_subclass_twos"]})
   -> 0.0005s
==  TestEnterprise: migrated (0.0007s) ========================================

但数据库保持不变,因为实际上Rails以某种方式将选项哈希从enterprise_mti_up和enterprise_mti_down转换为字符串!当我更改其中一个函数来操作哈希时,我得到以下结果:

def enterprise_mti_down(*args)
  opts = args.extract_options!
  puts "opts: #{opts}"
  puts "opts[:superclass_table]: #{opts[:superclass_table]}"
  puts "args: #{args}"
  puts "args.last.class: #{args.last.class}"
  enterprise_mti args.extract_options!, direction: :down
end

...

==  TestEnterprise: reverting =================================================
-- enterprise_mti_down({:superclass_table=>"test_superclasses", :subclass_tables=>["test_subclass_ones", "test_subclass_twos"]})
opts: {}
opts[:superclass_table]:
args: ["{:superclass_table=>\"test_superclasses\", :subclass_tables=>[\"test_subclass_ones\", \"test_subclass_twos\"]}"]
args.last.class: String
   -> 0.0002s
==  TestEnterprise: reverted (0.0005s) ========================================

有没有人知道为什么将哈希转换为字符串以及如何将哈希传递给我的方法?谢谢!

注意:在我的测试中,我发现如果我在选项哈希之前传递一个字符串作为第一个参数,那么一切都按照它应该的方式工作。但我不应该在哈希之前有任何参数。这让我认为Rails可能很难将字符串/符号作为迁移方法中的第一个参数。

1 个答案:

答案 0 :(得分:1)

解决了我的问题,但我仍然不知道它为什么会发生。我使用以下行在ActiveRecord代码中包含我的模块(ActiveRecord :: EnterpriseMtiMigrations):

ActiveRecord::ConnectionAdapters::SchemaStatements.send :include, ActiveRecord::EnterpriseMtiMigrations

我从另一个gem,acts_as_relation中删除了这一行,它为Rails添加了MTI功能。但是,acts_as_relation定义的迁移方法会使用字符串参数和后续的选项哈希。该模式与ActiveRecord :: ConnectionAdapters :: SchemaStatements中几乎所有方法的定义方式相匹配(例如,“create_table table_name,opts_hash”)。

鉴于这一事实,我有一种预感,通过将我的方法包含在SchemaStatements模块中,我以某种方式强迫我的第一个参数成为一个字符串,以匹配上述模式。我用以下内容替换了上面的代码行:

ActiveRecord::Migration.send :include, ActiveRecord::EnterpriseMtiMigrations

现在一切正常(按照@muistooshort的建议删除第二个extract_options!后)。去图。