Rails 应用程序中的主题

Posted

技术标签:

【中文标题】Rails 应用程序中的主题【英文标题】:Themes in Rails app 【发布时间】:2012-08-09 08:07:15 【问题描述】:

我想制作一个 Rails 应用程序,让用户输入数据,然后允许他们更改页面的主题。这样,他们的数据可以根据他们选择的主题进行不同的样式设置。我该怎么做呢?

    更改样式表? 具有不同类/元素的两个独立视图? 只需动态更改类/ID/选择器? ?

谢谢

【问题讨论】:

我是 Rails 新手,所以我不确定从哪里或如何开始。在网上找不到任何有关此的信息。 wordpress 的人如何切换主题这么好? 【参考方案1】:

为网站设置主题的最简单方法是简单地链接到不同的样式表。您可以使用以下方式动态执行此操作:

# in app/views/layouts/application.html.erb
<%= stylesheet_link_tag :application %>
<%= stylesheet_link_tag #current_theme %>

# in app/helpers/application_helper
def current_theme
  # You'll have to implement the logic for a user choosing a theme
  # and how to record that in the model.
  # Also, come up with a better name for your default theme, like 'twentyeleven' ;)
  current_user.theme || 'default'
end

然后你可以有几个主题清单。例如,您的资产目录可能如下所示:

应用程序/资产/样式表 application.css buttons.css 主题1/ index.css buttons.css 主题2/ index.css buttons.css

这将使您开始使用纯 CSS 主题。在某些时候,您可能还想要它们的 javascript 和 html 布局。当你开始发现需要在你的 html 中做这样的事情时:

<% if current_theme == 'theme1' %>
  <li>...
<% elsif current_theme == 'theme2' %>
  <b>...
<% end %>

那么是时候实现一个更强大的主题框架了:

按主题命名您的 html 模板(例如 app/views/themes/theme1/users/index.html.erb)并呈现主题版本而不是默认版本 命名空间只是模板的部分(例如app/views/themes/theme1/users/_form.html.erb)并添加一个辅助方法,如render_themed_partial 类似于上述方法,但是当主题变得非常大时,您应该考虑将它们作为 Rails 引擎放入自己的 gem 中

注意:这都是针对静态主题的。对于动态主题(例如,管理员可以登录并编辑样式表或 html),您必须将主题信息存储在数据库中。根据您的架构,您可以提供一组静态主题,然后提供另一个从数据库中动态获取样式数据的主题。但是,此时您正在开发一个 CMS,因此它超出了此答案的范围:)

【讨论】:

【参考方案2】:

如果我们为每个主题创建不同的样式表并进行小的更改,那么我们需要在所有样式表中进行相同的更改。真的会很头疼。另一种方法是使用 SASS 概念(mixins)。

添加到您的 Gemfile 中

gem 'sass-rails'

然后

bundle install

现在您需要在一个 SCSS 文件中包含您的 css 样式。 basic_styles.scss

$font_color: #565656;
$font-size: 13px;
$success-color: #088A08;
$error-color: #B40404;
@mixin basic_styles($dark_color,$light_color,$bullet_image) 

.footer
  
    background-color: rgba($dark_color,0.9);
    color: $light_color;
    text-align: center;
    position: fixed;
    bottom:0;
    left:0;
    width: 100%;
    height: 15px;
    border-top: 1px solid lighten($dark_color, 9%);     
    padding-left: 10px;
    padding-right: 10px;       
    font-size: $font_size - 2; 
  
  h3,hr,a,input
  
    color: $dark_color;
  
  h3
  
    margin-top: 2px;
    margin-bottom: 2px;
  
  hr 
    border-color: lighten($dark_color, 30%) -moz-use-text-color #FFFFFF;
    border-left: 0 none;
    border-right: 0 none;
    border-style: solid none;
    border-width: 1px 0;
  
  .btn 
  
    background-color: $dark_color;
    border-color: darken($dark_color, 15%);    
    border-radius: 4px 4px 4px 4px;
    border-style: solid;
    border-width: 1px;
    color: #FFFFFF;
    cursor: pointer;
    display: inline-block;
    line-height: 18px;
    padding: 3px 10px 3px 10px;
    text-shadow: 0 1px 1px rgba(0, 0, 0, 0.25);
    vertical-align: middle;
  
  .btn:hover
  
    text-shadow: 0 1px 1px rgba(0, 0, 0, 0.75);
    -moz-box-shadow: 0px 0px 2px 1px lighten($dark_color, 10%);
    -webkit-box-shadow: 0px 0px 2px 1px lighten($dark_color, 10%);
    box-shadow: 0px 0px 2px 1px lighten($dark_color, 10%);
  
  .success
  
    color: $success-color;
  
  .error
  
    color: $error-color;
  

然后您可以创建任意数量的主题。例如 Theme_Blue.scss

@import "basic_styles";
$dark_color: #08c;
$light_color: #FFFFFF;
$bullet_image: 'bullet_blue.png';
@include basic_styles($dark_color,$light_color,$bullet_image);

现在在你的 html 中

<%= stylesheet_link_tag "Theme_Blue" %>

将使用 basic_styles.scss 中指定的所有 css 类,颜色为蓝色。

您可以添加任意数量的主题文件,例如 Theme_Blue.scss。 并更改为

<%= stylesheet_link_tag current_user.theme %>

这样,您只需要修改basic_styles.scss即可进行任何修改。

【讨论】:

有没有办法在变量和mixins之间切换生成两个不同的application.css?示例:application-dark.css 和 application-light.css。【参考方案3】:

我设法从 Chamnap 的答案中提取了精髓(由于某种原因它不起作用 - 也许是 Rails 的版本?)。

class ApplicationController < ActionController::Base
  layout :layout_selector

  def layout_selector
    # puts "*** layout_selector #session.to_json"
    name = ['bootstrap', 'mytheme'][session[:theme].to_i] 
    # puts "*** loading theme #name"
    prepend_view_path "app/themes/#name/views"
    name
  end

你可以在这里阅读:

http://guides.rubyonrails.org/layouts_and_rendering.html#finding-layouts http://apidock.com/rails/AbstractController/Layouts/ClassMethods/layout

您可能必须添加到资产路径和预编译列表(或者使用 gem 而不使用 theme 方法)。

  Dir.glob("#Rails.root/app/themes/*/assets/*").each do |dir|
    config.assets.paths << dir
  end

  config.assets.precompile += [ Proc.new  |path, fn| fn =~ /app\/themes/ && !%w(.js .css).include?(File.extname(path))  ]
  config.assets.precompile += Dir["app/themes/*"].map  |path| "#path.split('/').last/all.js" 
  config.assets.precompile += Dir["app/themes/*"].map  |path| "#path.split('/').last/all.css" 

记得在主题名称的子目录下有 JS 和图片。它们在服务器上可能是分开的,但对于浏览器和缓存来说,/images/logo.png 对于两个主题看起来是一样的。所以你必须使用/images/theme1/logo.png/images/theme2/logo.png

【讨论】:

以上是关于Rails 应用程序中的主题的主要内容,如果未能解决你的问题,请参考以下文章

Ruby on Rails - 在我的项目中使用Themeforest Admin主题

Rails api 和本机移动应用程序身份验证

Rails + JQuery 侧边栏下拉菜单立即关闭

将 Rails 应用程序提取到插件或引擎中

rails 应用程序在 heroku 上找不到 fontawesome 图标

Rails API:实现身份验证的最佳方式?