2010-01-24 19 views
17

Ho un'app Rails relativamente semplice e vorrei memorizzare varie impostazioni di configurazione che gli utenti amministratori possono modificare mentre l'applicazione è in esecuzione, ad esempio, consentendo commenti sui post o modificando il formato di visualizzazione di l'appuntamento.Ruby on Rails - Memorizzazione configurazione applicazione

So che posso memorizzare costanti ecc nel file environment.rb, tuttavia questi sembrano essere caricati solo quando il server viene riavviato.

C'è un posto alternativo in cui posso definire queste informazioni o sarebbe meglio tenerlo nel database?

Qualsiasi consiglio è gradito.

Grazie.

risposta

9

È possibile utilizzare il database. Crea una tabella separata "impostazioni" che memorizza i parametri chiave/valore di cui hai bisogno. Lo svantaggio di questa soluzione è un problema di prestazioni (interrogando DB ogni volta che si ha bisogno di un'impostazione). Per risolvere questo problema potresti leggere/scrivere nella cache come "cache_money" o crearne uno utilizzando "Rails.cache"

+0

Ho appena postato una risposta con un approccio che mantiene le impostazioni nel database, le aggiorna secondo necessità e non subisce problemi di prestazioni senza ricorrere alla memorizzazione nella cache di cose DB. – silverdr

1

Il modo migliore è utilizzare una tabella di database. Ogni riga dovrebbe contenere una parola chiave e un valore. Semplici.

+0

OK, ma come si gestiscono i diversi tipi di dati? Ad esempio, alcune impostazioni saranno booleane, altre stringhe, altri numeri interi ecc. – Dan

+3

memorizzano una stringa JSON. – Luke

+0

Non puoi usare solo una riga e aggiungere ogni impostazione come una colonna? Il recupero di un'impostazione sarebbe quindi semplice come SELECT enable_setting FROM server_settings LIMIT 1; – Edward

4

Prova a guardare potrebbe essere quello che ti serve.

http://github.com/ledermann/rails-settings

+4

Il repo di tergipavimento è di 4 anni non aggiornato e impossibile da utilizzare con le guide moderne. La gemma di ledermann richiede di legare a un altro oggetto record attivo (ne rende impossibile l'uso per le impostazioni globali dell'app). Se vuoi le impostazioni globali delle app, https://github.com/huacnlee/rails-settings-cached è il migliore – portforwardpodcast

1

ho usato app_config gioiello per un po 'di me stesso, ma non riesce con le rotaie 2.3.9 (e probabilmente anche con rotaie 3.x), così ho trovato this blog che cita rails-settings e configuration, rails- le impostazioni memorizzano i valori nel DB, ma la configurazione ha spazi dei nomi integrati. Non li ho provati, ma penso che passerò alle impostazioni dei binari.

mi accorgo ora che the branch of rails-settings that Yi-Ru Lin mentions sembra essere più ricco di funzioni rispetto agli altri rails-settings

Jarl

15

Si potrebbe utilizzare la gemma rails-settings-cached che è un fork del gioiello rotaie-settings (collegati da Yi-Ru Lin in un'altra risposta).

Una volta messa a punto, sarete in grado di fare cose come:

Setting.foo = 123 
Setting.foo # returns 123 

È inoltre possibile gestire le impostazioni sui modelli, gli ex:

user.settings.color = :red 
user.settings.color # returns :red 
0

Per rotaie 4, se si utilizza postgresql, è possibile utilizzare HStore, che è proprio come un attributo serializzabile, ma si fa una query SQL con esso.

Per le guide 3, è possibile utilizzare la gemma activerecord-postgres-hstore.

0

Ho provato https://github.com/huacnlee/rails-settings-cached, ma non funziona come descritto. Ovviamente l'autore ha dimenticato di menzionare alcune ulteriori messe a punto nella descrizione dell'uso della gemma. Non sono riuscito a scrivere un controller per la manipolazione delle impostazioni.

Invece sono riuscito a utilizzare https://github.com/paulca/configurable_engine - nonostante alcuni problemi minori, questo gioiello è di gran lunga più ragionevole di rails-settings-cached.

La gemma configurable_engine ha uno svantaggio: ha le route codificate che sono oscure e non convenienti. L'autore della gemma promised to correct it, ma ha detto che al momento non ne ha avuto il tempo.

Quindi questo problema è stato facilmente organizzato semplicemente creando i miei percorsi. Qui è il mio codice (aggiunto per rendere questo gioiello veramente lavorare):

routes.rb

namespace :admin do 
    resources :configurables, only: [:index, :show, :edit, :update, :destroy] 
end 

admin/configurables_controller.rb

class Admin::ConfigurablesController < Admin::ApplicationController 
     # include the engine controller actions 
    include ConfigurableEngine::ConfigurablesController 

    before_action :set_configurable, only: [:show, :edit, :update, :destroy] 

    def index 

    @configurables = (Configurable.all.size > 0 ? Configurable.all : []) + 
    (Configurable.defaults.keys - Configurable.all.collect { |c| c.name }) 

    end 

    def show 
    end 

    def edit 
    new = params[:new] 
    end 

    def new 

    respond_to do |format| 

     name = params[:name] 

     if name 

      @configurable = Configurable.create!(name: name, value: nil) 

      if @configurable 
      format.html { redirect_to edit_admin_configurable_path(@configurable, new: true), notice: 'The setting was successfully created.' } 
     else 
      format.html { redirect_to admin_configurables_url, notice: 'Failed to create the setting.' } 
     end 
     else 
      format.html { redirect_to admin_configurables_url, notice: 'The name of the new setting was not specified.' } 
     end 

    end 

    end 

    def update 
    respond_to do |format| 
     if @configurable.update(configurable_params) 
     format.html { redirect_to [:admin, @configurable], notice: 'The setting was successfully updated.' } 
     format.json { render :show, status: :ok, location: @configurable } 
     else 
     format.html { render :edit } 
     format.json { render json: @configurable.errors, status: :unprocessable_entity } 
     end 
    end 
    end 

    def destroy 
    @configurable.destroy 
    respond_to do |format| 
     format.html { redirect_to admin_configurables_url, notice: 'The setting was successfully destroyed.' } 
     format.json { head :no_content } 
    end 
    end 

    private 
    # Use callbacks to share common setup or constraints between actions. 
    def set_configurable 
     @configurable = Configurable.find(params[:id]) 
    end 

    # Never trust parameters from the scary internet, only allow the white list through. 
    def configurable_params 
     params.require(:configurable).permit(:name, :value) 
    end 

end 

index.html.erb

<h1 class="page-header">Settings</h1> 

<div class="table-responsive"> 
<table class="table table-striped"> 
    <thead> 
    <tr> 
     <th>Name</th> 
     <th colspan="3"></th> 
    </tr> 
    </thead> 

    <tbody> 
    <% @configurables.each do |configurable| %> 
     <tr> 
     <% if configurable.try(:name) %> 
      <td><%= Configurable.defaults[configurable.name][:name]%></td> 
      <td></td> 
      <td><%= link_to 'Show', [:admin, configurable] %></td> 
      <td><%= link_to 'Edit', edit_admin_configurable_path(configurable) %></td> 
      <td><%= link_to 'Destroy', [:admin, configurable], method: :delete, data: { confirm: 'Are you sure?' } %></td> 
     <% else %> 
      <td><%= Configurable.defaults[configurable][:name] %></td>  
      <td><%= link_to 'Create', new_admin_configurable_path(name: configurable) %></td> 
      <td colspan="3"></td> 
     <% end %> 
     </tr> 
    <% end %> 
    </tbody> 
</table> 
</div> 

edit.html.erb

<h1>Editing <%= @new ? "new " : "" %>setting</h1> 

<%= render 'form', configurable: @configurable %> 

<%= link_to 'Show', [:admin, @configurable] %> | 
<%= link_to 'Back', admin_configurables_path %> 

show.html.erb

<p> 
    <strong>Name:</strong> 
    <%= Configurable.defaults[@configurable.name][:name] %> 
</p> 

<p> 
    <strong>Value:</strong> 
    <%= @configurable.value %> 
</p> 


<%= link_to 'Edit', edit_admin_configurable_path(@configurable) %> | 
<%= link_to 'Back', admin_configurables_path %> 

_form.html.erb

<%= form_for([:admin, configurable]) do |f| %> 

    <div class="field"> 
    <%= f.label "Name" %> 
    <%= Configurable.defaults[@configurable.name][:name] %> 
    </div> 

    <div class="field"> 
    <%= f.label "Value" %> 
    <%= f.text_area :value %> 
    </div> 

    <div class="actions"> 
    <%= f.submit "Submit" %> 
    </div> 
<% end %> 

causa della codificato duro instrada il mio controller non è completamente compatibile con REST, b è abbastanza vicino a L'azione new crea effettivamente un'impostazione (memorizzata nel database) (solo per sovrascrivere il valore del file yml).

Quindi, questo codice aggiunto al codice descrizione della gemma consente di utilizzare praticamente le impostazioni RoR modificabili in fase di esecuzione.

La gemma richiede di impostare alcuni valori predefiniti in un file yml in anticipo, che è possibile sovrascrivere più avanti in fase di esecuzione. Ma non è possibile creare una nuova impostazione in fase di esecuzione (not-yml-file-existent) - modificare solo un file esistente (in file yml) - che è abbastanza logico.

Oppure è possibile ripristinare (in fase di esecuzione) il valore predefinito di qualsiasi impostazione (eliminando il valore sovrascritto del database memorizzato).

Questo codice è stato verificato per funzionare con Rails 5.