Utilizzo di HasCustomFields in un plugin

Ho un modello in un plugin. Il modello è Pfaffmananger::Server, la tabella è pfaffmanager_servers. Per motivi specifici, voglio avere campi personalizzati per questo modello (mi aspetto che ci siano casi in cui vorrò estendere i dati del server che saranno probabilmente utilizzati solo per alcune istanze e non voglio un numero enorme di campi per lo più inutilizzati nel modello).

Ecco la migrazione che crea la tabella:

class CreatePfaffmanagerServerCustomField < ActiveRecord::Migration[6.0]
  def change
    create_table :pfaffmanager_server_custom_fields do |t|
      t.integer :server_id, null: false
      t.string :name, limit: 256, null: false
      t.text :value
      t.timestamps null: false
    end
    add_index :pfaffmanager_server_custom_fields, [:server_id, :name]
  end
end

Se uso pfaffmanager_server_id invece di server_id, la migrazione fallisce perché non riesce a trovare server_id, ma quando uso pfaffmanager_server_id come nome del campo, dopo aver creato un campo personalizzato, quando provo a salvare un server ottengo:

  Pfaffmanager::ServerCustomField Load (0.4ms)  SELECT "pfaffmanager_server_custom_fields".* FROM "pfaffmanager_server_custom_fields" WHERE "pfaffmanager_server_custom_fields"."server_id" = 1
   (0.2ms)  ROLLBACK
