rightmove_blm 0.1.6 → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: d86b0d52da5fad3fdac5c44ad7cc0ee515b67b6f4bdb7b2abd25ae92cd65aad3
4
- data.tar.gz: 84d91eda581f2a813bd5da72db9f2a9384262505913074077ba78fe104169bd8
3
+ metadata.gz: a4ec5f3eee9950c331f0a1dd23129b47d6917c332fae762df37346f67c3ae15b
4
+ data.tar.gz: e803eb23307b33115103e2cd99c94398d272576db5206670eff24c64f13f72af
5
5
  SHA512:
6
- metadata.gz: 653deacb786ab85ba54a77318e62f36fc570c2da370163b475191003190db55d7d77e4019924e2643c56ad00b2a04060ae142fc57eb65f5997f0aa41ee53e9dc
7
- data.tar.gz: e16d71c8a41018d8d4adbeedf69059e5b111a3dbb22a23f818ab36c7d6545529eed67d1f6cbba0d900811bf0abda5ebab79792f55852aecdce449021bc1e41d0
6
+ metadata.gz: 784c8aad75336281c6e7bc59a0a16866929f62268542d0ebf93c5bccb5a21b1e651a91b1edeca885d571ab18bdd35289afd27937316ff8a5c473d44ad612c760
7
+ data.tar.gz: 9f8dc40c0e294360d4ca3b7b713da7922b4c9a90795517f98fcd71d13b9ba22e21435aa5f984618d3d30aabb91a6ffa0fad7640d248339a2b59c1c20453e4f96
data/.rubocop.yml CHANGED
@@ -1,6 +1,9 @@
1
+ require:
2
+ - rubocop-rspec
3
+
1
4
  AllCops:
2
5
  NewCops: enable
3
6
 
4
7
  Metrics/BlockLength:
5
8
  Exclude:
6
- - 'spec/blm_spec.rb'
9
+ - 'spec/**/*_spec.rb'
data/README.md CHANGED
@@ -10,6 +10,8 @@ This library is not affiliated with or endorsed by _Rightmove Plc_ in any way.
10
10
 
11
11
  ### Loading a BLM file
12
12
 
13
+ #### RightmoveBLM::Document
14
+
13
15
  Load a BLM file by passing the `source` parameter to `RightmoveBLM::Document.new`:
14
16
 
15
17
  ```ruby
@@ -20,17 +22,32 @@ The returned `RightmoveBLM::Document` instance implements:
20
22
 
21
23
  * `#header` - the header containing information about the document's structure.
22
24
  * `#definition` - the field list contained in the document.
