Check alle échte Black Friday-deals Ook zo moe van nepaanbiedingen? Wij laten alleen échte deals zien

[ruby] datamapper geeft errors over unitialized variabelen

Pagina: 1
Acties:

  • Boudewijn
  • Registratie: Februari 2004
  • Niet online

Boudewijn

omdat het kan

Topicstarter
Hoi


Ik zit op Linux met een datamapper projectje, met de volgende code te rommelen.
Er is een parser klasse die infections (zeg maar een lijstje met hacks) inlaadt. Hierbij worden infection objecten in mysql gestopt via Datamapper.

Nu is mijn applicatie een stuk verder (klasse of 10) maar om het probleem te isoleren laat ik de overige classes buiten beschouwing.

Goed, de infection class:
code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
require 'data_mapper' # requires all the gems listed above

class Infection
  include DataMapper::Resource
  property :id, Serial              
  property :add_date, DateTime
  property :infection_path, String, :default =>""
  property :tld, String           , :default =>""
  property :ip_address, String    , :default =>""
  property :system, String        , :default =>""
  property :web_server, String    , :default =>""
  property :reason, String        , :default =>""
  property :hackmode, String      , :default =>""
  property :type, String          , :default =>""
  property :redefacement, Boolean , :default =>false
  property :state, String         , :default =>""
  property :def_grade, String     , :default =>""
  property :defacement_id, String , :default =>""
 
  #TODO: implementeren van ip_locatie via whois
  property :ip_location, String   , :default =>""
  #property :date_day, String      , :default =>""
  #the hash of the line in the file from the infection
  property :infection_digest, String , :default =>""
  property :created_at, DateTime      #, :default =>nil
  
  def init( h )  
    if h && h.instance_of?( Hash ) then
      h.each do |k,v|
        obj.send("#{k}=", v)
      end        
      obj.send(":created_ad=",Time.now)   
    end         
  end

end

General.initDM()

offtopic:
(het kan zijn dat er een end'je teveel/te weinig in zit, heb wat member functies geloosd in de listing hier).

Ik instantieer die infections als volgt:
code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
    @inf=Infection.new(
      :add_date => strings[0],
      :infection_path => infection_path,
      :ip_address=>strings[3],
      :system=>strings[4],
      :web_server =>strings[5],
      :reason => strings[6],
      :hackmode => strings[7],
      :type => strings[9],
      :redefacement => Parser.yesNoToBoolean(strings[10]),
      :state => strings[11],
      :def_grade => strings[12],
      :defacement_id => strings[13],
      :infection_digest=>Digest::MD5.hexdigest(line),
      :created_at=>Time.now
    )      
    @inf.save 
   pp @inf  //deze produceert de listing hieronder!

    return @inf

De strings array komt uit een parser, en heeft in principe altijd een waarde.

Deze warning krijg ik:
code:
1
/var/lib/gems/1.9.1/gems/dm-core-1.2.0/lib/dm-core/property.rb:608: warning: instance variable @id not initialized


Als ik een object instantieer zie ik dit, via de pp uit bovenstaande listing:
code:
1
#<Infection @id=nil @add_date=#<DateTime: 2013-01-10T11:19:26+00:00 ((2456303j,40766s,0n),+0s,2299161j)> @infection_path="KNIP" @tld="" @ip_address="KNIP @system="KNIP" @web_server="" @reason="KNIP" @hackmode="KNIP" @type="KNIP" @redefacement=false @state="KNIP" @def_grade="KNIP" @defacement_id="KNIP" @ip_location="" @infection_digest="0d330c714770307b008f039e30438ad1" @created_at=#<DateTime: 2013-02-12T00:46:06+01:00 ((2456335j,85566s,0n),+3600s,2299161j)>>

De KNIPjes zijn reeele data maar die is hier niet heel relevant. Die data is dus prima ingevuld.
Wat opvalt is dat het id inderdaad op nil staat conform de warning.
Dat is raar, want als de save methode draait wordt de data *met* id prima weggeschreven in de DB, en daarna draaien we pas de pp. Dat het id door de DB wordt toegekend betekent dat je het id niet weet voor je de data in de DB zet , maar daarna zou je hem moeten weten.


Goed, een wat minder groot voorbeeld uit dezelfde code. Mijn parser slaat een recordje op als hij een bestandje verwerkt heeft zodat bestandjes niet meerdere keren worden verwerkt. De bestandjes worden nml niet verwijderd na inlezen.

inputFile klasse:
code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
require 'data_mapper' # requires all the gems listed above
require './lib/infection.rb'
require './lib/general.rb'

class InputFile
  include DataMapper::Resource
  property :id,           Serial
  property :filename,     String
  property :directory,    String
  property :created_at,   DateTime
  property :processed_at, DateTime
  property :digest,    String, :default => ""
  
end

General.initDM()
Woohoo,de fancyness zelve ;).
De initDM() in elke datamapper-related file gezet en bestaat uit:
code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
class General
  
  @@db_user='*'
  @@db_name='*'
  @@db_pass='*'
  @@db_host='*'
  @@db_type='mysql'  
  
  def General.initDM()      
    DataMapper.finalize    
    DataMapper::Logger.new($stdout, :debug) if $DEBUG  
    DataMapper.setup(:default, "#{@@db_type}://#{@@db_user}:#{@@db_pass}@#{@@db_host}/#{@@db_name}") 
    DataMapper.auto_migrate!
  end  