PG::UndefinedColumn: ERROR:  column "pfaffmanager_server_id" of relation "pfaffmanager_server_custom_fields" does not exist
LINE 1: INSERT INTO pfaffmanager_server_custom_fields (pfaffmanager_...
    

Quindi, se la migrazione ha il campo pfaffmanager_server_id, la migrazione fallisce, e se il nome del campo è server_id, il salvataggio fallisce.

Sto esaminando save_custom_fields in concerns/has_custom_fields.rb, ma non riesco proprio a capire se esiste un modo per sovrascriverlo.

C’è qualcosa che posso fare oltre a rifattorizzare tutto per usare server invece di pfaffmanager_server?

Hai aggiornato anche la chiamata add_index per puntare a pfaffmanager_server_id?

2 Mi Piace

Grazie mille, David!

Sì. Potrebbe essere il mio problema. Immagino che questo sia il messaggio di errore che avrei dovuto includere. Posso far funzionare la migrazione con entrambi i campi (anche se con pfaffmanager_server_id come nome del campo, il nome dell’indice supera i 63 caratteri, quindi devo usare un nome diverso per l’indice).

Riprovo.

server_id come nome del campo

class CreatePfaffmanagerServerCustomField < ActiveRecord::Migration[6.0]
  def change
    create_table :pfaffmanager_server_custom_fields do |t|
      t.integer :server_id, null: false
      t.string :name, limit: 256, null: false
      t.text :value
      t.timestamps null: false
    end
    add_index :pfaffmanager_server_custom_fields, [:server_id, :name]
  end
end

Fallisce al salvataggio con:

 Pfaffmanager::ServerCustomField Load (3.8ms)  SELECT "pfaffmanager_server_custom_fields".* FROM "pfaffmanager_server_custom_fields" WHERE "pfaffmanager_server_custom_fields"."server_id" = 1
   (1.4ms)  ROLLBACK
PG::UndefinedColumn: ERROR:  column "pfaffmanager_server_id" of relation "pfaffmanager_server_custom_fields" does not exist
LINE 1: INSERT INTO pfaffmanager_server_custom_fields (pfaffmanager_...
                                                       ^

Quindi sta cercando pfaffmanager_server_id. Ora, proviamo con pfaffmanager_server_id.

pfaffmanager_server_id come nome del campo

Ecco la migrazione:

class CreatePfaffmanagerServerCustomField < ActiveRecord::Migration[6.0]
  def change
    create_table :pfaffmanager_server_custom_fields do |t|
      t.integer :pfaffmanager_server_id, null: false
      t.string :name, limit: 256, null: false
      t.text :value
      t.timestamps null: false
    end
    add_index :pfaffmanager_server_custom_fields,
      [:pfaffmanager_server_id, :name],
      name: 'index_pfaffmanager_server_custom_fields_on_server_id_and_name'

  end
end

Ecco cosa succede quando provo s.custom_fields (quanto sopra era riuscito a restituire nil per questo, ma non ha fallito fino a quando non ho provato a salvare un campo personalizzato). Ho chiamato register_custom_field_type qui:

 pry(main)> s.custom_fields
   (1.1ms)  SELECT "pfaffmanager_server_custom_fields"."name", "pfaffmanager_server_custom_fields"."value" FROM "pfaffmanager_server_custom_fields" WHERE "pfaffmanager_server_custom_fields"."server_id" = 1 ORDER BY id asc
ActiveRecord::StatementInvalid: PG::UndefinedColumn: ERROR:  column pfaffmanager_server_custom_fields.server_id does not exist
LINE 1: ...e" FROM "pfaffmanager_server_custom_fields" WHERE "pfaffmana...
                                                             ^

from /home/pfaffman/.rbenv/versions/2.7.1/lib/ruby/gems/2.7.0/gems/rack-mini-profiler-2.3.0/lib/patches/db/pg.rb:69:in `exec_params'
Caused by PG::UndefinedColumn: ERROR:  column pfaffmanager_server_custom_fields.server_id does not exist
LINE 1: ...e" FROM "pfaffmanager_server_custom_fields" WHERE "pfaffmana...
                                                             ^

Ora sta cercando server_id.

Quindi sembra che custom_fields lo voglia in un modo e save_custom_fields nell’altro.

Non gli importa come si chiama l’indice, vero?}

1 Mi Piace

Non credo di sì.

Penso che il secondo approccio sia probabilmente quello da seguire (usando pfaffman_server_id come nome della colonna).

Mi chiedo se sovrascrivere questo metodo possa aiutare:

Puoi verificare il valore corrente nella console così:

Server.new.custom_fields_fk

Se è server_id, suggerisco di sovrascrivere quel metodo nel tuo modello Server:

class Server < ...
  def custom_fields_fk
    "pfaffman_server_id"
  end
end
1 Mi Piace

O forse è questa parte :thinking:

1 Mi Piace

Grazie mille! Quindi Server.new.custom_fields_fk è pfaffmanager_server_id se uso pfaffmanager_serfver_id. Quindi forse dovrei usare server_id e poi sovrascrivere come hai suggerito sopra.

Sembra che refresh_custom_fields_from_db stia cercando di usare i nomi sbagliati. Non capisco esattamente cosa stia facendo _custom_fields.order....

Vedrò cosa succede se uso server_id e se poi posso sovrascrivere custom_fields_fk.

1 Mi Piace

Ehi! Ce l’hai fatta! Grazie mille. L’ho cambiato in server_id e poi ho fatto questo nel mio modello server.rb:

    def custom_fields_fk
      @custom_fields_fk ||= "server_id"
    end

Finché questo sovrascriverà il valore solo per questo modello e non romperà user_custom_field e gli altri, penso di essere pronto a ricominciare a darmi la testa contro il muro su Best way to enforce permissions--controller or constraint?. E poi potrò aggiungere le rotte per fare cose come popolare i miei nuovi campi personalizzati con… qualcosa.

Non posso ringraziarti abbastanza. Probabilmente mi hai risparmiato un’intera giornata. Ti devo una :beer:!

1 Mi Piace

Ottimo! :tada: Se riesci a pensare a un modo per renderlo più generico, sarebbe certamente ben accetto come PR.

1 Mi Piace

Se mi viene in mente qualcosa, te lo farò sapere o invierò una PR, ma devo pensare che un plugin che vuole utilizzare campi personalizzati sia piuttosto ai margini.

1 Mi Piace

OM_fk_G.

custom_fields_fk sembrava così stupido che ho pensato fosse qualcosa che intendevo eliminare e gli avevo dato un nome stupido in modo da sapere che era sicuro eliminarlo in seguito. Era più tardi, quindi l’ho eliminato. E poi le mie specifiche sono fallite.

C’era persino un commento con un link a questo argomento nel codice.

1 Mi Piace