sql >> Database teknologi >  >> RDS >> PostgreSQL

Modellering af PostgreSQL's store objekter i Rails

Hvis du bruger ActiveRecord, der følger med Rails med en af ​​dets adaptere, er den eneste formelle tilknytning af databasetype til Rails eller Ruby type, der sker, typisk defineret i NATIVE_DATABASE_TYPES konstant i adapteren, som returneres via dens native_database_types metode. For PostgreSQL i Rails 3.2.x, dvs. i ActiveRecord::ConnectionAdapters::PostgreSQLAdapter som er her . Så for den adapter er den "binære" type i Rails knyttet til typen "bytea" i PG. For nogle typer kan du tilsidesætte den databasetype, som den er knyttet til ved hjælp af en perle kaldet activerecord-native_db_types_override a> . Men vi vil gerne bruge store genstande, så...

Migreringer

Som Jim Deville bemærkede i kommentarerne, kan du angive den brugerdefinerede kolonne i tabellen som:

t.column :some_oid, 'blob_oid', :null => false

Hvis du har brug for at gøre endnu mere, der ikke er standard, kan du også bruge en execute("SQL GOES HERE;") at oprette tabellen ved hjælp af lige SQL. Og hvis du har et eksisterende ældre skema eller SQL-ændringer, der er foretaget uden for migreringerne, kan du overveje at bruge structure.sql (config.active_record.schema_format = :sql mulighed i config/application.rb og gør derefter:rake db:structure:dump ).

Store objekter Læs/Skriv/Tjek længde/Slet

Kopieret med nogle ændringer for at præcisere osv. fra:https://github.com/diogob/carrierwave-postgresql/blob/v0.1.0/lib/carrierwave/storage/postgresql_lo.rb :

Opdateret :vi kan, men behøver ikke at begynde før lo_read/lo_write/lo_lseek og gør lo_close i sikre blokering, fordi pr. PG-dokumentation "Alle store objektbeskrivelser, der forbliver åbne i slutningen af ​​en transaktion, lukkes automatisk." (tak til Diogo for den info)

    require 'pg'

    ...

    def read
      (...).transaction do
        lo = connection.lo_open(identifier)
        content = connection.lo_read(lo, file_length)
        connection.lo_close(lo)
        content
      end
    end

    def write(file)
      (...).transaction do
        lo = connection.lo_open(identifier, ::PG::INV_WRITE)
        size = connection.lo_write(lo, file.read)
        connection.lo_close(lo)
        size
      end
    end

    def delete
      connection.lo_unlink(identifier)
    end

    def file_length
      (...).transaction do
        lo = connection.lo_open(identifier)
        size = connection.lo_lseek(lo, 0, 2)
        connection.lo_close(lo)
        size
      end
    end

I stedet for connection , brug råforbindelsen fra modellen eller basen, f.eks. ActiveRecord::Base.connection.raw_connection (se dette ).

(...).transaction kalder transaktion på model eller base, f.eks. ActiveRecord::Base.transaction (se dette ).

identifier er den oid, som du enten skal sende ind/indstille eller få ved blot at lave en connection.lo_creat .

Andre eksempler/info:

Sidstnævnte og nogle svar her foreslår, at du måske vil overveje opbevaring af store filer adskilt fra DB, f.eks. så du kan bruge cloud storage. Men hvis kun gemmer stierne/ID'erne til eksterne filer, der ikke er administreres af DB, mister du ACID-konsistens (en eller flere DB-poster kan pege på en eller flere filer, der ikke er der, eller der kan eksistere en eller flere filer, der ikke har en eller flere tilknyttede poster i databasen). Et andet argument for at gemme filer på filsystemet er, at du kan streame filer, men PG large object gemmer filer på filsystemet på en måde, der administreres af postgres for både at sikre ACID-konsistens og tillade streaming (hvilket du ikke kan med en normal BLOB) /Binær type skinner). Så det kommer bare an på; nogle finder lagring i separat lager ved hjælp af sti-referencer en bedre mulighed, og nogle foretrækker ACID-konsistens via store objekter.

Den nemme måde

Brug bare CarrierWave og carrierwave-postgresql .




  1. HTTP-fejl 500.22 - Intern serverfejl (Der er fundet en ASP.NET-indstilling, som ikke gælder i integreret administreret pipeline-tilstand.)

  2. Hvordan importerer jeg rækker til Postgresql fra STDIN?

  3. Sådan bruges BETWEEN-tilstand ved at bruge hovedforespørgsel og underforespørgsler

  4. mysql vælg forskellige rækker i en kommasepareret listekolonne