2010-10-25 100 views
50

在我的數據庫中有列名,例如'delete'或'listen-control'等等。這些都不能改變,所以我想用別名來避免我的應用程序出現問題。Rails中列名的別名

我發現the following code但它是過時的(2005年8月5日)並沒有了Rails 3:

module Legacy 
    def self.append_features(base) 
    super 
    base.extend(ClassMethods) 
    end 
    module ClassMethods 
    def alias_column(options) 
     options.each do |new_name, old_name| 
     self.send(:define_method, new_name) { self.send(old_name) } 
     self.send(:define_method, "#{new_name}=") { |value| self.send("#{old_name}=", value) } 
     end 
    end 
    end 
end 

ActiveRecord::Base.class_eval do 
    include Legacy 
end 

如何可以別名的列名?可能嗎?

+0

我不明白使用'delete'和'listen-control'作爲列名會出現什麼問題?你遇到錯誤還是別的什麼? – Ariejan 2010-10-25 13:13:21

+3

監聽控制會導致問題,因爲它的名稱中有一個破折號,這使其成爲無效的ruby對象屬性。 Ruby會將「object.listen-control」解釋爲「object.listen,minus control」。並且刪除可能是保留關鍵字。我不知道你爲什麼想這樣做。有時候正確的答案是停止嘗試與紅寶石或鐵軌對抗。 – 2010-10-25 13:25:24

+0

'define_method(「listen-control」,Proc.new {puts「bingo」})'然後'發送(「監聽控制」)'。問題在哪裏? – rthbound 2017-01-06 15:40:26

回答

0

正如Jaime所說,這些名字可能會導致問題。

在這種情況下,請使用一些合理的名稱。你的圖形用戶界面不應該指定你的列的命名方式。

建議:is_deleteddeleted_atlisten_control

然後,相應地改變你的看法,這是比斗的ActiveRecord和數據庫的方式更容易。

+3

...用這個名稱改變從數據庫讀寫的主應用程序? – user486421 2010-10-25 15:02:30

6

別名方法名稱不會解決您的問題。正如我在上面的評論中提到的那樣,ruby方法或變量名稱中不能有破折號,因爲ruby會將它們解釋爲「減號」。所以:

object.listen-control 

將紅寶石被解釋爲:

object.listen - control 

,並會失敗。您發現的代碼片段可能因爲ruby 1.9而失敗,而不是rails 3. Ruby 1.9不允許您在受保護或私有方法上調用.send,就像1.8以前一樣。

這就是說,我明白有些時候,舊的數據庫列名看起來不太好,你想清理它們。在名爲「bellmyer」的lib文件夾中創建一個文件夾。然後創建一個名爲「create_alias.rb」文件,並添加這樣的:

module Bellmyer 
    module CreateAlias 
    def self.included(base) 
     base.extend CreateAliasMethods 
    end 

    module CreateAliasMethods 
     def create_alias old_name, new_name 
     define_method new_name.to_s do 
      self.read_attribute old_name.to_s 
     end 

     define_method new_name.to_s + "=" do |value| 
      self.write_attribute old_name.to_s, value 
     end 
     end 
    end 
    end 
end 

現在,在你的模型,需要走樣,你可以這樣做:

class User < ActiveRecord::Base 
    include Bellmyer::CreateAlias 
    create_alias 'name-this', 'name_this' 
end 

它將正確的別名。它使用ActiveRecord的read_attributewrite_attribute方法訪問這些表列而不將它們作爲ruby方法調用。

+0

感謝您的回答,但是我測試了您的解決方案並獲得錯誤: SyntaxError(/usr/lib/ruby/gems/1.9.1/gems/activemodel-3.0.0/lib/active_model/attribute_methods。RB:229:語法錯誤,意外 '' 發送(:VM-密碼= *參數) ^): 時定義:alias_attribute 「vm_password」, 「VM-密碼」 並嘗試獲取「vm_password 」。 – user486421 2010-10-25 15:00:37

+0

我找到了解決方案!請參閱我上面的答案編輯。 – 2010-10-25 15:28:17

+0

非常感謝! 我測試了它,發現: 1.在user.rb需要添加第一行:require'bellmyer/create_alias.rb' 2.當沒有人在表中記錄時,您的方法正常工作。有一個或多個記錄導致錯誤:ActionView :: Template :: Error(/usr/lib64/ruby/gems/1.9.1/gems/activemodel-3.0.0/lib/active_model/attribute_methods.rb:273:syntax error ,意外的' - ',期待keyword_end undef:vm-password?... 3.使用字段名稱,如'delete',此方法不起作用,因爲'delete'是方法名稱 – user486421 2010-10-25 17:09:58

123

在你的模型中聲明這個。

alias_attribute :new_column_name, :column_name_in_db 
+0

當表列中有一個帶有破折號的名稱時,此方法不起作用。表格列必須按照原樣映射到有效的ruby方法名稱,以便能夠使用它。 – 2010-10-25 20:02:11

+1

會這樣嗎? 'alias_attribute:'new-column-name',:'column-name-in-db'' – 2011-02-07 03:53:11

+0

:'foo'與foo相同。 :'新列名'是一個符號。我想你沒有嘗試過。 ;) – 2011-06-06 18:21:12