23
- * `#data` - an array of `RightmoveBLM::Row` objects (use dot notation to access fields, e.g. `row.foo` to access the "foo" field).
25
+ * `#rows` - an array of `RightmoveBLM::Row` objects.
26
+ * `#valid?` - `true` if no rows have errors, `false` if any rows have errors.
27
+ * `#errors` - all error messages for all invalid rows.
28
+ * `#version` - the version of the document format as a string (e.g. `'3'`).
29
+ * `#international?` - `true` if document meets the [Rightmove International](https://www.rightmove.co.uk/ps/pdf/guides/RightmoveDatafeedFormatV3iOVS_1.6.pdf) specification, `false` otherwise.
30
+
31
+ #### RightmoveBLM::Row
32
+
33
+ `RightmoveBLM::Row` implements:
24
34
 
25
- `RightmoveBLM::Row` also implements `#to_h` which provides a _Hash_ of the row data.
35
+ * `#valid?` - `true` if no errors were encountered, false otherwise.
36
+ * `#errors` - an array of error strings (empty if no errors present).
37
+ * `#to_h` (or `#attributes`) - a hash of row attributes (`nil` if errors encountered).
38
+ * `#method_missing` - allows accessing row attributes by dot notation (e.g. `row.address_1`).
26
39
 
27
40
  #### Example
28
41
 
29
42
  ```ruby
30
- blm.data.each do |row|
43
+ blm.data.select(&:valid?).each do |row|
31
44
  puts row.address_1
32
45
  puts row.to_h
33
46
  end
47
+
48
+ blm.data.reject(&:valid?).each do |row|
49
+ puts "Errors: #{row.errors.join(', ')}"
50
+ end
34
51
  ```
35
52
 
36
53
  ### Writing BLM data
@@ -13,7 +13,15 @@ module RightmoveBLM
13
13
  @source = source
14
14
  @header = header
15
15
  @definition = definition
16
- @data = data&.map { |row| Row.new(row) }
16
+ initialize_with_data(data) unless data.nil?
17
+ end
18
+
19
+ def inspect
20
+ %(<##{self.class.name} version=#{version} rows=#{rows.size} valid=#{valid?} errors=#{errors.size}>)
21
+ end
22
+
23
+ def to_s
24
+ inspect
17
25
  end
18
26
 
19
27
  def to_blm
@@ -43,27 +51,49 @@ module RightmoveBLM
43
51
  end.compact
44
52
  end
45
53
 
46
- def data
47
- @data ||= contents.split(header[:eor]).map do |line|
48
- row(line)
49
- end
54
+ def rows
55
+ data
56
+ end
57
+
58
+ def errors
59
+ @errors ||= data.reject(&:valid?).flat_map(&:errors)
60
+ end
61
+
62
+ def valid?
63
+ errors.empty?
64
+ end
65
+
66
+ def version
67
+ header[:version]
68
+ end
69
+
70
+ def international?
71
+ %w[H1 3I].include?(version)
50
72
  end
51
73
 
52
74
  private
53
75
 
76
+ def initialize_with_data(data)
77
+ @data = data.each_with_index.map { |hash, index| Row.from_attributes(hash, index: index) }
78
+ end
79
+
80
+ def data
81
+ @data ||= contents.split(header[:eor]).each_with_index.map do |line, index|
82
+ Row.new(index: index, data: line, separator: header[:eof], definition: definition)
83
+ end
84
+ end
85
+
54
86
  def contents(section = :data)
55
87
  marker = "##{section.to_s.upcase}#"
56
- start = @source.index(marker) + marker.size
57
- finish = @source.index('#', start) - 1
88
+ start = verify(:start, @source.index(marker)) + marker.size
89
+ finish = verify(:end, @source.index('#', start)) - 1
58
90
  @source[start..finish].strip
59
91
  end
60
92
 
61
- def row(line)
62
- entry = {}
63
- line.split(header[:eof]).each_with_index do |field, index|
64
- entry[definition[index].to_sym] = field.strip
65
- end
66
- Row.new(entry)
93
+ def verify(type, val)
94
+ return val unless val.nil?
95
+
96
+ raise ParserError, "Unable to parse document: could not detect #{type} marker."
67
97
  end
68
98
 
69
99
  def generated_date
@@ -3,22 +3,72 @@
3
3
  module RightmoveBLM
4
4
  # A row in a BLM document.
5
5
  class Row
6
- attr_accessor :attributes
6
+ attr_reader :index
7
7
 
8
- def initialize(hash)
9
- @attributes = hash
8
+ def self.from_attributes(attributes, index:)
9
+ new(index: index, data: nil, separator: nil, definition: attributes.keys, attributes: attributes)
10
+ end
11
+
12
+ def initialize(index:, data:, separator:, definition:, attributes: nil)
13
+ @index = index
14
+ @data = data
15
+ @separator = separator
16
+ @definition = definition
17
+ @attributes = attributes
18
+ @fields = attributes.keys unless attributes.nil?
10
19
  end
11
20
 
12
21
  def to_h
13
- @attributes
22
+ attributes
23
+ end
24
+
25
+ def valid?
26
+ return false unless field_size_valid?
27
+
28
+ true
29
+ end
30
+
31
+ def errors
32
+ return [] if valid?
33
+
34
+ errors = []
35
+ errors << field_size_mismatch_message unless field_size_valid?
36
+ errors
37
+ end
38
+
39
+ def attributes
40
+ return nil unless valid?
41
+
42
+ @attributes ||= fields.each_with_index.to_h do |field, field_index|
43
+ [definition[field_index].to_sym, field.strip]
44
+ end
45
+ end
46
+
47
+ private
48
+
49
+ attr_reader :data, :separator, :definition
50
+
51
+ def field_size_mismatch_message
52
+ "Field size mismatch in row #{index}. Expected: #{definition.size} fields, found: #{fields.size}"
53
+ end
54
+
55
+ def fields
56
+ @fields ||= data.split(separator)
57
+ end
58
+
59
+ def field_size_valid?
60
+ definition.size >= fields.size
14
61
  end
15
62
 
16
63
  def method_missing(method, *_arguments)
17
- return @attributes[method] unless @attributes[method].nil?
64
+ return super if attributes.nil?
65
+ return attributes[method] unless attributes[method].nil?
66
+
67
+ super
18
68
  end
19
69
 
20
70
  def respond_to_missing?(method, _ = false)
21
- !@attributes[method].nil?
71
+ !attributes[method].nil?
22
72
  end
23
73
  end
24
74
  end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module RightmoveBLM
4
- VERSION = '0.1.6'
4
+ VERSION = '0.2.0'
5
5
  end
data/lib/rightmove_blm.rb CHANGED
@@ -8,4 +8,6 @@ require 'time'
8
8
  # Rightmove BLM (Bulk Load Mass) data format parsing tools.
9
9
  # https://www.rightmove.co.uk/ps/pdf/guides/RightmoveDatafeedFormatV3iOVS_1.6.pdf
10
10
  module RightmoveBLM
11
+ class Error < StandardError; end
12
+ class ParserError < Error; end
11
13
  end
@@ -5,7 +5,7 @@ require_relative 'lib/rightmove_blm/version'
5
5
  Gem::Specification.new do |spec|
6
6
  spec.name = 'rightmove_blm'
7
7
  spec.version = RightmoveBLM::VERSION
8
- spec.authors = ['Robert Farrell']
8
+ spec.authors = ['Bob Farrell']
9
9
  spec.email = 'git@bob.frl'
10
10
 
11
11
  spec.summary
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: rightmove_blm
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.6
4
+ version: 0.2.0
5
5
  platform: ruby
6
6
  authors:
7
- - Robert Farrell
7
+ - Bob Farrell
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2022-12-29 00:00:00.000000000 Z
11
+ date: 2023-05-06 00:00:00.000000000 Z
12
12
  dependencies: []
13
13
  description: Parse and generate Rightmove BLM files
14
14
  email: git@bob.frl
@@ -27,7 +27,6 @@ files:
27
27
  - Makefile
28
28
  - README.md
29
29
  - Rakefile
30
- - VERSION
31
30
  - lib/rightmove_blm.rb
32
31
  - lib/rightmove_blm/document.rb
33
32
  - lib/rightmove_blm/row.rb
data/VERSION DELETED
@@ -1 +0,0 @@
1
- 0.1.6