2012-08-13 9 views
10

Vorrei creare un'app Rails che consenta agli utenti di immettere dati e quindi consentire loro di cambiare il tema della pagina. In questo modo i loro dati potrebbero essere stilizzati in modo diverso in base al tema che scelgono. Come potrei fare questo?Temi nell'app Rails

  1. Cambia foglio di stile?
  2. Due viste separate con classi/elementi diversi?
  3. Dinamicamente basta cambiare classi/id/selettori?
  4. ?

Grazie

+0

cosa hai provato? –

+1

Sono nuovo alle rotaie quindi non sono sicuro di dove o come iniziare. Non posso trovare alcuna informazione su questo online. Come fanno i wordpress a cambiare tema così bene? – AdamT

risposta

12

Il modo più semplice per tema un sito è semplicemente creare un collegamento a un foglio di stile diverso. Puoi farlo dinamicamente usando qualcosa come:

# 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 

Quindi puoi avere un paio di manifesti per temi. Ad esempio, la directory degli asset può essere simile a questa:

  • app/attività/fogli di stile
    • application.css
    • buttons.css
    • theme1/
      • index.css
      • buttons.css
    • t heme2/
      • index.css
      • buttons.css

Questo vi permetterà di cominciare con la pura tematizzazione css. A un certo punto probabilmente vorrai anche i layout javascript e html. Quando si avvia trovando il bisogno di fare qualcosa di simile nel tuo html:

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

allora è il momento di attuare un più robusto quadro tematizzazione:

  • namespace i modelli HTML per tema (ad esempio app/views /themes/theme1/users/index.html.erb) e renderizza la versione a tema invece dello spazio dei nomi predefinito
  • solo i partial per modello (ad esempio app/views/themes/theme1/users/_form.html.erb) e aggiungi un metodo di supporto come render_themed_partial
  • simi LAR agli approcci di cui sopra, ma quando i temi diventano molto grandi, si dovrebbe prendere in considerazione la loro messa in proprie gemme come rotaie motori

Nota: Questo è tutto per i temi statici. Per i temi dinamici (ad esempio, in cui un amministratore può accedere e modificare i fogli di stile o html), è necessario memorizzare le informazioni sul tema nel database. A seconda dell'architettura, è possibile fornire un set di temi statici e quindi un altro tema che acquisisce dinamicamente i dati di stile dal database.A quel punto, tuttavia, stai sviluppando un CMS, quindi è fuori dallo scopo di questa risposta :)

+0

Questa è una risposta fantastica, grazie Ben! – kgx

8

Se creiamo fogli di stile diversi per ogni tema e apportando piccoli cambiamenti, allora dobbiamo fare lo stesso cambia in tutti i fogli di stile. Sarà davvero un mal di testa. In alternativa, è possibile utilizzare i concetti SASS (mixins).

Aggiungi nella tua Gemfile

gem 'sass-rails' 

poi

bundle install 

Ora è necessario avere gli stili CSS in un unico file SCSS. 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; 
    } 
} 

quindi è possibile creare qualsiasi numero di temi. Per esempio 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); 

Ora nel tuo html

<%= stylesheet_link_tag "Theme_Blue" %> 

utilizzerà i tutte le classi CSS di cui basic_styles.scss con i colori blu.

È possibile aggiungere qualsiasi numero di file di temi come Theme_Blue.scss. e cambiare per

<%= stylesheet_link_tag current_user.theme %> 

In questo modo, è necessario modificare solo le basic_styles.scss per eventuali modifiche.

+0

davvero una buona risposta grazie – jpwynn

+0

C'è un modo per passare da variabili a mixin per generare due diversi application.css? Esempio: application-dark.css e application-light.css. –

2

Sono riuscito a estrarre l'essenza dalla risposta di Chamnap (che non ha funzionato per qualche motivo - forse la versione di 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 

Si può leggere su di esso qui:

probabilmente si dovrà aggiungere al percorso di asset e la lista di pre-compilazione (o altro utilizzare la gemma senza utilizzare il metodo 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" } 

Ricordarsi di avere JS e le immagini in sottodirectory con il nome del tema. Potrebbero essere separati sul server, ma per il browser e la cache, /images/logo.png ha lo stesso aspetto per entrambi i temi. Quindi devi usare /images/theme1/logo.png e /images/theme2/logo.png.