EDIT: Per ottenere esattamente quello che stai cercando di cui sopra, devi usare questo per ignorare il setter di default nel file del modello:
def path=(value)
self[:path] = connection.execute("SELECT text2ltree('#{value}');")[0][0]
end
Poi il codice che avete sopra funziona.
Sono interessato a saperne di più sugli interni di ActiveRecord e le sue impenetrabili basi metaprogrammanti, così come un esercizio ho cercato di realizzare ciò che hai descritto nei tuoi commenti qui sotto. Ecco un esempio che ha funzionato per me (questo è tutto in post.rb): uscita
module DatabaseTransformation
extend ActiveSupport::Concern
module ClassMethods
def transformed_by_database(transformed_attributes = {})
transformed_attributes.each do |attr_name, transformation|
define_method("#{attr_name}=") do |argument|
transformed_value = connection.execute("SELECT #{transformation}('#{argument}');")[0][0]
write_attribute(attr_name, transformed_value)
end
end
end
end
end
class Post < ActiveRecord::Base
attr_accessible :name, :path, :version
include DatabaseTransformation
transformed_by_database :name => "length"
end
Console:
1.9.3p194 :001 > p = Post.new(:name => "foo")
(0.3ms) SELECT length('foo');
=> #<Post id: nil, name: 3, path: nil, version: nil, created_at: nil, updated_at: nil>
Nella vita reale Presumo che ci si vuole include
il modulo in ActiveRecord: : Base, in un file da qualche parte prima nel percorso di caricamento. Dovresti anche gestire correttamente il tipo di argomento che stai passando alla funzione del database. Infine, ho appreso che connection.execute
è implementato da ogni adattatore del database, quindi il modo in cui si accede al risultato potrebbe essere diverso in Postgres (questo esempio è SQLite3, dove il set di risultati viene restituito come una matrice di hash e la chiave del primo record di dati . è 0]
Questo post è stato incredibilmente utile:
http://www.fakingfantastic.com/2010/09/20/concerning-yourself-with-active-support-concern/
come era le guide per il plugin-authoring:
http://guides.rubyonrails.org/plugins.html
Inoltre, per quello che vale, penso che in Postgres lo farei ancora usando una migrazione per creare una regola di riscrittura delle query, ma ciò è stato per un'ottima esperienza di apprendimento. Spero che funzioni e posso smettere di pensare a come farlo ora.
È possibile scrivere una funzione Postgres (stored procedure) e quindi chiamare semplicemente 'SELECT myfunc ('1.2.3')'. Posso fornire un esempio se sei interessato a quel percorso. –