2011-04-09 5 views
8

Tenga paciencia conmigo en este caso.Creación de tablas y modelos sobre la marcha (dinámicamente) en Ruby on Rails 3

En una aplicación que estoy trabajando, los usuarios pueden cargar archivos CSV en el sistema, con cualquier encabezado que les guste y cualquier columna en los datos. El CSV luego se usa para generar una tabla en la base de datos y los datos escritos en ella, luego se puede acceder a través del sistema para diversos usos, búsquedas, actualizaciones de ordenaciones, etc.

El antiguo (y ahora difunto sistema) era en PHP y manejado bien, aunque bastante desordenado con muchos sql sin formato para crear las tablas y los modelos mágicos admitidos en el marco (si la tabla existía también lo hizo el objeto sin una clase definida en un archivo de modelo)

se está escribiendo una nueva versión en RoR3, y todavía tengo que encontrar una manera de hacerlo. He logrado ordenar la creación de la tabla llamando a las herramientas de migración dentro de un modelo (no muy Rails-y lo sé, pero debe ser necesario ...), pero no encuentro la forma de vincular a la nueva tabla una vez que se ha creado. escribir en los datos, construir relaciones o cualquier otra cosa.

Lo que estoy esperando es tampoco,

a) alguien de aquí tiene una mejor forma de hacerlo que la creación de tablas y modelos sobre la marcha (una advertencia aquí, estos archivos pueden contener de 100'000 de registros y diferentes campos para que una sola opción de tabla no funcione tan bien), es decir, un mejor diseño de la base de datos para este problema.

o

b) me puede decir cómo resolver el problema del modelo.

He mirado en gema mágica modelo del Dr. Nic para RoR pero no parece trabajar en RoR3 a menos que yo estoy haciendo algo mal

Lo siento por el muro de texto, mirar hacia adelante a cualquier sugerencia

Gracias de antemano

+0

Sólo un salvaje Pensamiento: Tal vez intente crear un archivo de migración sobre la marcha, luego vuelva a cargar ese archivo y db: migrar. – Zabba

+0

@Zabba, ¿qué lograría eso exactamente? Disculpe mi falta de experiencia en RoR, pero ¿no es la migración la que crea la mesa y no el modelo? ¿O quisiste decir que sería una "mejor" forma de crear la mesa? – fullybaked

+0

Sí, me refiero a la parte sobre la creación de la tabla. Pero también puedes crear el archivo de modelo y cargarlo, I * supongo *. Sin experiencia con este tipo de cosas todavía. – Zabba

Respuesta

9

Bien, tengo una solución, creo, pero si es bueno eso es diferente.

Básicamente se crea una tabla sobre la marcha mediante la ejecución de SQL a través de Rail ActiveRecord. A continuación, utilice un modelo y cambie su nombre (Model.table_name).

Algo como esto:

// SQL Create table 
    sql = "CREATE TABLE my_table (id int(11) NOT NULL AUTO_INCREMENT, code varchar(3) NOT NULL)" 
    ActiveRecord::Base.connection.execute(sql) 

Luego, con un modelo que puede cambiar el nombre de la tabla sobre la marcha, como:

MyModel.table_name = "my_table" 
records = MyModel.all 

Ok, uno de los problemas es la lógica del modelo & asociaciones . Eres un poco limitado, pero tal vez puedas solucionarlo.

Realmente no son las mejores prácticas, supongo, pero si las necesita. ¡Creo que podría funcionar!

5

Implementé la aplicación que se utiliza para cargar un archivo csv y convertir el archivo en un modelo de registro activo. puedes consultar este repositorio.

Visita https://github.com/Athul92/Salary_Sheet_Comparison/blob/master/app/models/makemodel.rb

He aquí una pequeña idea sobre la forma en que se logró:

class Makemodel < ActiveRecord::Migration 
    def self.import(file,project_name,file_name,start_row,end_row,unique,last_column) 
     spreadsheet = open_spreadsheet(file) 
     header = spreadsheet.row(start_row.to_i) 
     i=0 
     header.count.times do 
     unless header[i].nil? 
      header[i]= header[i].gsub(/[^0-9A-Za-z]/, '').downcase 
     end 
     i+=1 
     end 
     name = "#{project_name.downcase}"+"#{file_name.downcase}" 
     create_table name.pluralize do |t| 
     header.each do |head| 
      t.string head 
     end 
     end 
     model_file = File.join("app", "models", name.singularize+".rb") 
     model_name = name.singularize.capitalize 
     File.open(model_file, "w+") do |f| 
     f << "class #{model_name} < ActiveRecord::Base\nend" 
     end 

     ((start_row.to_i+1)..end_row.to_i).each do |i| 
     row = Hash[[header, spreadsheet.row(i)].transpose] 
     #should find a logic to find the model class that is being created 
     product = Object.const_get(name.capitalize).new 
     product.attributes = row.to_hash 
     product.save! 
     end 
    end 

    def self.open_spreadsheet(file) 
     case File.extname(file.original_filename) 
     when ".csv" then Csv.new(file.path, nil, :ignore) 
     when ".xls" then Roo::Excel.new(file.path) 
     when ".xlsx" then Roo::Excelx.new(file.path) 
     else raise "Unknown file type: #{file.original_filename}" 
     end 
    end 
    end 

Hay también algunos problemas técnicos con este que es difícil añadir asociación y también Validaciones

Cuestiones relacionadas