如何根据Sinatra中的控制器名称请求单独的文件夹视图路径?

时间:2015-05-25 04:21:17

标签: ruby model-view-controller routing sinatra slim-lang

这是我app/controllers/application_controller.rb的内容:

要求' sinatra / base' 要求'苗条' 要求'着色'

class ApplicationController < Sinatra::Base

  # Global helpers
  helpers ApplicationHelper

  # Set folders for template to
  set :root, File.expand_path(File.join(File.dirname(__FILE__), '../'))
  puts root.green
  set :sessions,
      :httponly       => true,
      :secure         => production?,
      :expire_after   => 31557600, # 1 year
      :secret         => ENV['SESSION_SECRET'] || 'keyboardcat',
      :views          => File.expand_path(File.expand_path('../../views/', __FILE__)),
      :layout_engine  => :slim

  enable :method_override

  # No logging in testing
  configure :production, :development do
    enable :logging
  end

  # Global not found??
  not_found do
    title 'Not Found!'
    slim :not_found
  end
end

如您所见,我将views目录设置为:

File.expand_path(File.expand_path('../../views/', __FILE__))

可以是/Users/vladdy/Desktop/sinatra/app/views

configure.ru中,我然后map('/') { RootController },在所述控制器中,我使用slim :whatever

呈现视图

问题是,所有控制器的所有视图都在同一个位置!如何向Sinatra视图添加文件夹结构?

2 个答案:

答案 0 :(得分:1)

如果我理解你的问题,你想覆盖#find_template

我将此功能粘贴在名为view_directory_helper.rb的助手中。

helpers do
    def find_template(views, name, engine, &block)
      views.each { |v| super(v, name, engine, &block) }
    end
end

并且在设置视图目录时,传入一个数组,如下所示:

set :views, ['views/layouts', 'views/pages', 'views/partials']

这将让您拥有像

这样的文件夹结构
app
    -views
        -layouts
        -pages
        -partials
    -controllers

答案 1 :(得分:0)

我面临同样的任务。我没有使用Ruby编程的经验,但很长一段时间以来一直在使用PHP。我认为这样做会更容易,你可以轻松地从父类中获取孩子。有一些困难。据我了解,该语言提供回调函数,如 self.innereted ,以解决此问题。但它没有帮助,因为我无法确定给定时间内的特定路由器。也许环境变量可以帮助解决这个问题。但我能够通过解析调用堆栈来调用调用者类和包装输出函数,找到解决此问题的解决方法。我不认为这是解决问题的最优雅方式。但我能够意识到这一点。

class Base < Sinatra::Application

  configure do
    set :views, 'app/views/'
    set :root, File.expand_path('../../../', __FILE__)
  end

  def display(template, *args)
    erb File.join(current_dir, template.to_s).to_sym, *args
  end

  def current_dir
    caller_class.downcase!.split('::').last
  end

  private

  def caller_class(depth = 1)
    /<class:([\w]*)>/.match(parse_caller(caller(depth + 1)[1]))[1]
  end

  def parse_caller(at)
    Regexp.last_match[3] if /^(.+?):(\d+)(?::in `(.*)')?/ =~ at
  end
end

The last function is taken from here。它既可以用作默认的erb函数:

class Posts < Base
  get '/posts' do
    display :index , locals: { variables: {} }
  end
end

我希望它对某人有用。