2013-10-29 37 views
0

好的,这是一个非常奇怪的问题。我试着写,将延长的ActiveRecord ::迁移库,这样我可以在我的Rails迁移写这样的代码: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

由于您修改过的'enterprise_mti_down'版本因为它调用'extract_options!'两次而被破坏,'extract_options!'是'Array#pop'周围非常薄的包装。这就是说,我没有看到和你一样的行为。 –

+0

尝试替换args.extract_options!通过args.first – carlosavoy

+0

良好的捕获,@ muistooshort。 – earksiinni

回答

1

解决了我的问题,但我仍然不完全知道它为什么发生。我用的是以下行,包括我的ActiveRecord的代码模块(ActiveRecord的:: EnterpriseMtiMigrations):

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

我从那儿剽窃其他宝石,acts_as_relation这条线,,增加了MTI功能轨。但是,acts_as_relation定义的迁移方法需要一个字符串参数和一个选项散列。该模式与定义几乎所有ActiveRecord :: ConnectionAdapters :: SchemaStatements中的方法的方式相匹配(例如,“create_table table_name,opts_hash”)。

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

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

而现在一切正常(除去@muistooshort建议第二extract_options!为后)。去搞清楚。

+0

我不确定这个具体情况,但很多东西都会在它们的参数上调用'to_s'来规范化字符串和符号(即使m('s')'和'm(:s)'的行为方式相同)。我猜想在ActiveRecord的扭曲的肠子里深处的东西是这样做到你的SchemaStatements补丁。直接修补“ActiveRecord :: Migration”(或者根据需要手动添加您的模块),这对我来说更有意义。不要忘记,你可以在一天内接受你自己的答案。 –