2010-01-24 16 views
17

Tengo una aplicación Rails relativamente simple y me gustaría almacenar varias configuraciones que los usuarios administradores pueden cambiar mientras se ejecuta la aplicación, por ejemplo, permitiendo comentarios en publicaciones o cambiando el formato de visualización de la fecha.Ruby on Rails - Configuración de aplicación de almacenamiento

Sé que puedo almacenar constantes, etc. en el archivo environment.rb, sin embargo, parece que estas solo se cargan cuando se reinicia el servidor.

¿Existe un lugar alternativo donde pueda definir esta información o sería mejor mantenerlo en la base de datos?

Cualquier consejo apreciado.

Gracias.

Respuesta

9

Puede usar la base de datos. Cree una tabla de "configuraciones" separadas que almacene los parámetros de clave/valor que necesita. La desventaja de esta solución es un golpe de rendimiento (consultar DB cada vez que necesita una configuración). Para solucionar este problema, puede leer/escribir a través de la caché como "cache_money" o crear la suya propia usando "Rails.cache"

+0

Acabo de publicar una respuesta con un enfoque que mantiene la configuración en la base de datos, las actualiza según sea necesario y no sufre problemas de rendimiento sin recurrir al almacenamiento en caché de material de BD. – silverdr

1

La mejor manera es usar una tabla de base de datos. Cada fila debe contener una palabra clave y un valor. Simples.

+0

bien, pero ¿cómo se puede gestionar los diferentes tipos de datos? Por ejemplo, algunas configuraciones serán booleanas, otras cadenas, otras enteros, etc. – Dan

+3

almacenan una cadena JSON. – Luke

+0

¿No puede simplemente usar una fila y agregar cada configuración como una columna? Recuperar una configuración sería tan simple como SELECT enable_setting FROM server_settings LIMIT 1; – Edward

4

Intente buscarlo para que sea lo que necesita.

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

+4

El repositorio squeegy tiene 4 años de antigüedad e imposible de usar con los rieles modernos. La gema ledermann requiere que se vincule a otro objeto de registro activo (hace que sea imposible usarla para la configuración global de la aplicación). Si desea una configuración global de la aplicación, https://github.com/huacnlee/rails-settings-cached es la mejor – portforwardpodcast

1

he utilizado app_config joya por un tiempo a mí mismo, pero falla con rieles 2.3.9 (y probablemente también con rieles 3.x), por lo que se encuentran this blog que menciona rails-settings y configuration, rails- la configuración almacena valores en DB, pero la configuración tiene espacios de nombres integrados. No los he probado, pero creo que cambiaré a la configuración de rieles.

noto ahora que the branch of rails-settings that Yi-Ru Lin mentions parece ser más featureful que el otro rails-settings

Jarl

15

Se puede usar la gema rails-settings-cached que es un tenedor de la gema-settings carriles (vinculado por Yi-Ru Lin en otra respuesta).

Una vez configurado, podrás hacer cosas como:

Setting.foo = 123 
Setting.foo # returns 123 

También puede administrar configuración de modelos, ex:

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

Para carriles 4, si está utilizando postgresql, puede usar HStore, que es como un atributo serializable, pero usted hace consultas SQL con él.

Para los rieles 3, puede usar activerecord-postgres-hstore gema.

0

Intenté https://github.com/huacnlee/rails-settings-cached, pero no funciona según lo descrito. Obviamente, el autor olvidó mencionar algunos ajustes adicionales en la descripción del uso de gemas. No pude escribir un controlador para la manipulación de configuraciones.

En su lugar, tuve éxito en utilizar https://github.com/paulca/configurable_engine - a pesar de algunos problemas menores, esta gema es mucho más razonable que rails-settings-cached.

La gema configurable_engine tiene un inconveniente: tiene las rutas codificadas que son oscuras y no convenientes. El autor de la gema promised to correct it, pero dijo que actualmente no tenía tiempo para eso.

Así que este problema se solucionó fácilmente simplemente creando mis propias rutas. Aquí está mi código (añadido para hacer esta joya realmente el trabajo):

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 %> 

Debido a la modificable rutas mi controlador no es completamente REST-obediente, b ut es bastante cercano a. Mi acción new realmente crea una configuración (almacenada en la base de datos) (solo para anular su valor de archivo yml).

Por lo tanto, este código agregado al código de descripción de gemas le permite utilizar prácticamente las configuraciones de RoR cambiables en tiempo de ejecución.

La gema requiere que establezca previamente algunos valores predeterminados en un archivo yml, que puede anular más adelante en el tiempo de ejecución. Pero no puede crear una nueva configuración en tiempo de ejecución (no-yml-file-existente); solo modifique una existente (en archivo yml), lo cual es bastante lógico.

O puede restaurar (en el tiempo de ejecución) el valor predeterminado de cualquier configuración (borrando su valor sobrescrito de la base de datos).

Este código se comprobó que trabajar con rieles 5.