переменные в представлениях воспроизведения

Я нашел несколько ответов онлайн на мой вопрос, но все для старых версий игры, которые больше не работают.

Я пытаюсь найти способ использовать переменную в качестве части пути к шаблону.
Я понимаю, что это уберет проверку типа и т. д., Но это для генератора/прототипирования/внутреннего инструмента и не то, что увидит общественность/внешний мир.

вот кодез:

Лучший ответ, который я могу найти в качестве работы вокруг:

def index(page: String) = Action {
   page match {
      case "something" => Ok(views.html.examples.something())
      case "else" => Ok(views.html.examples.else())
      case "another" => Ok(views.html.examples.elements.another())
   }
}

в идеале что-то вроде этого имело бы больше смысла:

def index(page: String) = Action {
  Ok(views.html.getClassFromStringOrSomething(page));
}

Я использую последнюю версию Play framework (2.5.* ) с scala.

является ли использование матча единственным способом?
Должен быть динамический почему возвращать представление?

n.b. Я нашел множество предложений в интернете, которые используютplay.api.templates.Html/play.twirl.api.Html, которые, кажется, больше не работают, Htmlне могут быть найдены, поэтому я предполагаю, что api имеет изменения других версий.

Используя это, я получаю:

def index(page: String, parent: String) = Action {

  val clazz: Class[_] = Play.current.classloader.loadClass(page)
  val render: Method = clazz.getDeclaredMethod("render")
  val view = Some(render.invoke(clazz).asInstanceOf[play.twirl.api.Html])
  Ok(view)
}

Это дает мне ошибку
Cannot write an instance of Some[play.twirl.api.Html] to HTTP response. Try to define a Writeable[Some[play.twirl.api.Html]]и вот где я застрял

1 ответ

  1. Я добавил ответ здесь исключительно для того, чтобы помочь кому-либо еще, попавшему в эту проблему.

    @Mikesname был правильным, удалите Some()и оно ‘должно’ все работать нормально.

    Проблема заключалась в том, что я динамически загружал имя класса/представления, но не использовал полное имя класса. Я загружал ,somethingкогда должен былview.html.something.

    Вот код, который я использовал для работы функции
    (нуждается в очистке, но он работает, также учитывает представления, названные indexвнутри каталога, т. е. views.html.parent -> /parent/index.scala.html

        package controllers
    
    import javax.inject.{Inject, Singleton}
    
    import play.api.Play
    import play.api.mvc.{Action, Controller}
    
    import play.twirl.api.Html
    
    @Singleton
    class PathController @Inject() extends Controller {
    
      def index(page: String, parent: String, grandparent: String) = Action {
         Ok(buildView(buildClassName(page, parent, grandparent)))
      }
    
      def buildClassName(page: String, parent: String, grandparent: String): String = {
        val pathGrandParent = if (grandparent != null) grandparent  + '.' else ""
        val pathParent = if (parent != null) parent + '.' else ""
    
        "views.html." + pathGrandParent + pathParent + page
      }
    
      def loadClass(name: String): Class[_] =  {
        try {
          Play.current.classloader.loadClass(name)
        } catch {
            case _: Throwable => {
              Play.current.classloader.loadClass(name + ".index")
            }
        }
      }
    
      def buildView(name: String): Html = {
        val clazz = loadClass(name)
        clazz.getDeclaredMethod("render").invoke(clazz).asInstanceOf[play.twirl.api.Html]
      }
    }
    

    Я бы предположил, что есть гораздо лучший способ сделать часть представления индекса, а затем попробовать/поймать, но это нормально для инструмента, который я создаю