Class: AlPersistFile

Inherits:
AlPersist show all
Defined in:
lib/al_persist_file.rb

Overview

Note:

データ永続化 単純ファイル版

データ本体は、Marshalによるエンコードを行っている。 識別のため、プライマリキーとして:idが自動的に付与される。 検索は使えない。並べ替えは使えない。

Instance Attribute Summary collapse

Attributes inherited from AlPersist

#persist_base, #pkeys, #result, #search_condition, #values

Class Method Summary collapse

Instance Method Summary collapse

Methods inherited from AlPersist

#[], #[]=, #get_next_offset, #get_previous_offset, #pkey

Constructor Details

#initialize(fname) ⇒ AlPersistFile

constructor

Parameters:

  • fname (String)

    ファイルネーム



44
45
46
47
# File 'lib/al_persist_file.rb', line 44

def initialize( fname )
  super( nil, :id )
  @filename = fname
end

Instance Attribute Details

#filenameString (readonly)

Returns 保存ファイル名.

Returns:

  • (String)

    保存ファイル名



37
38
39
# File 'lib/al_persist_file.rb', line 37

def filename
  @filename
end

Class Method Details

.connect(dsn = nil) ⇒ AlPersistFile

ファクトリ

Parameters:

  • dsn (String) (defaults to: nil)

    ファイル名

Returns:



31
32
33
# File 'lib/al_persist_file.rb', line 31

def self.connect( dsn = nil )
  return self.new( dsn )
end

Instance Method Details

#allArray<AlPersist>

Note:

登録データをすべて読み込む。

データ1件を1つのAlPersistオブジェクトとして配列で返す。 一件もデータがない場合は、空の配列を返す。 read()と違って自分は何も変わらず、自分の複製を生産する。

Returns:

  • (Array<AlPersist>)

    AlPersistオブジェクトの配列



242
243
244
# File 'lib/al_persist_file.rb', line 242

def all()
  search( :limit=>nil, :offset=>nil )
end

#create(values = nil) ⇒ Boolean

Note:

データをファイルへ、新規保存する。

引数の指定があれば、その値を一旦内部値(@values)にしたうえで、 内部値を新規保存する。

Parameters:

  • values (Hash) (defaults to: nil)

    プライマリキーを含む保存する値のHash

Returns:

  • (Boolean)

    成功/失敗



95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
# File 'lib/al_persist_file.rb', line 95

def create( values = nil )
  @values = values  if values

  file = open( @filename, File::RDWR|File::CREAT )
  file.flock( File::LOCK_EX )

  id = ""
  while (keys = file.gets) && (datas = file.gets)
    id = keys
  end
  id = (id.chomp.to_i + 1).to_s
  @values[:id] = id
  file.puts( id )
  file.puts( Alone::encode_uri_component( Marshal.dump( @values ) ) )
  file.close()

  return true
end

#delete(values = nil) ⇒ Boolean

Note:

キーの合致するファイル内のデータを、削除する。

valuesには、プライマリキー以外の値が含まれていてもよく、単に無視される。 引数の指定があれば、その値を一旦内部値(@values)にしたうえで削除する。

Parameters:

  • values (Hash) (defaults to: nil)

    プライマリキーを含むHash

Returns:

  • (Boolean)

    成功/失敗



160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
# File 'lib/al_persist_file.rb', line 160

def delete( values = nil )
  @values = values  if values
  return false  if ! @values[:id]
  id = "#{@values[:id]}\n"

  ret = false
  file = open( @filename, 'r' )
  file.flock( File::LOCK_SH )
  fout = Tempfile.new( "al-temp", File.dirname(@filename) )
  while (keys = file.gets) && (datas = file.gets)
    if keys == id
      ret = true
    else
      fout.write( keys )
      fout.write( datas )
    end
  end
  file.close()
  File.rename( fout.path, @filename )
  fout.close()

  return ret
end

#entry(values = nil) ⇒ Boolean

Note:

キーの合致するデータがあれば更新し、なければ新規登録する。

引数の指定があれば、その値を一旦内部値(@values)にしたうえで登録する。

Parameters:

  • values (Hash) (defaults to: nil)

    プライマリキーを含む保存する値のHash

Returns:

  • (Boolean)

    成功/失敗



193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
# File 'lib/al_persist_file.rb', line 193

