在我的 rails 应用程序中,我有一个具有复杂 default_scope 的特定模型,并且我试图在一个通过该模型的模型上创建 has_many 关系。不幸的是,我收到了奇怪的错误消息,这似乎是由 :through 模型的默认范围引起的。这是我的设置:
# == Schema Information
#
# Table name: training_classes
#
# id :integer not null, primary key
# created_at :datetime not null
# updated_at :datetime not null
#
class TrainingClass < ActiveRecord::Base
has_many :meetings, class_name: :ClassMeeting, foreign_key: :class_id, dependent: :destroy, inverse_of: :training_class
has_many :training_records, foreign_key: :class_id, dependent: :destroy, inverse_of: :training_class
scope :with_date, joins("
LEFT OUTER JOIN
(#{ClassMeeting.earliest_dates.to_sql}) as class_meeting
ON class_meeting.class_id = training_classes.id
")
default_scope with_date.order('class_meeting.start_time ASC')
end
# == Schema Information
#
# Table name: training_records
#
# id :integer not null, primary key
# class_id :integer
# created_at :datetime not null
# updated_at :datetime not null
#
class TrainingRecord < ActiveRecord::Base
belongs_to :training_class, foreign_key: :class_id, inverse_of: :training_records
has_many :attendance_records, inverse_of: :training_record, dependent: :destroy
has_many :meetings, class_name: :ClassMeeting, through: :training_class # This doesn't work correctly
end
# == Schema Information
#
# Table name: class_meetings
#
# id :integer not null, primary key
# class_id :integer
# start_time :datetime
# end_time :datetime
# created_at :datetime not null
# updated_at :datetime not null
#
class ClassMeeting < ActiveRecord::Base
belongs_to :training_class, foreign_key: :class_id, inverse_of: :meetings
has_many :attendance_records, class_name: :AttendanceRecord, foreign_key: :meeting_id, dependent: :destroy
has_many :training_records, through: :training_class # This doesn't work correctly
scope :earliest_dates, select('
class_meetings.id,
class_meetings.class_id,
MIN(class_meetings.start_time) as start_time'
).group('class_meetings.class_id').order('class_meetings.start_time DESC')
end
请注意,在这些示例中,为简单起见,我删除了代码。我很确定与这三个模型之间的关系相关的所有内容都完好无损。此外,关于这些模型的其他所有内容在我的应用程序中都可以正常工作,只是has_many :x, through: training_class
关系不起作用。这是我收到的错误消息:
irb(main):004:0> ClassMeeting.first.training_records
ClassMeeting Load (0.0ms) SELECT "class_meetings".* FROM "class_meetings" LIMIT 1
TrainingRecord Load (0.0ms) SELECT "training_records".* FROM "training_records" INNER JOIN "training_classes" ON "training_records"."class_id" = "training_classes"."id" WHERE "training_classes"."id" = 1 ORDER BY class_meeting.start_time ASC
ActiveRecord::StatementInvalid: SQLite3::SQLException: no such column: class_meeting.start_time: SELECT "training_records".* FROM "training_records" INNER JOIN "training_classes" ON "training_records"."class_id" = "training_classes"."id" WHERE "training_classes"."id" = 1 ORDER BY class_meeting.start_time ASC
from c:/RailsInstaller/Ruby1.9.3/lib/ruby/gems/1.9.1/gems/sqlite3-1.3.6-x86-mingw32/lib/sqlite3/database.rb:91:in `initialize'
from c:/RailsInstaller/Ruby1.9.3/lib/ruby/gems/1.9.1/gems/sqlite3-1.3.6-x86-mingw32/lib/sqlite3/database.rb:91:in `new'
from c:/RailsInstaller/Ruby1.9.3/lib/ruby/gems/1.9.1/gems/sqlite3-1.3.6-x86-mingw32/lib/sqlite3/database.rb:91:in `prepare'
from c:/RailsInstaller/Ruby1.9.3/lib/ruby/gems/1.9.1/gems/activerecord-3.2.6/lib/active_record/connection_adapters/sqlite_adapter.rb:246:in `block in exec_query'
from c:/RailsInstaller/Ruby1.9.3/lib/ruby/gems/1.9.1/gems/activerecord-3.2.6/lib/active_record/connection_adapters/abstract_adapter.rb:280:in `block in log'
from c:/RailsInstaller/Ruby1.9.3/lib/ruby/gems/1.9.1/gems/activesupport-3.2.6/lib/active_support/notifications/instrumenter.rb:20:in `instrument'
from c:/RailsInstaller/Ruby1.9.3/lib/ruby/gems/1.9.1/gems/activerecord-3.2.6/lib/active_record/connection_adapters/abstract_adapter.rb:275:in `log'
from c:/RailsInstaller/Ruby1.9.3/lib/ruby/gems/1.9.1/gems/activerecord-3.2.6/lib/active_record/connection_adapters/sqlite_adapter.rb:242:in `exec_query'
from c:/RailsInstaller/Ruby1.9.3/lib/ruby/gems/1.9.1/gems/activerecord-3.2.6/lib/active_record/connection_adapters/sqlite_adapter.rb:467:in `select'
from c:/RailsInstaller/Ruby1.9.3/lib/ruby/gems/1.9.1/gems/activerecord-3.2.6/lib/active_record/connection_adapters/abstract/database_statements.rb:18:in `select_all'
from c:/RailsInstaller/Ruby1.9.3/lib/ruby/gems/1.9.1/gems/activerecord-3.2.6/lib/active_record/connection_adapters/abstract/query_cache.rb:63:in `select_all'
from c:/RailsInstaller/Ruby1.9.3/lib/ruby/gems/1.9.1/gems/activerecord-3.2.6/lib/active_record/querying.rb:38:in `block in find_by_sql'
from c:/RailsInstaller/Ruby1.9.3/lib/ruby/gems/1.9.1/gems/activerecord-3.2.6/lib/active_record/explain.rb:40:in `logging_query_plan'
from c:/RailsInstaller/Ruby1.9.3/lib/ruby/gems/1.9.1/gems/activerecord-3.2.6/lib/active_record/querying.rb:37:in `find_by_sql'
from c:/RailsInstaller/Ruby1.9.3/lib/ruby/gems/1.9.1/gems/activerecord-3.2.6/lib/active_record/relation.rb:171:in `exec_queries'
from c:/RailsInstaller/Ruby1.9.3/lib/ruby/gems/1.9.1/gems/activerecord-3.2.6/lib/active_record/relation.rb:160:in `block in to_a'
from c:/RailsInstaller/Ruby1.9.3/lib/ruby/gems/1.9.1/gems/activerecord-3.2.6/lib/active_record/explain.rb:33:in `logging_query_plan'
from c:/RailsInstaller/Ruby1.9.3/lib/ruby/gems/1.9.1/gems/activerecord-3.2.6/lib/active_record/relation.rb:159:in `to_a'
from c:/RailsInstaller/Ruby1.9.3/lib/ruby/gems/1.9.1/gems/activerecord-3.2.6/lib/active_record/relation/finder_methods.rb:159:in `all'
from c:/RailsInstaller/Ruby1.9.3/lib/ruby/gems/1.9.1/gems/activerecord-3.2.6/lib/active_record/associations/has_many_through_association.rb:173:in `find_target'
from c:/RailsInstaller/Ruby1.9.3/lib/ruby/gems/1.9.1/gems/activerecord-3.2.6/lib/active_record/associations/collection_association.rb:333:in `load_target'
from c:in `load_target'
from c:/RailsInstaller/Ruby1.9.3/lib/ruby/gems/1.9.1/gems/activerecord-3.2.6/lib/active_record/associations/collection_proxy.rb:87:in `method_missing'
from c:/RailsInstaller/Ruby1.9.3/lib/ruby/gems/1.9.1/gems/railties-3.2.6/lib/rails/commands/console.rb:47:in `start'
from c:/RailsInstaller/Ruby1.9.3/lib/ruby/gems/1.9.1/gems/railties-3.2.6/lib/rails/commands/console.rb:8:in `start'
from c:/RailsInstaller/Ruby1.9.3/lib/ruby/gems/1.9.1/gems/railties-3.2.6/lib/rails/commands.rb:41:in `<top (required)>'
from script/rails:6:in `require'
和:
irb(main):006:0> TrainingRecord.first.meetings
TrainingRecord Load (0.0ms) SELECT "training_records".* FROM "training_records" LIMIT 1
ClassMeeting Load (0.0ms) SELECT "class_meetings".* FROM "class_meetings" INNER JOIN "training_classes" ON "class_meetings"."class_id" = "training_classes"."id" WHERE "training_classes"."id" = 23 ORDER BY class_meeting.start_time ASC
ActiveRecord::StatementInvalid: SQLite3::SQLException: no such column: class_meeting.start_time: SELECT "class_meetings".* FROM "class_meetings" INNER JOIN "training_classes" ON "class_meetings"."class_id" = "training_classes"."id" WHERE "training_classes"."id" = 23 ORDER BY class_meeting.start_time ASC
from c:/RailsInstaller/Ruby1.9.3/lib/ruby/gems/1.9.1/gems/sqlite3-1.3.6-x86-mingw32/lib/sqlite3/database.rb:91:in `initialize'
from c:/RailsInstaller/Ruby1.9.3/lib/ruby/gems/1.9.1/gems/sqlite3-1.3.6-x86-mingw32/lib/sqlite3/database.rb:91:in `new'
from c:/RailsInstaller/Ruby1.9.3/lib/ruby/gems/1.9.1/gems/sqlite3-1.3.6-x86-mingw32/lib/sqlite3/database.rb:91:in `prepare'
from c:/RailsInstaller/Ruby1.9.3/lib/ruby/gems/1.9.1/gems/activerecord-3.2.6/lib/active_record/connection_adapters/sqlite_adapter.rb:246:in `block in exec_query'
from c:/RailsInstaller/Ruby1.9.3/lib/ruby/gems/1.9.1/gems/activerecord-3.2.6/lib/active_record/connection_adapters/abstract_adapter.rb:280:in `block in log'
from c:/RailsInstaller/Ruby1.9.3/lib/ruby/gems/1.9.1/gems/activesupport-3.2.6/lib/active_support/notifications/instrumenter.rb:20:in `instrument'
from c:/RailsInstaller/Ruby1.9.3/lib/ruby/gems/1.9.1/gems/activerecord-3.2.6/lib/active_record/connection_adapters/abstract_adapter.rb:275:in `log'
from c:/RailsInstaller/Ruby1.9.3/lib/ruby/gems/1.9.1/gems/activerecord-3.2.6/lib/active_record/connection_adapters/sqlite_adapter.rb:242:in `exec_query'
from c:/RailsInstaller/Ruby1.9.3/lib/ruby/gems/1.9.1/gems/activerecord-3.2.6/lib/active_record/connection_adapters/sqlite_adapter.rb:467:in `select'
from c:/RailsInstaller/Ruby1.9.3/lib/ruby/gems/1.9.1/gems/activerecord-3.2.6/lib/active_record/connection_adapters/abstract/database_statements.rb:18:in `select_all'
from c:/RailsInstaller/Ruby1.9.3/lib/ruby/gems/1.9.1/gems/activerecord-3.2.6/lib/active_record/connection_adapters/abstract/query_cache.rb:63:in `select_all'
from c:/RailsInstaller/Ruby1.9.3/lib/ruby/gems/1.9.1/gems/activerecord-3.2.6/lib/active_record/querying.rb:38:in `block in find_by_sql'
from c:/RailsInstaller/Ruby1.9.3/lib/ruby/gems/1.9.1/gems/activerecord-3.2.6/lib/active_record/explain.rb:40:in `logging_query_plan'
from c:/RailsInstaller/Ruby1.9.3/lib/ruby/gems/1.9.1/gems/activerecord-3.2.6/lib/active_record/querying.rb:37:in `find_by_sql'
from c:/RailsInstaller/Ruby1.9.3/lib/ruby/gems/1.9.1/gems/activerecord-3.2.6/lib/active_record/relation.rb:171:in `exec_queries'
from c:/RailsInstaller/Ruby1.9.3/lib/ruby/gems/1.9.1/gems/activerecord-3.2.6/lib/active_record/relation.rb:160:in `block in to_a'
from c:/RailsInstaller/Ruby1.9.3/lib/ruby/gems/1.9.1/gems/activerecord-3.2.6/lib/active_record/explain.rb:33:in `logging_query_plan'
from c:/RailsInstaller/Ruby1.9.3/lib/ruby/gems/1.9.1/gems/activerecord-3.2.6/lib/active_record/relation.rb:159:in `to_a'
from c:/RailsInstaller/Ruby1.9.3/lib/ruby/gems/1.9.1/gems/activerecord-3.2.6/lib/active_record/relation/finder_methods.rb:159:in `all'
from c:/RailsInstaller/Ruby1.9.3/lib/ruby/gems/1.9.1/gems/activerecord-3.2.6/lib/active_record/associations/has_many_through_association.rb:173:in `find_target'
from c:/RailsInstaller/Ruby1.9.3/lib/ruby/gems/1.9.1/gems/activerecord-3.2.6/lib/active_record/associations/collection_association.rb:333:in `load_target'
from c:in `load_target'
from c:/RailsInstaller/Ruby1.9.3/lib/ruby/gems/1.9.1/gems/activerecord-3.2.6/lib/active_record/associations/collection_proxy.rb:87:in `method_missing'
from c:/RailsInstaller/Ruby1.9.3/lib/ruby/gems/1.9.1/gems/railties-3.2.6/lib/rails/commands/console.rb:47:in `start'
from c:/RailsInstaller/Ruby1.9.3/lib/ruby/gems/1.9.1/gems/railties-3.2.6/lib/rails/commands/console.rb:8:in `start'
from c:/RailsInstaller/Ruby1.9.3/lib/ruby/gems/1.9.1/gems/railties-3.2.6/lib/rails/commands.rb:41:in `<top (required)>'
from script/rails:6:in `require'
from script/rails:6:in `<main>'irb(main):007:0>
似乎 :through 关系在其repsective查询中包含了默认范围的order('class_meeting.start_time ASC')
一部分。TrainingClass
对我来说,这似乎根本不是合理的行为。这是 Rails 的错误吗?我已经能够通过使用 :finder_sql 关系选项使关系正常工作,但这似乎是一个相当尴尬的解决方案。有谁知道我该如何解决这个问题?(也许是一种让关系忽略TrainingClass
默认范围的方法?)