2017-09-17 2 views
0

Je suis un développeur débutant Ruby. Je ne peux pas comprendre comment créer un modèle ActiveRecord avec les noms des attributs différents que définis dans un schéma de DBComment définir des attributs avec des noms différents d'un schéma DB

Tenir compte le schéma suivant

create_table "sync_tasks", force: :cascade do |t| 
    t.string "name" 
    t.string "path" 
    t.string "task_type" 
    t.string "status" 
    t.boolean "async", default: false 
    t.boolean "direct_download", default: true 
    t.datetime "created_at", null: false 
    t.datetime "completed_at" 
    t.datetime "updated_at", null: false 
    end 

Et je la charge utile suivante

{ 
    "name" : "Sync /var/www/", 
    "path" : "/var/www", 
    "directDownload": true, 
    "async" : false, 
    "taskType" : "directory" 
} 

Et essayer pour créer mon modèle comme ça

class SyncTask < ApplicationRecord 
    TYPE_DB='db' 
    TYPE_FILE='file' 
    TYPE_DIRECTORY='directory' 

    def initialize(params) 
# super 
    @task_type = params[:taskType] 
    @direct_download = params[:directDownload] 
    @path = params[:path] 
    @status = params[:status] 
    @async = params[:async] 
    end 
end 

Lorsque je tente de sauver renvoie une erreur

<NoMethodError: undefined method `[]' for nil:NilClass> 

Aussi je ne suis pas en mesure d'accéder domaine comme celui

new_task = SyncTask.new(allowed_task_params) 
    new_task.task_type 

Il jette l'erreur suivante

#<NoMethodError: undefined method `task_type' for #<SyncTask not initialized>> 

Dans le cas où je décommenter le super appel donne une autre erreur

#<ActiveModel::UnknownAttributeError: unknown attribute 'taskType' for SyncTask.> 

Qu'est-ce que je fais mal? Comment puis-je utiliser différents noms d'attributs et initialiser le modèle par moi-même?

Merci

Répondre

1

Vous pouvez transform the keys, par exemple:

=> payload = { "name": "Sync /var/www/", "path": "/var/www", "directDownload": true, "taskType": "directory" } 
=> h = payload.transform_keys { |key| key.to_s.underscore } # only since v4.0.2 
=> h = Hash[payload.map { |(k, v)| [k.to_s.underscore, v] }] # before v.4.0.2 
#> {"name"=>"Sync /var/www/", "path"=>"/var/www", "direct_download"=>true, "task_type"=>"directory"} 
=> new_task = SyncTask.new(h) 

Vous ne devriez pas utiliser la méthode initialize sur les modèles AR. Si vous avez toujours besoin d'utiliser initialize, utilisez le crochet after_initialize. Parce qu'avec l'initialisation nous devons déclarer le super, il est donc préférable d'utiliser le callback.

+0

Il n'y a aucun moyen de fournir des initiateurs personnalisés? Je ne m'attendais pas un tel comportement d'un langage dynamique comme Ruby – bxfvgekd

+0

Cela fonctionne, mais je n'aime pas cette solution, fonctionnalité vraiment pauvre. – bxfvgekd

+0

Dans ce cas vous dépendez des détails d'implémentation du modèle et vous ne pouvez pas séparer les différentes couches de votre application, vraiment déçu – bxfvgekd