end

En daarna ge-required in relevante bestanden. Niet boeiend dus.


Goed, die worden hier gebruikt:
code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
  if fileIsProcessed?(filename,hashFile(filePath))
        puts "Skipping file: #{filename}" if $VERBOSE
      else        
        @file = InputFile.new(
          :filename   => filename,
          :directory  => dirname,
          :created_at => Time.now
        )
        @file.save

        #file_infections=parseFile(filePath)
        #infections.push(file_infections)
        @file.processed_at=Time.now
        @file.digest=hashFile(filePath)
        @file.save    
      end  
    end

Ik maak dus een vrij leeg File object aan, parse hem (is nu uitgecomment voor deze demo) en vul daarin in alle verplichte (niets dus!) data in. Vervolgens lees ik de file uit en zet zowel die hash als die processed_at en sla het object opnieuw op.

De warnings die ik hiervan krijg:
code:
1
2
/var/lib/gems/1.9.1/gems/dm-core-1.2.0/lib/dm-core/property.rb:608: warning: instance variable @id not initialized
/var/lib/gems/1.9.1/gems/dm-core-1.2.0/lib/dm-core/property.rb:608: warning: instance variable @processed_at not initialized

Los van dat, als ik mijn applicatie draai krijg ik een berg van dit soort bork te zien:
code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
/var/lib/gems/1.9.1/gems/dm-do-adapter-1.2.0/lib/dm-do-adapter/adapter.rb:34: warning: instance variable @field_types not initialized
/var/lib/gems/1.9.1/gems/dm-do-adapter-1.2.0/lib/dm-do-adapter/adapter.rb:34: warning: instance variable @field_types not initialized
/var/lib/gems/1.9.1/gems/dm-do-adapter-1.2.0/lib/dm-do-adapter/adapter.rb:34: warning: instance variable @field_types not initialized
/var/lib/gems/1.9.1/gems/dm-core-1.2.0/lib/dm-core/property.rb:431: warning: instance variable @precision not initialized
/var/lib/gems/1.9.1/gems/dm-core-1.2.0/lib/dm-core/property.rb:431: warning: instance variable @precision not initialized
/var/lib/gems/1.9.1/gems/dm-core-1.2.0/lib/dm-core/property.rb:431: warning: instance variable @precision not initialized
/var/lib/gems/1.9.1/gems/dm-core-1.2.0/lib/dm-core/property.rb:431: warning: instance variable @precision not initialized
/var/lib/gems/1.9.1/gems/dm-core-1.2.0/lib/dm-core/property.rb:431: warning: instance variable @precision not initialized
/var/lib/gems/1.9.1/gems/dm-core-1.2.0/lib/dm-core/property.rb:431: warning: instance variable @precision not initialized
/var/lib/gems/1.9.1/gems/dm-do-adapter-1.2.0/lib/dm-do-adapter/adapter.rb:34: warning: instance variable @field_types not initialized
/var/lib/gems/1.9.1/gems/dm-do-adapter-1.2.0/lib/dm-do-adapter/adapter.rb:34: warning: instance variable @field_types not initialized
/var/lib/gems/1.9.1/gems/dm-do-adapter-1.2.0/lib/dm-do-adapter/adapter.rb:34: warning: instance variable @field_types not initialized
/var/lib/gems/1.9.1/gems/dm-core-1.2.0/lib/dm-core/property.rb:431: warning: instance variable @precision not initialized
/var/lib/gems/1.9.1/gems/dm-core-1.2.0/lib/dm-core/property.rb:431: warning: instance variable @precision not initialized
/var/lib/gems/1.9.1/gems/dm-core-1.2.0/lib/dm-core/property.rb:431: warning: instance variable @precision not initialized
/var/lib/gems/1.9.1/gems/dm-core-1.2.0/lib/dm-core/property.rb:431: warning: instance variable @precision not initialized
/var/lib/gems/1.9.1/gems/dm-core-1.2.0/lib/dm-core/property.rb:431: warning: instance variable @precision not initialized
/var/lib/gems/1.9.1/gems/dm-core-1.2.0/lib/dm-core/property.rb:431: warning: instance variable @precision not initialized
/var/lib/gems/1.9.1/gems/dm-core-1.2.0/lib/dm-core/property.rb:431: warning: instance variable @precision not initialized
/var/lib/gems/1.9.1/gems/dm-core-1.2.0/lib/dm-core/property.rb:431: warning: instance variable @precision not initialized
/var/lib/gems/1.9.1/gems/dm-core-1.2.0/lib/dm-core/property.rb:431: warning: instance variable @precision not initialized
/var/lib/gems/1.9.1/gems/dm-core-1.2.0/lib/dm-core/property.rb:431: warning: instance variable @precision not initialized
/var/lib/gems/1.9.1/gems/dm-core-1.2.0/lib/dm-core/property.rb:431: warning: instance variable @precision not initialized
/var/lib/gems/1.9.1/gems/dm-core-1.2.0/lib/dm-core/property.rb:431: warning: instance variable @precision not initialized
/var/lib/gems/1.9.1/gems/dm-core-1.2.0/lib/dm-core/property.rb:431: warning: instance variable @precision not initialized
/var/lib/gems/1.9.1/gems/dm-core-1.2.0/lib/dm-core/property.rb:431: warning: instance variable @precision not initialized
/var/lib/gems/1.9.1/gems/dm-core-1.2.0/lib/dm-core/property.rb:431: warning: instance variable @precision not initialized
/var/lib/gems/1.9.1/gems/dm-core-1.2.0/lib/dm-core/property.rb:431: warning: instance variable @precision not initialized
/var/lib/gems/1.9.1/gems/dm-core-1.2.0/lib/dm-core/property.rb:431: warning: instance variable @precision not initialized
Parsing directory /home/boudewijn/KNIP
/var/lib/gems/1.9.1/gems/dm-core-1.2.0/lib/dm-core/property.rb:608: warning: instance variable @id not initialized
/var/lib/gems/1.9.1/gems/dm-core-1.2.0/lib/dm-core/property.rb:608: warning: instance variable @processed_at not initialized
/var/lib/gems/1.9.1/gems/dm-core-1.2.0/lib/dm-core/property.rb:608: warning: instance variable @id not initialized
/var/lib/gems/1.9.1/gems/dm-core-1.2.0/lib/dm-core/property.rb:608: warning: instance variable @processed_at not initialized
/var/lib/gems/1.9.1/gems/dm-core-1.2.0/lib/dm-core/property.rb:608: warning: instance variable @id not initialized
/var/lib/gems/1.9.1/gems/dm-core-1.2.0/lib/dm-core/property.rb:608: warning: instance variable @processed_at not initialized
/var/lib/gems/1.9.1/gems/dm-core-1.2.0/lib/dm-core/property.rb:608: warning: instance variable @id not initialized
/var/lib/gems/1.9.1/gems/dm-core-1.2.0/lib/dm-core/property.rb:608: warning: instance variable @processed_at not initialized
/var/lib/gems/1.9.1/gems/dm-core-1.2.0/lib/dm-core/property.rb:608: warning: instance variable @id not initialized
/var/lib/gems/1.9.1/gems/dm-core-1.2.0/lib/dm-core/property.rb:608: warning: instance variable @processed_at not initialized


