Reputation: 5950
We are beginning a Rails 3 front end to a newly developed application written in Java w/ SQL Server data layer.
Due to the team's previous experience, all column names are in Pascal Case (Id, Name, MyTableId) and table names are in singular form (not pluralized). Is there a way to easily globally overwrite the default rails conventions to work with this data model?
I realize this can be done by using set_table_name and column aliasing, but that kind of defeats the purpose of using Rails to quickly develop the application as we would have to duplicate our existing domain layer codebase.
I've found the code snippet below that will somewhat satisfy my needs, is this the best way / is this still valid?
http://snippets.dzone.com/posts/show/2034
Upvotes: 1
Views: 713
Reputation: 5950
I here is what I came up with help from wilsona. Per answer, added
ActiveRecord::Base.pluralize_table_names = false
to environment.rb.
I added this class in my models directory, and have all my models inherit from it.
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
Upvotes: 0
Reputation: 8840
One part of your problem is solved by an option on ActiveRecord::Base. In your environments.rb, put
ActiveRecord::Base.pluralize_table_names = false
Your other problems, as far as I can tell, will have to be solved by diving into the model generator code and finding where it massages your attributes into its column names. Once the database and its schema follow your convention, ActiveRecord should (from my understanding) automatically generate its attributes with that convention. The easy way to test this is to create a quick record with your conventions, create a model on that record, and then use rails/console to print the result of column_names on an instance of that model.
EDIT: From your edit above, I can see that ActiveRecord's method_missing probably enforces case. Using that link should solve that issue, though.
Do beware, of course, that using Pascal case may cause some headaches with Ruby, since capitalized items without a scope resolution operator are taken to be Constants, not Objects. For example:
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
This will just mean your model code will need to properly use self
, which you should be doing anyway.
Upvotes: 2