Введение : я создаю отдельное (не Rails) приложение, которое использует ActiveRecord и ActiveRecord SQL Server Adapter для доступа к базе данных для коммерческого приложения. Я не могу изменить схему базы данных или сервер базы данных так, как мне бы хотелось. Я пытался изменить имена ниже, чтобы защитить виновных.
Базовый класс модели:
class AppRecord < ActiveRecord::Base
after_initialize :parent_init
attr_reader :_downcase_field_values
attr_accessor :downcase_field_values
self.primary_key = 'IRN'
def parent_init
set_downcase_field_values
end
def set_downcase_field_values
@downcase_field_values ||= []
@_downcase_field_values = self.attributes.keys.select { |att| att if (att.match(/IRN/) || att == "Id") }
downcase_fields! self
end
def self.table_name
"app.#{self}"
end
def to_h
self.attributes.to_options
end
end
Модель классов:
class ReportIndex < AppRecord
after_find :init
has_many :ReportIndexParameters, class_name: "ReportIndexParameters", foreign_key: "ReportIndexIRN", dependent: :destroy
has_many :ReportProperties, class_name: "ReportProperties", foreign_key: "ReportIndexIRN", dependent: :destroy
has_many :ReportLayouts, class_name: "ReportLayouts", foreign_key: "ReportIndexIRN", dependent: :destroy
has_many :ReportIndexSeries, class_name: "ReportIndexSeries", foreign_key: "ReportIndexesIRN", dependent: :destroy
has_many :ReportUserDefinedViews, class_name: "ReportUserDefinedViews", foreign_key: "BaseClassID", primary_key: "ClassId"
def init
self.downcase_field_values = %w(BaseClassID)
end
end
class ReportProperties < AppRecord
belongs_to :ReportIndex
after_find :init
has_many :ReportPropertySeriesFilters, class_name: "ReportPropertySeriesFilters", foreign_key: "ReportPropertiesIRN", dependent: :destroy
has_many :ReportPropertyParameters, class_name: "ReportPropertyParameters", foreign_key: "ReportPropertiesIRN", dependent: :destroy
def init
self.downcase_field_values = %w(ClassID)
end
end
Запрос ActiveRecord:
pp ReportIndex.includes(:ReportProperties).find_by(ReportName: report_name)
Ошибка:
/usr/local/bundle/gems/activerecord-5.1.6/lib/active_record/associations/preloader/association.rb:63:in `block in associated_records_by_owner': undefined method `association' for nil:NilClass (NoMethodError)
from /usr/local/bundle/gems/activerecord-5.1.6/lib/active_record/core.rb:367:in `init_with'
from /usr/local/bundle/gems/activerecord-5.1.6/lib/active_record/persistence.rb:69:in `instantiate'
from /usr/local/bundle/gems/activerecord-5.1.6/lib/active_record/querying.rb:50:in `block (2 levels) in find_by_sql'
from /usr/local/bundle/gems/activerecord-5.1.6/lib/active_record/result.rb:55:in `block in each'
from /usr/local/bundle/gems/activerecord-5.1.6/lib/active_record/result.rb:55:in `each'
from /usr/local/bundle/gems/activerecord-5.1.6/lib/active_record/result.rb:55:in `each'
from /usr/local/bundle/gems/activerecord-5.1.6/lib/active_record/querying.rb:50:in `map'
from /usr/local/bundle/gems/activerecord-5.1.6/lib/active_record/querying.rb:50:in `block in find_by_sql'
from /usr/local/bundle/gems/activesupport-5.1.6/lib/active_support/notifications/instrumenter.rb:21:in `instrument'
from /usr/local/bundle/gems/activerecord-5.1.6/lib/active_record/querying.rb:49:in `find_by_sql'
from /usr/local/bundle/gems/activerecord-5.1.6/lib/active_record/relation.rb:678:in `exec_queries'
from /usr/local/bundle/gems/activerecord-5.1.6/lib/active_record/relation.rb:546:in `load'
from /usr/local/bundle/gems/activerecord-5.1.6/lib/active_record/associations/preloader/association.rb:122:in `block in load_records'
from /usr/local/bundle/gems/activerecord-5.1.6/lib/active_record/associations/preloader/association.rb:121:in `each'
from /usr/local/bundle/gems/activerecord-5.1.6/lib/active_record/associations/preloader/association.rb:121:in `each_slice'
from /usr/local/bundle/gems/activerecord-5.1.6/lib/active_record/associations/preloader/association.rb:121:in `each'
from /usr/local/bundle/gems/activerecord-5.1.6/lib/active_record/associations/preloader/association.rb:121:in `flat_map'
from /usr/local/bundle/gems/activerecord-5.1.6/lib/active_record/associations/preloader/association.rb:121:in `load_records'
from /usr/local/bundle/gems/activerecord-5.1.6/lib/active_record/associations/preloader/association.rb:61:in `associated_records_by_owner'
from /usr/local/bundle/gems/activerecord-5.1.6/lib/active_record/associations/preloader/collection_association.rb:8:in `preload'
from /usr/local/bundle/gems/activerecord-5.1.6/lib/active_record/associations/preloader/association.rb:19:in `run'
from /usr/local/bundle/gems/activerecord-5.1.6/lib/active_record/associations/preloader.rb:151:in `block (2 levels) in preloaders_for_one'
from /usr/local/bundle/gems/activerecord-5.1.6/lib/active_record/associations/preloader.rb:149:in `each'
from /usr/local/bundle/gems/activerecord-5.1.6/lib/active_record/associations/preloader.rb:149:in `map'
from /usr/local/bundle/gems/activerecord-5.1.6/lib/active_record/associations/preloader.rb:149:in `block in preloaders_for_one'
from /usr/local/bundle/gems/activerecord-5.1.6/lib/active_record/associations/preloader.rb:148:in `each'
from /usr/local/bundle/gems/activerecord-5.1.6/lib/active_record/associations/preloader.rb:148:in `flat_map'
from /usr/local/bundle/gems/activerecord-5.1.6/lib/active_record/associations/preloader.rb:148:in `preloaders_for_one'
from /usr/local/bundle/gems/activerecord-5.1.6/lib/active_record/associations/preloader.rb:115:in `preloaders_on'
from /usr/local/bundle/gems/activerecord-5.1.6/lib/active_record/associations/preloader.rb:102:in `block in preload'
from /usr/local/bundle/gems/activerecord-5.1.6/lib/active_record/associations/preloader.rb:101:in `each'
from /usr/local/bundle/gems/activerecord-5.1.6/lib/active_record/associations/preloader.rb:101:in `flat_map'
from /usr/local/bundle/gems/activerecord-5.1.6/lib/active_record/associations/preloader.rb:101:in `preload'
from /usr/local/bundle/gems/activerecord-5.1.6/lib/active_record/relation.rb:686:in `block in exec_queries'
from /usr/local/bundle/gems/activerecord-5.1.6/lib/active_record/relation.rb:684:in `each'
from /usr/local/bundle/gems/activerecord-5.1.6/lib/active_record/relation.rb:684:in `exec_queries'
from /usr/local/bundle/gems/activerecord-5.1.6/lib/active_record/relation.rb:546:in `load'
from /usr/local/bundle/gems/activerecord-5.1.6/lib/active_record/relation.rb:255:in `records'
from /usr/local/bundle/gems/activerecord-5.1.6/lib/active_record/relation/finder_methods.rb:508:in `find_take'
from /usr/local/bundle/gems/activerecord-5.1.6/lib/active_record/relation/finder_methods.rb:100:in `take'
from /usr/local/bundle/gems/activerecord-5.1.6/lib/active_record/relation/finder_methods.rb:78:in `find_by'
from /src/artest.rb:13:in `<main>'
Однако SQL, сгенерированный ActiveRecord, кажется правильным:
D, [2018-06-27T17:42:49.256232 #1] DEBUG -- : SQL (33.3ms) USE [APP]
D, [2018-06-27T17:42:50.017505 #1] DEBUG -- : ReportIndex Load (40.5ms) EXEC sp_executesql N'SELECT [app].[ReportIndex].* FROM [app].[ReportIndex] WHERE [app].[ReportIndex].[ReportName] = @0 ORDER BY [app].[ReportIndex].[IRN] ASC OFFSET 0 ROWS FETCH NEXT @1 ROWS ONLY', N'@0 nvarchar(80), @1 int', @0 = N'Master Condemnation', @1 = 1 [["ReportName", nil], ["LIMIT", nil]]
D, [2018-06-27T17:42:51.043389 #1] DEBUG -- : ReportProperties Load (133.9ms) SELECT [app].[ReportProperties].* FROM [app].[ReportProperties] WHERE [app].[ReportProperties].[ReportIndexIRN] = '3cad6165-221e-4607-b5ad-01bc32f29157'
Я подозреваю, что эти нарушения проистекают из того, что мне удалось архитектурно ошибиться. Код существующей модели отлично работает для операций DELETE
и UPDATE
, но не для SELECT
с. Я приветствую улей, чтобы дать мне два цента.