2012-02-22 1 views
0

Rails 3.1, Ruby 1.9.2, activerecord-sqlserver-adapter gem을 통한 SQL Server 2008 데이터베이스 사용. 전 레거시 데이터베이스로 작업 중이므로 자발적이지 않았습니다.ActiveAdmin 쿼리 중에 누락 된 열 이름

ActiveAdmin에 이상한 문제가 있습니다. 나는 전에 ActiveAdmin을 사용하지 않았고 Railcast를보고 나서 추가했습니다. 표준 설치 지침에 따라 관리 콘솔에 로그인 할 수 있습니다.

내가 모델 추가

:

rails generate active_admin:resource Payment 

모델 (복수의)는 이제 ActiveAdmin을 대시 보드에 볼 수 있습니다. - 그것의 이름이 열을 좋아하지 않는 나는 SQL Server 데이터베이스에 직접 실행하는 경우

TinyTds::Error: No column name was specified for column 2 of '__rnt'.: EXEC 
sp_executesql N'SELECT TOP (1) [__rnt].* FROM (SELECT ROW_NUMBER() OVER (ORDER 
BY [Payments].[UPaymentID] ASC) AS [__rn], 1 FROM [Payments]) AS [__rnt] 
WHERE [__rnt].[__rn] > (0) ORDER BY [__rnt].[__rn] ASC' 

지금,이 쿼리는 같은 오류를 반환 : 내가 링크를 클릭 그러나, 나는 다음과 같은 오류가 발생합니다 "1".

문제가 무엇인지 확인하기 위해 파기를 시작했습니다. 확실한 장소는 activeadmin과 activerecord, 그리고 activerecord와 SQL Server 어댑터 간의 변환입니다. 첫 번째 교차로에 대한 스택 추적은 다음과 같습니다.

activerecord (3.1.0) lib/active_record/relation/finder_methods.rb:197:in `exists?' 
activeadmin (0.4.2) lib/active_admin/views/pages/index.rb:41:in `items_in_collection?' 
activeadmin (0.4.2) lib/active_admin/views/pages/index.rb:20:in `main_content' 

items_in_collection과 유사합니까? 부름이 있습니까? 주문 필터가 제거 된 컬렉션 이 시점에서 ActiveRecord로 전달합니다. 우리는 SQL 서버 어댑터 액티브의 전환 보면, 그것은 SELECT 문이 이미 형성되어있는 것처럼 보이는 :

activerecord-sqlserver-adapter (3.1.6) lib/active_record/connection_adapters/sqlserver/database_statements.rb:348:in `do_exec_query' 
activerecord-sqlserver-adapter (3.1.6) lib/active_record/connection_adapters/sqlserver/database_statements.rb:24:in `exec_query' 
activerecord-sqlserver-adapter (3.1.6) lib/active_record/connection_adapters/sqlserver/database_statements.rb:297:in `select' 
activerecord (3.1.0) lib/active_record/connection_adapters/abstract/database_statements.rb:18:in `select_all' 
activerecord (3.1.0) lib/active_record/connection_adapters/abstract/query_cache.rb:61:in `block in select_all' 

나는 SQL이 방법은 그 발생 이유에 관해서는 완전히 혼란 스러워요 입니다. 몇 가지 후보 문제 영역이 있습니다 :

  1. 저는 이상한 스키마를 가진 레거시 데이터베이스에서 작업하고 있습니다. 내 모델 내에서 테이블 이름과 기본 키 이름을 설정해야합니다. do not가 나오는 나오는 쿼리가 적절한 기본 키와 테이블 이름을 사용하는 것 같습니다.
  2. activerecord-sqlserver-adapter 보석 문제. 그러나, 나는 소스 코드를 가져 왔고, 그런 식으로이 쿼리를 조합 할만한 것이 전혀없는 것처럼 보입니다.

