我正致力于在Ruby on Rails应用程序中创建问卷数据模型,该应用程序需要复合主键和外键。对于此任务,我使用composite-primary-keys gem与SQLServer,我过去使用的配对。不幸的是,当我使用复合进行查找时遇到问题,无论是指定.find([x,y,z]),还是使用belongs_to关系定义的方法。 有趣的是,但是,它通过has_many定义的关系正常运行。我的模型如下(错误将在本文的底部):
class QuestionSet < ActiveRecord::Base
self.primary_keys = :question_set_id, :generation, :language_id
has_many :question_set_questions,
foreign_key: [:set_id, :set_generation],
primary_key: [:question_set_id, :generation]
has_many :questions, through: :question_set_questions
end
class QuestionSetQuestion < ActiveRecord::Base
belongs_to :question_set,
-> { where :language_id => Language.current_language.id },
foreign_key: [:set_id, :set_generation],
primary_key: [:question_set_id, :generation]
belongs_to :question,
-> { where :language_id => Language.current_language.id },
foreign_key: [:question_id, :question_generation],
primary_key: [:question_id, :generation]
end
class Question < ActiveRecord::Base
self.primary_keys = :question_id, :generation, :language_id
has_many :question_set_questions,
foreign_key: [:question_id, :question_generation],
primary_key: [:question_id, :generation]
has_many :question_sets, through: :question_set_questions
end
如果模型需要解释,QuestionSet和Question每个都有一个复合主键,由三个整数组成:question_或question_set_ id,generation和language_id。它们受QuestionnaireSetQuestion约束,其中包含id和分组编号,并使用当前选定的语言(通过Language.current_language.id
)来实现正确的记录。
如果我说的话:
qs = QuestionSet.first
qs.questions
然后一切都很完美,我看到了我期望的确切结果。我已经对此进行了非常彻底的测试,很多问题,很多问题集,很多语言,很多分组。在QuestionSet上调用.questions非常有效。它也是相反的方式,... ...
q = Question.first
q.question_sets
...每次都返回正确的结果。
此外,在问题或问题集上调用.question_set_questions可以正常运行。
如果我说......
qsq = QuestionSetQuestion.first
qsq.question
# or
qsq.question_set
......我收到错误。当我说:
时,我得到同样的错误Question.find([1,1,1])
# or
QuestionSet.find([1,1,1])
该错误如下:
EXEC sp_executesql N'SELECT [questions].* FROM [questions] WHERE ([questions].[question_id] = @0 AND [questions].[generat
ion] = @1 AND [questions].[language_id] = @2) ORDER BY [questions].[question_id,generation,language_id] ASC OFFSET 0 ROWS FETCH NEXT 1 ROWS ONLY',
N'@0 int, @1 int, @2 int', @0 = 1, @1 = 1, @2 = 1 [["question_id", 1], ["generation", 1], ["language_id", 1]]
TinyTds::Error: Invalid column name 'question_id,generation,language_id'.: EXEC sp_executesql N'SELECT [questions].* FROM [questions] WHERE ([ques
tions].[question_id] = @0 AND [questions].[generation] = @1 AND [questions].[language_id] = @2) ORDER BY [questions].[question_id,generation,langu
age_id] ASC OFFSET 0 ROWS FETCH NEXT 1 ROWS ONLY', N'@0 int, @1 int, @2 int', @0 = 1, @1 = 1, @2 = 1
ActiveRecord::StatementInvalid: TinyTds::Error: Invalid column name 'question_id,generation,language_id'.: EXEC sp_executesql N'SELECT [questions]
.* FROM [questions] WHERE ([questions].[question_id] = @0 AND [questions].[generation] = @1 AND [questions].[language_id] = @2) ORDER BY [question
s].[question_id,generation,language_id] ASC OFFSET 0 ROWS FETCH NEXT 1 ROWS ONLY', N'@0 int, @1 int, @2 int', @0 = 1, @1 = 1, @2 = 1
from c:/RailsInstaller/Ruby2.0.0/lib/ruby/gems/2.0.0/gems/activerecord-sqlserver-adapter-4.2.3/lib/active_record/connection_adapters/sqlser
ver/database_statements.rb:336:in `each'
from c:/RailsInstaller/Ruby2.0.0/lib/ruby/gems/2.0.0/gems/activerecord-sqlserver-adapter-4.2.3/lib/active_record/connection_adapters/sqlser
ver/database_statements.rb:336:in `handle_to_names_and_values_dblib'
from c:/RailsInstaller/Ruby2.0.0/lib/ruby/gems/2.0.0/gems/activerecord-sqlserver-adapter-4.2.3/lib/active_record/connection_adapters/sqlser
ver/database_statements.rb:325:in `handle_to_names_and_values'
from c:/RailsInstaller/Ruby2.0.0/lib/ruby/gems/2.0.0/gems/activerecord-sqlserver-adapter-4.2.3/lib/active_record/connection_adapters/sqlser
ver/database_statements.rb:300:in `_raw_select'
from c:/RailsInstaller/Ruby2.0.0/lib/ruby/gems/2.0.0/gems/activerecord-sqlserver-adapter-4.2.3/lib/active_record/connection_adapters/sqlser
ver/database_statements.rb:295:in `block in raw_select'
from c:/RailsInstaller/Ruby2.0.0/lib/ruby/gems/2.0.0/gems/activerecord-4.2.0/lib/active_record/connection_adapters/abstract_adapter.rb:466:
in `block in log'
from c:/RailsInstaller/Ruby2.0.0/lib/ruby/gems/2.0.0/gems/activesupport-4.2.0/lib/active_support/notifications/instrumenter.rb:20:in `instr
ument'
from c:/RailsInstaller/Ruby2.0.0/lib/ruby/gems/2.0.0/gems/activerecord-4.2.0/lib/active_record/connection_adapters/abstract_adapter.rb:460:
in `log'
from c:/RailsInstaller/Ruby2.0.0/lib/ruby/gems/2.0.0/gems/activerecord-sqlserver-adapter-4.2.3/lib/active_record/connection_adapters/sqlser
ver/database_statements.rb:295:in `raw_select'
from c:/RailsInstaller/Ruby2.0.0/lib/ruby/gems/2.0.0/gems/activerecord-sqlserver-adapter-4.2.3/lib/active_record/connection_adapters/sqlser
ver/database_statements.rb:244:in `sp_executesql'
from c:/RailsInstaller/Ruby2.0.0/lib/ruby/gems/2.0.0/gems/activerecord-sqlserver-adapter-4.2.3/lib/active_record/connection_adapters/sqlser
ver/database_statements.rb:19:in `exec_query'
from c:/RailsInstaller/Ruby2.0.0/lib/ruby/gems/2.0.0/gems/activerecord-sqlserver-adapter-4.2.3/lib/active_record/connection_adapters/sqlser
ver/database_statements.rb:199:in `select'
from c:/RailsInstaller/Ruby2.0.0/lib/ruby/gems/2.0.0/gems/activerecord-4.2.0/lib/active_record/connection_adapters/abstract/database_statem
ents.rb:32:in `select_all'
from c:/RailsInstaller/Ruby2.0.0/lib/ruby/gems/2.0.0/gems/activerecord-4.2.0/lib/active_record/connection_adapters/abstract/query_cache.rb:
70:in `select_all'
from c:/RailsInstaller/Ruby2.0.0/lib/ruby/gems/2.0.0/gems/activerecord-4.2.0/lib/active_record/querying.rb:39:in `find_by_sql'
from c:/RailsInstaller/Ruby2.0.0/lib/ruby/gems/2.0.0/gems/activerecord-4.2.0/lib/active_record/relation.rb:638:in `exec_queries'
... 1 levels...
from c:/RailsInstaller/Ruby2.0.0/lib/ruby/gems/2.0.0/gems/activerecord-4.2.0/lib/active_record/relation.rb:243:in `to_a'
from c:/RailsInstaller/Ruby2.0.0/lib/ruby/gems/2.0.0/gems/activerecord-4.2.0/lib/active_record/relation/finder_methods.rb:487:in `find_take
'
from c:/RailsInstaller/Ruby2.0.0/lib/ruby/gems/2.0.0/gems/activerecord-4.2.0/lib/active_record/relation/finder_methods.rb:105:in `take'
from c:/RailsInstaller/Ruby2.0.0/lib/ruby/gems/2.0.0/gems/composite_primary_keys-8.1.0/lib/composite_primary_keys/relation/finder_methods.r
b:124:in `find_one'
from c:/RailsInstaller/Ruby2.0.0/lib/ruby/gems/2.0.0/gems/composite_primary_keys-8.1.0/lib/composite_primary_keys/relation/finder_methods.r
b:97:in `find_with_ids'
from c:/RailsInstaller/Ruby2.0.0/lib/ruby/gems/2.0.0/gems/activerecord-4.2.0/lib/active_record/relation/finder_methods.rb:71:in `find'
from c:in `find'
from c:/RailsInstaller/Ruby2.0.0/lib/ruby/gems/2.0.0/gems/composite_primary_keys-8.1.0/lib/composite_primary_keys/core.rb:26:in `find'
from (irb):1
from c:/RailsInstaller/Ruby2.0.0/lib/ruby/gems/2.0.0/gems/railties-4.2.0/lib/rails/commands/console.rb:110:in `start'
from c:/RailsInstaller/Ruby2.0.0/lib/ruby/gems/2.0.0/gems/railties-4.2.0/lib/rails/commands/console.rb:9:in `start'
from c:/RailsInstaller/Ruby2.0.0/lib/ruby/gems/2.0.0/gems/railties-4.2.0/lib/rails/commands/commands_tasks.rb:68:in `console'
from c:/RailsInstaller/Ruby2.0.0/lib/ruby/gems/2.0.0/gems/railties-4.2.0/lib/rails/commands/commands_tasks.rb:39:in `run_command!'
from c:/RailsInstaller/Ruby2.0.0/lib/ruby/gems/2.0.0/gems/railties-4.2.0/lib/rails/commands.rb:17:in `<top (required)>'
from bin/rails:4:in `require'
from bin/rails:4:in `<main>'irb(main):
对不起,这太乱了。 我相信正确的重点是
TinyTds::Error: Invalid column name 'question_id,generation,language_id'
据我所知,它试图找到一个名为&#39; question_id,generation,language_id&#39;的实际列,并且因为显然没有这样的列存在而失败。我怀疑其他命令工作的原因是因为他们在这三个字段中构建了一个.where语句,而这是滥用.find。也就是说,我只是根据我观察到的行为进行推测。
如果有人对此有任何想法,我会非常感激,因为这被证明是一个重要的时间点,我还没有找到任何东西。
谢谢!
答案 0 :(得分:0)
我对一个没有在数据库中定义主键的表有同样的问题。我在这里创建了一个问题 - https://github.com/composite-primary-keys/composite_primary_keys/issues/316 - 并且还发布了一个对我有用的修补程序。