ruby-on-rails ruby-on-rails-3 readonly activeadmin friendly-id

ruby on rails - ActiveRecord:: ReadOnlyRecord cuando se usa ActiveAdmin y Friendly_id



ruby-on-rails ruby-on-rails-3 (5)

Aquí está mi solución basada en la solución @Thomas.

ActiveAdmin.setup do |config| # ... config.before_filter :revert_friendly_id, :if => -> { !devise_controller? && resource_controller? } end # override #to_param method defined in model in order to make AA generate # routes like /admin/page/:id/edit ActiveAdmin::BaseController.class_eval do protected def resource_controller? self.class.superclass.name == "ActiveAdmin::ResourceController" end def revert_friendly_id model_name = self.class.name.match(/::(.*)Controller$/)[1].singularize # Will throw a NameError if the class does not exist Module.const_get model_name eval(model_name).class_eval do def to_param id.to_s end end rescue NameError end end

Comencé a usar ActiveAdmin recientemente en un proyecto y casi todo funciona bien, pero tengo un problema cuando lo uso en combinación con la gema friendly_id. Obtengo ActiveRecord :: ReadOnlyRecord para mis formularios [creo] debido al atributo friendly_id cuyo ID es de solo lectura:

{"utf8"=>"✓", "_method"=>"put", "authenticity_token"=>"Rc5PmUYZt3BiLvfPQr8iCPPXlbfgjoe/n+NhCwXazNs=", "space"=>{"name"=>"The Kosmonaut", "address"=>"8 Sichovykh Striltsiv 24", "email"=>"[email protected]"}, "commit"=>"Update Space", "id"=>"the-kosmonaut"} <--- culprit

Supongo que la última línea es la culpable ya que es un atributo de solo lectura, no está en mi forma sino en el PATH

http://localhost:5000/manage/spaces/the-kosmonaut/edit

¿Cómo puedo solucionar esto al intentar actualizar la ID?

El formulario de ActiveAdmin se ve así:

form do |f| f.inputs "Details" do f.input :name f.input :address f.input :email f.input :phone f.input :website end f.inputs "Content" do f.input :description f.input :blurb end f.buttons end

ACTUALIZACIÓN: ¿Esto tampoco funciona así que no es el friendly_id?

Intenté usar la sugerencia de @ watson, que debería haber funcionado, pero aún así tuve el mismo error ;-(

{"utf8"=>"✓", "_method"=>"put", "authenticity_token"=>"Rc5PmUYZt3BiLvfPQr8iCPPXlbfgjoe/n+NhCwXazNs=", "space"=>{"name"=>"The Kosmonaut 23"}, "commit"=>"Update Space", "id"=>"6933"}

http://localhost:5000/manage/spaces/6933/edit

Cuando reviso el registro en la consola con record.readonly? devuelve falso

ACTUALIZACIÓN ACTUALIZACIÓN: eliminando el alcance_para solucionar el problema.

scope_to :current_user, :unless => proc{ current_user.admin? }

El único problema es que necesito alcance_para evitar que los usuarios vean registros que no son de su propiedad. ¿Mi suposición es (como supongo que scope_to normalmente funciona con has_many) que mi asociación HABTM causa alguna rareza? Es decir, Usuarios <- HABTM -> ¿Espacios?


Este método funciona para mí. agrega este código en app / admin / model_name.rb

ActiveAdmin.register model_name do controller do defaults finder: :find_by_slug end end


Para agregar a la solución de Denny , una solución más "amigable" sería utilizar los buscadores de friendly_id.

controller do def find_resource scoped_collection.friendly.find_by_friendly_id(params[:id]) end end

Source


Puede personalizar la recuperación de recursos de acuerdo con http://activeadmin.info/docs/2-resource-customization.html#customizing_resource_retrieval . Tenga en cuenta que desea utilizar el método find_resource lugar del resource , o no podrá crear nuevos registros.

(Consulte https://github.com/gregbell/active_admin/blob/master/lib/active_admin/resource_controller/data_access.rb para obtener más detalles)

En su clase de recurso ActiveAdmin escriba:

controller do def find_resource scoped_collection.where(slug: params[:id]).first! end end

También puede sobrescribir el comportamiento de todos los recursos modificando el ResourceController en el inicializador active_admin.rb .

ActiveAdmin::ResourceController.class_eval do def find_resource if scoped_collection.is_a? FriendlyId scoped_collection.where(slug: params[:id]).first! else scoped_collection.where(id: params[:id]).first! end end end

¡Espero que ayude!

Nota al margen: al crear nuevos registros a través de la interfaz de administración, asegúrese de no incluir el campo de slug en el formulario, o FriendlyId no generará los slugs. (Creo que eso es solo para la versión 5+)


Si solo quieres IDs amigables en el extremo delantero y no te importan dentro de Active Admin, puedes revertir los efectos de la gema friendly_id para tus controladores Active Admin.

No sé exactamente cómo friendly_id reemplaza el método to_param , pero si lo está haciendo de la manera normal, volver a reemplazarlo dentro de todos los controladores de administración activa debería solucionarlo, por ejemplo:

ActiveAdmin.register Foobar do before_filter do Foobar.class_eval do def to_param id.to_s end end end end

Aún mejor, podría crear un filtro anterior en el controlador Active Admin ActiveAdmin::ResourceController para que se herede automáticamente en todos sus controladores Active Admin.

Primero agregue el filtro a la config/initializers/active_admin.rb :

ActiveAdmin.setup do |config| # ... config.before_filter :revert_friendly_id end

ActiveAdmin::ResourceController y agregue un método revert_friendly_id , por ejemplo, agregando lo siguiente al final de config/initializers/active_admin.rb :

ActiveAdmin::ResourceController.class_eval do protected def revert_friendly_id model_name = self.class.name.match(/::(.*)Controller$/)[1].singularize # Will throw a NameError if the class does not exist Module.const_get model_name eval(model_name).class_eval do def to_param id.to_s end end rescue NameError end end

Actualización: acabo de actualizar el último ejemplo de código para manejar controladores sin modelo relacionado (por ejemplo, el controlador Active Admin Dashboard)

Actualización 2: Acabo de intentar usar el truco anterior junto con la gema friendly_id y parece que funciona bien :)

Actualización 3: limpié el código para usar la forma estándar de agregar Active Admin antes de los filtros al controlador base