비슷한 사람이 있습니까? 무슨 일이 일어나고 있는지 전체 스택을 통해 디버깅 할 필요가있을 것입니다. 그것이 처음에 여기에서 확인할 가치가있을 것 인 것이라고 상상했다.

편집 : 이제 activerecord-sqlserver-adapter의 버그라고 확신합니다. 일단 내가 가지고 있으면 결의안을 게시 할 것입니다.

편집 2 : ActiveAdmin없이 오류를 재현 할 수 있습니다. 이것은 SQL Server 어댑터가 오프셋 쿼리를 처리하는 방식과 관련이 있습니다. 호출

MyModel.offset(1).exists? 

같은 오류가 발생합니다. 모든 유닛 테스트를 통과하는 어댑터에 대한 추악한 패치가 있지만 풀 요청을하기 전에보다 세련된 솔루션을 찾으려고합니다.

답변

1

정확히 답이 아닌 것은 확실하지만 로컬 코드를 패치하고 쿼리가 현재 작동합니다.

첫째, github의 문제 :

https://github.com/rails/rails/issues/1623

및 arkadiyk의 수정을 위해 다음 풀 요청 :

https://github.com/arkadiyk/rails/commit/7e2ddddb303d17adc825ebb691097a93902fa539

기본적인 문제는 finder_methods.rb이며, 기존 코드를 가지고 줄 187 또는 188 주위 :

relation = relation.except(:select).select("1").limit(1) 
,451,515,

MSSQL이 생성 익명의 열을 barfs, 그래서 다음 코드를 해결하는 데 도움이

relation = relation.except(:select).select("1 as o").limit(1) 

희망을.

+0

감사합니다. 나는이 문제를 해결할 올바른 곳이 어디인지에 대해 혼란스러워했습니다. 확실히 레일은 1이 선택된 열을 앨리어스 (aliasing)하여 우리의 삶을 편하게 만들 수 있지만, 데이터베이스에 고유 한 문제가 더 많기 때문에 레일이 필요하지 않아야한다고 생각하고 싶습니다. 동일한 일을 수행하는 activerecord-sqlserver-adapter에 대한 패치를 가지고 있지만 훨씬 더 끔찍한 방법으로 (기본적으로 선택 처리 중에 노드를 방문하고 노드가 "1"이면 별칭 열을 추가합니다). 내 풀 요청에 대한 링크와 함께 답변을 게시 할 것입니다. –

+0

동의. 또한 임시 열 이름을 제조하는 일반 어댑터 ​​기능을보고 처리 마지막 단계에서 쿼리와 결과 집합을 정리하는 기능을 볼 수 있습니다. 이렇게하면 어댑터가 도입 된 열을 관리 할 수있을뿐 아니라 사용자가 열 이름에 대해 다른 생성기를 지정할 수 있도록 허용합니다. 그냥 생각. 나는 무엇이 가장 합리적인지를보기 위해 코드를 자세히 보지 않았다. – Raels

0

이 문제를 해결하는 데는 두 가지 방법이 있습니다. 레일에 고정 시키거나 activerecord-sqlserver-adaptor에서 수정하십시오.

Raels이 제공 한 링크가이를 수정하는 올바른 방법 일 수 있지만 끌어 오기 요청이 레일에 허용되지 않았습니다. 필자는 패치 된 버전의 레일을 사용하는 것에 대해 우려하고 있습니다. 이렇게하면 패치 된 버전을 사용하도록 강요하거나 레일이 전개 될 때 패치를 계속할 수 있습니다.

다른 대안은 activerecord-sqlserver-adapter에서이를 수정하는 것입니다. 나는 여기에 끌어 오기 요청을 제출 한 :

https://github.com/rails-sqlserver/activerecord-sqlserver-adapter/pull/171

그것은 액티브 SQLSERVER 어댑터의 메인테이너가 더 우아한 수정을 마련 할 가능성이 있습니다. 그가 대답한다면, 나는이 대답을 업데이트 할 것이다.