def entry( values = nil )
  @values = values  if values
  if @values[:id]
    id = "#{@values[:id]}\n"
  else
    id = nil
  end

  ret = false
  new_id = ""
  file = open( @filename, 'r' )
  file.flock( File::LOCK_SH )
  fout = Tempfile.new( "al-temp", File.dirname(@filename) )
  while (keys = file.gets) && (datas = file.gets)
    new_id = keys
    fout.write( keys )
    if keys == id
      fout.puts( Alone::encode_uri_component( Marshal.dump( @values ) ) )
      ret = true
    else
      fout.write( datas )
    end
  end

  if ! ret
    id = (new_id.chomp.to_i + 1).to_s
    @values[:id] = id
    fout.puts( id )
    fout.puts( Alone::encode_uri_component( Marshal.dump( @values ) ) )
    ret = true
  end

  file.close()
  File.rename( fout.path, @filename )
  fout.close()

  return ret
end

#read(values = nil) ⇒ Boolean

Note:

キーを指定してデータを読み込み、内部(@values) に保持する。

valuesには、プライマリキー以外の値が含まれていてもよく、単に無視される。

Parameters:

  • values (Hash) (defaults to: nil)

    プライマリキーを含むHash

Returns:

  • (Boolean)

    成功/失敗



58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
# File 'lib/al_persist_file.rb', line 58

def read( values = nil )
  @values = values  if values
  return false  if ! @values[:id]
  id = "#{@values[:id]}\n"

  file = nil
  ret = false
  begin
    file = open( @filename, 'r' )
    file.flock( File::LOCK_SH )

    while (keys = file.gets) && (datas = file.gets)
      if keys == id
        @values = Marshal.load( Alone::decode_uri_component( datas ) )
        ret = true
        break
      end
    end
    file.close()

  rescue
    file.close()  if file
  end

  return ret
end

#search(param = {}) ⇒ Array<AlPersist>

Note:

登録データを選択的に読み込む。

データ1件を1つのAlPersistオブジェクトとして配列で返す。 一件もデータがない場合は、空の配列を返す。 read()と違って自分は何も変わらず、自分の複製を生産する。 RDB等と違って、選択パラメータは、limitとoffsetのみ。

Parameters:

  • param (Hash) (defaults to: {})

    検索パラメータ

Options Hash (param):

  • :limit (Integer)

    最大取得数

  • :offset (Integer)

    オフセット

Returns:

  • (Array<AlPersist>)

    Persistオブジェクトの配列



260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
# File 'lib/al_persist_file.rb', line 260

def search( param = {} )
  #
  # limitとoffsetの調整
  #
  if param[:limit]
    limit = param[:limit].to_i
    limit = 1  if limit < 1
    @search_condition[:limit] = limit
  end
  if param[:offset]
    offset = param[:offset].to_i
    offset = 0  if offset < 0
    @search_condition[:offset] = offset
  end

  total_rows = 0
  file = nil
  ret = []
  begin
    file = open( @filename, 'r' )
    file.flock( File::LOCK_SH )
    while (keys = file.gets) && (datas = file.gets)
      total_rows += 1

      if @search_condition[:limit]
        next  if ret.count >= @search_condition[:limit]
        if @search_condition[:offset]
          next  if total_rows <= @search_condition[:offset]
        end
      end

      t = self.dup
      t.values = Marshal.load( Alone::decode_uri_component( datas ) )
      ret << t
    end
    file.close()

  rescue
    file.close()  if file
  end

  @search_condition[:total_rows] = total_rows
  @search_condition[:num_rows] = ret.size
  @search_condition[:has_next_page] = (@search_condition[:offset].to_i + @search_condition[:num_rows]) < @search_condition[:total_rows]

  return ret
end

#update(values = nil) ⇒ Boolean

Note:

キーの合致するファイル内のデータを、更新する。

引数の指定があれば、その値を一旦内部値(@values)にしたうえで更新する。

Parameters:

  • values (Hash) (defaults to: nil)

    プライマリキーを含む更新する値のHash

Returns:

  • (Boolean)

    成功/失敗



123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
# File 'lib/al_persist_file.rb', line 123

def update( values = nil )
  @values = values  if values
  return false  if ! @values[:id]
  id = "#{@values[:id]}\n"

  ret = false
  file = open( @filename, 'r' )
  file.flock( File::LOCK_SH )
  fout = Tempfile.new( "al-temp", File.dirname(@filename) )
  while (keys = file.gets) && (datas = file.gets)
    if keys == id
      @values = Marshal.load( Alone::decode_uri_component( datas ) ).merge( @values )
      fout.puts( keys )
      fout.puts( Alone::encode_uri_component( Marshal.dump( @values ) ) )
      ret = true
    else
      fout.write( keys )
      fout.write( datas )
    end
  end
  file.close()
  File.rename( fout.path, @filename )
  fout.close()

  return ret
end