2009-10-08 10 views
0

Je voudrais commencer par poser cette question en disant que je suis relativement nouveau dans le développement de Ruby, mais personnellement, je me suis consacré à essayer de trouver les réponses moi-même, plutôt que de poser des questions sur des forums. Cela étant dit, ceci est mon premier "message" officiel, et j'ai fait tout mon possible pour être aussi précis et concis dans mon affichage.RoR ActiveRecord find_by_sql Question

J'ai une base de données MSSQL 2005 à laquelle je me connecte, en utilisant RoR ActiveRecord & RubyGems ADO.

Dans ma classe de base AR, j'exécute une instruction find_by_sql, qui exécute une instruction SELECT à plusieurs tables. Ma requête s'exécute comme prévu, et j'ai vérifié que les données renvoyées sont exactes.

Mon objectif:

J'ai besoin d'interroger une base de données MSSQL 2005, puis vider les données qui est retourné dans un fichier .csv.

Mon plan pour y arriver est:

  1. Utilisez des gemmes rubis & ADO pour se connecter au MSSQL DB
  2. Utilisez Ruby AR pour interroger la base de données en utilisant find par sql (en raison de la nature de la requête)
  3. Utilisez Ruby FasterCSV pour récupérer les données et les vider dans un fichier .csv.

Scénario actuel:

Je suis en mesure de se connecter avec succès à la base de données, et d'interroger les données en utilisant AR.

Problème:

Une fois la requête Recherche par SQL a été exécuté, AR renvoie les données dans un tableau de hash. Comme je l'ai déjà dit, je suis novice dans le domaine de l'AR et je travaille sur RoR depuis plusieurs mois maintenant. En tant que tel, je ne sais pas comment accéder aux attributs du tableau.

Voici ce que j'ai jusqu'à présent:

require 'rubygems' 
require 'activerecord' 
require "fastercsv" 


ActiveRecord::Base.pluralize_table_names = false 

ActiveRecord::Base.establish_connection(
    :adapter => 'sqlserver', 
    :mode => 'ODBC', 
    :dsn => 'xxxx', 
    :database => 'xxxx', 
    :username => 'blah', 
    :password => 'blahblah', 
    :host => 'server' 
) 

class Dp_display < ActiveRecord::Base 
    od30 = Dp_display.find_by_sql("SELECT dd.acct_no, dd.cur_bal, dd.od_dt, ra.email_1 
    FROM dp_display dd, rm_acct ra 
    WHERE dd.rim_no = ra.rim_no and dd.cur_bal < -10 and dd.class_code = 125 and 
    dd.od_dt = convert(varchar, getdate()-30,101) 
    ORDER BY dd.od_dt desc"); 

    #testing od30 returning values successfully 
    puts od30 

Résultat:

Quand je regarde od30, toutes les données sont renvoyées correctement. Les données se présente comme suit (liste seulement le premier élément de tableau):

od30 = Array (2 elements) 
     +[0] = {Dp_display}#<Dp_display:0x7667d74> 
      [email protected] = Hash (4 elements) 
      +'acct_no'-> 1122334455 
      +'email_1'-> [email protected] 
      +'cur_bal'-> -333.55 
      +'od_dt'-> 2009-09-08 00:00:00.000 
     +[1] = {Dp_display}#<Dp_display:0x7667d10> 

En utilisant FasterCSV, j'effectuer les opérations suivantes:

FasterCSV.open("c://file30.csv", "w") do |csv| 
     csv << od30 

Le fichier .csv est créé avec succès, et quand je l'ouvre, il ne contient:

<Dp_display:0x7667d74> 

Ce que je suis en train de faire est:

1122334455, whodat @ WHE re.com, -333.55,2009-09-08 00:00:00.Pour l'apprentissage/test, j'ai essayé d'accéder aux éléments du tableau en utilisant de nombreuses fonctions de tableau différentes, y compris model.attributes, each_index, aplatir, puis mettre le résultat. Malheureusement, je ne peux pas le comprendre.

Dans tous les cas, je viens avec le même résultat:

Encore une fois, je sais que, avec un peu de temps, je pourrais trouver une solution élaborée, mais pour l'instant, je veux essayer de garder les choses simples (comme je suis nouveau au développement, et en essayant d'apprendre de petites étapes).

Toute aide serait grandement appréciée (même si simplement me diriger dans la bonne direction serait génial!).

Merci.

Répondre

1

find_by_sql tente toujours de mapper vos résultats sur des objets, dans votre cas, les objets Dp_display. Comme il s'agit d'objets ActiveRecord, vous pouvez accéder aux colonnes renvoyées comme n'importe quel attribut, mais toutes les colonnes dérivées qui n'existent pas dans la table seront en lecture seule.

Il semble que vous essayez de vider un tableau d'objets à la place de chaque objet. Essayez quelque chose comme ceci:

FasterCSV.open("c://file30.csv", "w") do |csv| 
    csv << ['here', 'are', 'my', 'headers'] 
    od30.each |o| 
    csv << [o.acct_no, o.email_1, o.cur_bal, o.od_dt] 
    end 
end 

C'est du haut de ma tête, il y a probablement un moyen plus facile de le faire en faisant correspondre les touches d'en-tête aux attributs. Bonne chance!

Peer

+0

Merci Peer! Cela a fonctionné parfaitement. Après avoir regardé ce que vous avez recommandé, il est devenu clair pour moi que je ne considérais pas les éléments du tableau comme des objets. Au lieu de cela, je vidais le tableau lui-même, et non ses éléments. Merci beaucoup de m'avoir aidé à le comprendre! –

0

Ou seulement

FasterCSV.open("c://file30.csv", "w") do |csv| 
    od30.each |o| 
    csv << o 
    end 
end 

http://fastercsv.rubyforge.org/

+0

je peux voir la logique, mais quand je change le code pour en tenir compte, je reçois une erreur: dans chaque ': pas de bloc donné (LocalJumpError) Cette erreur fait référence à la ligne qui contient: od30. chaque | o | L'EDI RubyMine indique également que 'o' ne peut pas être résolu en une cible valide. –