1

런타임시 스코프를 동적으로 결합하여 사용자 입력을 기반으로 커스텀 쿼리를 생성하고 싶습니다. Book 모델이있는 라이브러리 응용 프로그램이 있고 다음 범위가 정의되어 있다고 가정 해보십시오. checked_out, fiction, non_fiction, overdue, and checked_out_by.Ruby on Rails는 스코프를 동적으로 결합합니다.

last scope, checked_out_by은 library_user_id를 인수로 사용하는 람다입니다. 이 응용 프로그램을 사용하면 사서가 사용자 입력을 기반으로 동적으로 이러한 범위를 결합하는 다양한 종류의 쿼리를 실행할 수 있습니다. 사서가 체크 아웃 된 모든 논픽션 책을 보여주는 보고서를 작성하고자하는 경우 그래서,이 같은 것을 할 쉽게 :하지만

criteria = ["non_fiction", "checked_out"] <= array built based on what the user selected 
books = Book.scoped 
criteria.each {|criteria| books = books.send(criteria)} 

을 나는대로 설정 범위와이를 어떻게 람다? 예를 들어, 사용자가 기한이 지난 책과 특정 사람이 checked_out_을 보여주는 쿼리를 만들고 싶다면? 이 경우 기준 배열에 "연체 된"및 "checked_out_by"범위가 포함되도록하고 싶지만 람다 범위로 설정하는 방법을 알 수는 없습니다. 나는 시도했다 :

criteria = ["non_fiction", {:checked_out_by => 6}] 

그러나 나는 저에게 "{:checked_out_by => 6} is not a symbol"를 말하는 과실을 준다. 나는 또한 시도했다

와 약간의 다른 변종. 그러나 그들 중의 누구도 일하지 않았다. 누구든지이 작업을 수행하는 방법을 알고 있습니까?

답변

1

두 번째 매개 변수로 매개 변수를 send에 보낼 수 있습니다.

criteria = [:non_fiction, { checked_out_by: 6 }] 

criteria.each do |c| 
    case c 
    when Hash then c.keys.each { |key| books = books.send key, c[key] } 
    when Symbol then books = books.send c 
    end 
end 

을 아니면 Hash 대신에 OpenStruct을 사용할 수 있습니다 : 당신의 예제에, 당신이 뭔가를 할 수 있습니다.

criteria = [:non_fiction, OpenStruct.new(key: :checked_out_by, value: 6)] 

    criteria.each do |c| 
     books = case c 
     when OpenStruct then books.send c.key, c.value 
     when Symbol then books.send c 
     end 
    end 

또는 더 나은 방법은 필요한 키와 값을 가진 클래스를 만드는 것입니다.

+0

고맙습니다. 훌륭한 제안입니다. 나는 처음으로 문제를 해결했습니다. –