Goed, om een lang verhaal kort te maken 3 dingen

1: waarom zeurt datamapper er uberhaupt over? Hij kan de spullen gewoon prima opslaan.
2: Waarom zeurt hij wel over die processed_at en niet over die digest?
3: Waarom zeurt Datamapper over die @precision? Waar komt dat toch vandaan? een of andere float ofzo die niet goed gezet wordt? Nou ik gebruik compleet geen floats...

Heb ik nu iets compleet verkeerd opgezet danwel geinterpreteerd? Of wat gaat hier fout? Uiteraard heb ik de documentatie van Datamapper al gelezen maar ik zie geen obvious pitfalls waar ik in ben gelopen.


Verder merk ik dat als ik de app meerdere keren draai ik nogal wat auto_migrate errors krijg; ik knal nu na elke run de DB leeg. Dat is natuurlijk niet zo handig,maar ik denk dat dat een eigen topic verdient.

[ Voor 43% gewijzigd door Boudewijn op 12-02-2013 01:08 ]


  • messi
  • Registratie: Oktober 2001
  • Laatst online: 22:14
Datamapper wordt al een tijdje niet meer onderhouden (laatste release is uit 2011, in Ruby tijd is dat eeuwen geleden ;))

Ik weet dat hij werkt aan een nieuwe versie, maar ondertussen doet de maintainer niet veel aan deze versie.
Er zijn bijna 100 open issues en er wordt niet echt gereageerd.

