Ruby on rails Rails 3-轻松使用Pascal大小写列名

Ruby on rails Rails 3-轻松使用Pascal大小写列名,ruby-on-rails,sql-server,activerecord,Ruby On Rails,Sql Server,Activerecord,我们正在开始一个Rails 3前端到一个用JavaW/SQLServer数据层编写的新开发应用程序 由于团队以前的经验,所有列名都是Pascal大小写(Id、Name、MyTableId),表名是单数形式(不是复数形式)。有没有一种方法可以轻松地全局覆盖默认rails约定以使用此数据模型 我意识到这可以通过使用set_table_name和列别名来实现,但这样做会破坏使用Rails快速开发应用程序的目的,因为我们必须复制现有的域层代码库 我发现下面的代码片段在某种程度上满足了我的需要,这是最好的

我们正在开始一个Rails 3前端到一个用JavaW/SQLServer数据层编写的新开发应用程序

由于团队以前的经验,所有列名都是Pascal大小写(Id、Name、MyTableId),表名是单数形式(不是复数形式)。有没有一种方法可以轻松地全局覆盖默认rails约定以使用此数据模型

我意识到这可以通过使用set_table_name和列别名来实现,但这样做会破坏使用Rails快速开发应用程序的目的,因为我们必须复制现有的域层代码库

我发现下面的代码片段在某种程度上满足了我的需要,这是最好的方法吗


问题的一部分通过ActiveRecord::Base上的选项解决。在您的environments.rb中,放置

ActiveRecord::Base.pluralize_table_names = false
据我所知,您的其他问题将必须通过深入研究模型生成器代码并找到它将属性传递到其列名中的位置来解决。一旦数据库及其模式遵循您的约定,ActiveRecord应该(据我所知)自动生成具有该约定的属性。测试这一点的简单方法是使用约定创建一个快速记录,在该记录上创建一个模型,然后使用rails/console在该模型的实例上打印列名的结果

编辑:从上面的编辑中,我可以看到ActiveRecord的方法_缺失可能会强制执行该案例。不过,使用这个链接应该可以解决这个问题

当然,请注意,使用Pascal case可能会给Ruby带来一些麻烦,因为没有范围解析操作符的大写项被视为常量,而不是对象。例如:

class Foo
  attr_reader :low,:Cap


  def initialize
     @low = "lowtest"
     @Cap = "Captest"
  end

  def bar
     self.low   #<==works
     self.Cap   #<==works
  end

  def baz
     low        #<==works
     Cap        #<==raises NameError
  end
end
class-Foo
属性读取器:低,:上限
def初始化
@low=“lowtest”
@Cap=“Captest”
结束
def棒

self.low我在威尔索纳的帮助下想到了这一点。根据答案,添加

ActiveRecord::Base.pluralize_table_names = false  
到environment.rb

我在models目录中添加了这个类,并使我的所有模型都从中继承

class PascalCaseActiveRecord < ActiveRecord::Base
  self.abstract_class = true

  # all columns are uppercase
  set_primary_key 'Id'

  def self.reloadable?
    false
  end



  # convert to camel case attribute if in existence
  # record.name => record.Name
  # record.id => record.Id
  def method_missing(method_id, *args, &block)
    method_id = method_id.to_s.camelize if @attributes.include? method_id.to_s.camelize.gsub(/=/, '')
    super(method_id, *args, &block)
  end

#  def self.method_missing(method_id, *args)
#    # if its a finder method
#    if method_id.to_s.match(/^find_by_/)
#      puts "Before camelize #{method_id}"
#      s2 = method_id.to_s.sub("find_by_","").split('_and_')
#      s2.collect! {|s| s.camelize}
#      method_id = "find_by_" + s2.join("_and_")
#      puts "After camelize #{method_id}"
#    end
#    
#    super(method_id, *args)
#  end
#  
    # strip leading and trailing spaces from attribute string values
  def read_attribute(attr_name)
    value = super(attr_name)
    value.is_a?(String) ? value.strip : value
  end

  class << self # Class methods

    private
      # allow for find_by and such to work with uppercase attributes
      # find_by_name => find_by_Name
      # find_by_dob_and_height => find_by_Dob_and_Height
      def extract_attribute_names_from_match(match)
        match.captures.last.split('_and_').map { |name| name.camelize }
      end
  end
end
类PascalCaseActiveRecordrecord.name #record.id=>record.id 缺少def方法(方法id、*参数和块) 方法\u id=方法\u id.to\u.camelize if@attributes.include?方法id到camelize.gsub(/=/,'') 超级(方法id、*参数和块) 结束 #def self.method_缺失(method_id,*args) ##如果是查找方法 #如果方法id匹配(/^find\u by./) #放置“在camelize#{method_id}之前” #s2=方法id.to_.sub(“通过查找查找查找”).split(“查找和查找”) #收集!{| s | s.camelize} #方法\u id=“通过查找查找查找”+s2.join(“\u和\u”) #放置“在camelize#{method_id}之后” #结束 # #超级(方法id,*args) #结束 # #从属性字符串值中去掉前导空格和尾随空格 def read_属性(属性名称) 值=超级(属性名称) 值。_是?(字符串)吗?value.strip:value 结束 类按名称查找 #按大小和高度查找=>按大小和高度查找 def从匹配中提取属性名称(匹配) match.captures.last.split(“'u和').map{{| name | name.camelize} 结束 结束 结束
这个代码段链接正是您所需要的,尽管您的生成器仍然坚持Ruby风格的命名约定。