Outdated schema and dynamic find (Ruby on Rails)

I am trying to put rails on an outdated database. This is old Sybase 11. I got an ODBC connection that uses unixODBC and FreeTDS to work. I also use the activerecord-odbc-adapter attribute.

I had to use set_table_name and set_primary_key to make it work that far. However, none of the dynamic find_by methods work. I always get a missing error method. Also, searching through an association does not work well with the same error. Normal finds on models work, but I was hoping I could cut some of this down.

Am I SOL on this because it is an outdated DB or is there something I can do or check to make this work?

If I can, this will save me some work on writing SQL.

Thanks.

Edit:

Console output:

Person.find_by_last_name("Smith")


NoMethodError: undefined method `find_by_last_name' for Person(Table doesn't exist):Class
    from /opt/ruby-enterprise-1.8.6-20090201/lib/ruby/gems/1.8/gems/activerecord-2.2.2/lib/active_record/base.rb:1778:in `method_missing'
    from (irb):1


Person.find(:first, :conditions => { :last_name => "Smith" })

#<Person Person_ID: <redacted>, Title: "Mr.", First_Name: "Aaron", Middle_Name: "Michael", Last_Name: "Smith", Suffix: nil, Preferred_Name: nil

Further editing:

I accepted the wild hunch and the last name Last_Name. This has returned something. Looks like I'll have to do it. I still don’t know how part of the association will work. This is still a problem.

+3
source share
4 answers

Your problem is that crawlers are case sensitive. I have the same problem with my old database.

Try to see how it works:

Person.find_by_Last_Name("Smith")

That should do the trick.

I have some code that I wrote to fix such problems. This is a small monkey palette for ActiveRecord that you can insert into specific models that you want to change.

module ActiveRecord
  class Base
    # Indicates whether field names should be lowercased for legacy databse fields.
    # If true, the field Product_Name will be +product_name+. If false, it will remain +Product_Name+.
    # This is false, by default.
    cattr_accessor :downcase_legacy_field_names, :instance_writer => false
    @@downcase_legacy_field_names = false
  end
end

ActiveRecord, downcase_legacy_field_names. false. true , .

# set all accessor methods to lowercase (underscore)
# add set_columns_to_lower to each model that needs it 
class << ActiveRecord::Base

    # Returns a hash of all the methods added to query each of the columns in the table with the name of the method as the key
    # and true as the value. This makes it possible to do O(1) lookups in respond_to? to check if a given method for attribute
    # is available.
    def column_methods_hash #:nodoc:
      @dynamic_methods_hash ||= column_names.inject(Hash.new(false)) do |methods, attr|

        attr_final = downcase_legacy_field_names ? attr.to_s.downcase : attr

        attr_name = attr_final
        methods[attr_final.to_sym]       = attr_name
        methods["#{attr_final}=".to_sym] = attr_name
        methods["#{attr_final}?".to_sym] = attr_name
        methods["#{attr_final}_before_type_cast".to_sym] = attr_name
        methods
      end
    end

   # adapted from: http://wiki.rubyonrails.org/rails/pages/HowToUseLegacySchemas
    def downcase_legacy_field_methods
      column_names.each do |name|
       next if name == primary_key
       a = name.to_s.underscore

       define_method(a.to_sym) do
         read_attribute(name)
       end

       define_method("#{a}=".to_sym) do |value|
         write_attribute(name, value)
       end

       define_method("#{a}?".to_sym) do
         self.send("#{name}?".to_sym)
       end

      end
    end


end 




ActiveRecord::Base.downcase_legacy_field_names = true

: http://wiki.rubyonrails.org/rails/pages/HowToUseLegacySchemas

column_methods_hash ActiveRecord. , . - , ActiveRecord ( ) SQL .

downcase_legacy_field_methods - , , downcase.d.

ActiveRecord. , ActiveRecord. environment.rb.

ActiveRecord, . downcase_legacy_field_methods. :

class LegacyDatabaseModel < ActiveRecord::Base
  downcase_legacy_field_methods

  def cubits_to_feet
    #conversion code goes here
  end
end
+5

Legacy SQL Server, ASP.net SQL, .. ASP.net, .

, , , , Rails, , / ASP.net.

, .., .

, , , .

+2

:

User.find(:all, :conditions => ['name = ?', "bob"])

... ?

User.find_all_by_name("bob")

(This should be in a comment, but I am new and cannot comment :) A stack trace will help me figure out and see what happens. What version of rails are you using?

+1
source

This post helped me a lot and I formalized it into a plugin: http://github.com/reidmix/legacy_mappings , which I wanted to share. Click, it looks like the URL is encoded.

0
source

Source: https://habr.com/ru/post/1703056/


All Articles