如何在Rails中处理静态内容?

74

看了一些不同的选项:

一个选项是将静态页面放在public/文件夹中,但我希望来自layout/application的头部保持一致。

我尝试了这个选项,但是遇到了错误:

# in routes.rb:
map.connect '*path', :controller => 'content', :action => 'show'

# in content_controller.rb:
def show
  render :action => params[:path].join('/')
end

我想要一个简单的方法,只需创建一个.rhtml文件,就可以轻松地将我的常见问题解答、联系方式、服务条款、隐私政策等非应用程序类型的页面放在易于访问的地方。有谁做过这样的事情吗?

8个回答

179

对于 Rails6Rails5Rails4,您可以执行以下操作:

在 routes.rb 的末尾添加以下行:

  get ':action' => 'static#:action'

访问 根目录/welcome,将渲染 /app/views/static/welcome.html.erb

不要忘记创建一个“静态”控制器,即使您不需要在其中放置任何内容。

限制:如果有人尝试访问不存在的页面,它将抛出应用程序错误。 请查看下面的解决方案以处理404错误

对于Rails3,您必须使用“match”而不是“get”

  match ':action' => 'static#:action'

4
太棒了,正是我所需要的。由于它适用于最新的Rails版本,应该会得到更多的赞同票。 - spong
14
如果有人想知道,这里的“:action”是一个魔法词;如果你用“:id”或“:title”或其他什么东西来调用它是行不通的。 - mahemoff
1
在Rails4中,我在开发模式下收到一个提醒,提示我将“match”替换为“get”。 - joseph
2
如何避免异常,因为这是一个全捕获?理想情况下,您希望给出404而不是触发异常。我试图找到这是如何记录的,它不会触发缺少方法,它只是在磁盘上查找视图。 - Amala
1
@Rich 不,因为这是通配符,所以没有link_to助手。您需要直接指向原始路径,例如/hello - Roland Studer
显示剩余7条评论

31

22

这取决于URL的结构。如果您希望路径从 / 开始(例如 /about_us),则:

map.connect ':action', :controller => "static"
这应该放在你的路由文件的最后。将你的 .html.erb 文件放入 app/views/static 中,然后就完成了。
例如:添加 about_us.html.erb,就会在 /about_us 上生成一个页面。
你在问题中提到的项目很适合用于捕获所有的路由,你可以分析 params[:path] 中给出的数组。更多信息请参见http://railscasts.com/episodes/46-catch-all-route

13

渲染一个操作没有意义。你需要使用布局来渲染一个模板(或文件)。

# Path relative to app/views with controller's layout
render :template => params[:path]

# ... OR

# Absolute path. You need to be explicit about rendering with a layout
render :file => params[:path], :layout => true

使用页面缓存,您可以从单个操作中提供多种不同的模板。

# app/controllers/static_controller.rb
class StaticController < ApplicationController
  layout 'static'

  caches_page :show

  def show
    valid = %w(static1 static2 static3)
    if valid.include?(params[:path])
      render :template => File.join('static', params[:path])
    else
      render :file   => File.join(Rails.root, 'public', '404.html'), 
             :status => 404
    end
  end
end

最后,我们需要定义一个路由。

# config/routes.rb
map.connect 'static/:path', :controller => 'static', :action => 'show'

尝试访问这些静态页面。如果路径中不包含有效的模板,我们将呈现404文件并返回404状态。

  • http://localhost:3000/static/static1
  • http://localhost:3000/static/static3
  • http://localhost:3000/static/static2

如果您查看 app/public 目录,您会注意到一个 static/ 目录,其中包含 static1.html、static2.html 和 static3.html。在第一次访问页面后,由于页面缓存,任何后续请求都将完全是静态的。


3

根据给出的答案,我使用了通用控制器的思路,但是我想捕获404错误,因此我在其中加入了一个操作来处理这两种情况:

# app/controllers/static_controller.rb
class StaticController < ApplicationController
    def static_or_404
        render params[:static]
    rescue ActionView::MissingTemplate
        render :not_found
    end
end

然后在我的路由器底部:

# config/routes.rb
get '*static', to: 'static#static_or_404'

它会展示与路径同名的app/views/static视图,如果没有这样的视图,则会展示app/views/static/not_found.html.erb。你也可以用redirect_to root_path或任何你想要发生的事情来替换render :not_found

太棒了!我刚回来想写如何处理404错误的答案,然后发现你已经做了,现在我会链接到你的解决方案。从某种意义上说,为了可见性,更新我的答案仍然是好的。或者也许你想编辑我的答案,这样你就能得到一些归属。非常值得的赞成票。我希望最佳答案不会太长时间留在最少的投票中。 - Roland Studer
太棒了。我能够用8行代码取代高电压。非常感谢,这非常有帮助。 - Rich

2

如果您有一个Home Controller,其中包含show、aboutus和privacy等几个方法:

class HomesController < ApplicationController
  def show
  end
  def privacy
  end
  def aboutus
  end
end

将show方法映射到根路由,并将其他方法映射到一些命名路由,例如

map.root      :controller => "homes", :action => "show"
map.aboutus "/aboutus", :controller => "homes", :action => "aboutus"
map.privacy "/privacy", :controller => "homes", :action => "privacy"

对于每个视图,都有相应的内容

app/views/homes/aboutus.html.erb --> you get http://localhost:3000/aboutus
app/views/homes/show.html.erb --> you get http://localhost:3000 (root)
app/views/homes/privacy.html.erb --> you get http://localhost:3000/privacy

所有内容都使用相同布局,位于 app/views/layout/application.html.erb 中。


2

Lindsaar的解决方案是我见过的最好的之一。他构建了一个静态页面缓存,当git版本更改时会过期。

<%= cache "site-page-#{@page_name}-#{App.git_revision}" do %>
  <%= render :partial => @page_name %>
<% end %>

1
创建一个PagesController来处理静态页面(例如联系方式),并插入。
def contact_page
end

在config/routes.rb中插入。
get 'contact' => 'pages#contact_page'

这将显示来自views/pages/contact_page.html.erb的内容。


为什么要踩我?我知道我的回答是关于Rails 4的,但它仍然可以回答别人的问题。 - GoodViber

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接