Is er een reden dat je datamapper met mysql wil gebruiken en geen ActiveRecord/ActiveModel?

Over je warnings: er staat al ruim een jaar een issue over open: https://github.com/datamapper/dm-core/issues/172

Onze excuses voor het ontbreken van de ondertiteling.


  • Boudewijn
  • Registratie: Februari 2004
  • Niet online

Boudewijn

omdat het kan

Topicstarter
Goed punt. Inderdaad lijkt de maintainer een beetje dood danwel een luie donder te zijn ;).


Qua ActiveRecord, je zit afaik meteen aan migrations vast. Als ik bijvoorbeeld deze code heb:
code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
require "active_record"

class Client < ActiveRecord::Base
  has_one :address
  has_many :orders
  has_and_belongs_to_many :roles
end

class Address < ActiveRecord::Base
  belongs_to :client
end

class Order < ActiveRecord::Base
  belongs_to :client, :counter_cache => true
end

class Role < ActiveRecord::Base
  has_and_belongs_to_many :clients
end


#Change this to reflect your database settings
ActiveRecord::Base.establish_connection(
  :adapter => "mysql",
  :host => "localhost",
  :username => "*",
  :password => "*",
  :database => "*")
  
 c = Client.new

Dan werkt dat niet omdat die datamodellen niet aangemaakt worden zonder dat ik dat ga regelen. Op zich niet zo'n probleem mara het is imo minder simpel

Voor een webapp (rails-related) wellicht handig maar hier minder. Verder dacht ik eerlijk gezegd dat ActiveRecord vooral voor rails was maar he blijkt dus ook voor standalone apps te werken.

Ga er wel eens serieus naar kijken adhv https://simpleprojectmana...migrations-without-rails/ .

[ Voor 4% gewijzigd door Boudewijn op 13-02-2013 00:33 ]


  • messi
  • Registratie: Oktober 2001
  • Laatst online: 22:14
Cool!

Overigens zijn alle Rails onderdelen gewoon los te gebruiken, vooral ActiveSupport en ActiveModel zijn ook in andere projecten enorm handig :)

Onze excuses voor het ontbreken van de ondertiteling.


  • Boudewijn
  • Registratie: Februari 2004
  • Niet online

Boudewijn

omdat het kan

Topicstarter
True maar wat ik vervelend vind is dat je migrations moet schrijven; datamapper werkt op basis van je klasse-definitie en ik voel me hier een beetje alsof ik en een migration moet schrijven EN daarna bijna dezelfde code nog eens mag schrijven (nou ja een deel ervan).

offtopic:
Ik ben geen Java aan het doen :P.