rightmove_blm 0.1.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 ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: 72f7f143280413db6a1bfd9b5088adf48f703f8dff4e8d0c9f83f9809a5da899
4
+ data.tar.gz: 555f455ce456dd538bab99b94945bcb0792a15422bdaca37236e4243c0f60bab
5
+ SHA512:
6
+ metadata.gz: 5ca2e04480899cd352c48c3ce59c21993dc33c91c3638a165cee55c40cb8de285d008e59ef7332477d43ea67d00798e271e5e45f9ebe9a0071aeef57dd84c747
7
+ data.tar.gz: 38736bdc6fbf9b73a4e1ef0b6c6cb8fbe43e9b9a0aeb38b25fb106632ccd4bc845e6286866d5c664fa216d2d1abfc10f0429e4de9c93d422a98d780a6dfba481
data/.document ADDED
@@ -0,0 +1,5 @@
1
+ lib/**/*.rb
2
+ bin/*
3
+ -
4
+ features/**/*.feature
5
+ LICENSE.txt
data/.gitignore ADDED
@@ -0,0 +1,43 @@
1
+ # rcov generated
2
+ coverage
3
+
4
+ # rdoc generated
5
+ rdoc
6
+
7
+ # yard generated
8
+ doc
9
+ .yardoc
10
+
11
+ # bundler
12
+ .bundle
13
+
14
+ # jeweler generated
15
+ pkg
16
+
17
+ .rspec_status
18
+ # Have editor/IDE/OS specific files you need to ignore? Consider using a global gitignore:
19
+ #
20
+ # * Create a file at ~/.gitignore
21
+ # * Include files you want ignored
22
+ # * Run: git config --global core.excludesfile ~/.gitignore
23
+ #
24
+ # After doing this, these files will be ignored in all your git projects,
25
+ # saving you from having to 'pollute' every project you touch with them
26
+ #
27
+ # Not sure what to needs to be ignored for particular editors/OSes? Here's some ideas to get you started. (Remember, remove the leading # of the line)
28
+ #
29
+ # For MacOS:
30
+ #
31
+ #.DS_Store
32
+ #
33
+ # For TextMate
34
+ #*.tmproj
35
+ #tmtags
36
+ #
37
+ # For emacs:
38
+ #*~
39
+ #\#*
40
+ #.\#*
41
+ #
42
+ # For vim:
43
+ #*.swp
data/.rspec ADDED
@@ -0,0 +1,3 @@
1
+ --format documentation
2
+ --color
3
+ --require spec_helper.rb
data/.rubocop.yml ADDED
@@ -0,0 +1,6 @@
1
+ AllCops:
2
+ NewCops: enable
3
+
4
+ Metrics/BlockLength:
5
+ Exclude:
6
+ - 'spec/blm_spec.rb'
data/.ruby-version ADDED
@@ -0,0 +1 @@
1
+ 2.5.8
data/Gemfile ADDED
@@ -0,0 +1,13 @@
1
+ # frozen_string_literal: true
2
+
3
+ source 'http://rubygems.org'
4
+
5
+ group :development, :test do
6
+ gem 'devpack', '~> 0.3.2'
7
+ gem 'rspec', '~> 3.10'
8
+ gem 'rspec-file_fixtures', '~> 0.1.3'
9
+ gem 'rspec-its', '~> 1.3'
10
+ gem 'rubocop', '~> 1.13'
11
+ gem 'rubocop-rspec', '~> 2.2'
12
+ gem 'strong_versions', '~> 0.4.5'
13
+ end
data/Gemfile.lock ADDED
@@ -0,0 +1,68 @@
1
+ GEM
2
+ remote: http://rubygems.org/
3
+ specs:
4
+ ast (2.4.2)
5
+ concurrent-ruby (1.1.8)
6
+ devpack (0.3.2)
7
+ diff-lcs (1.4.4)
8
+ i18n (1.8.10)
9
+ concurrent-ruby (~> 1.0)
10
+ paint (2.2.1)
11
+ parallel (1.20.1)
12
+ parser (3.0.1.0)
13
+ ast (~> 2.4.1)
14
+ rainbow (3.0.0)
15
+ regexp_parser (2.1.1)
16
+ rexml (3.2.5)
17
+ rspec (3.10.0)
18
+ rspec-core (~> 3.10.0)
19
+ rspec-expectations (~> 3.10.0)
20
+ rspec-mocks (~> 3.10.0)
21
+ rspec-core (3.10.1)
22
+ rspec-support (~> 3.10.0)
23
+ rspec-expectations (3.10.1)
24
+ diff-lcs (>= 1.2.0, < 2.0)
25
+ rspec-support (~> 3.10.0)
26
+ rspec-file_fixtures (0.1.3)
27
+ rspec (~> 3.0)
28
+ rspec-its (1.3.0)
29
+ rspec-core (>= 3.0.0)
30
+ rspec-expectations (>= 3.0.0)
31
+ rspec-mocks (3.10.2)
32
+ diff-lcs (>= 1.2.0, < 2.0)
33
+ rspec-support (~> 3.10.0)
34
+ rspec-support (3.10.2)
35
+ rubocop (1.13.0)
36
+ parallel (~> 1.10)
37
+ parser (>= 3.0.0.0)
38
+ rainbow (>= 2.2.2, < 4.0)
39
+ regexp_parser (>= 1.8, < 3.0)
40
+ rexml
41
+ rubocop-ast (>= 1.2.0, < 2.0)
42
+ ruby-progressbar (~> 1.7)
43
+ unicode-display_width (>= 1.4.0, < 3.0)
44
+ rubocop-ast (1.4.1)
45
+ parser (>= 2.7.1.5)
46
+ rubocop-rspec (2.2.0)
47
+ rubocop (~> 1.0)
48
+ rubocop-ast (>= 1.1.0)
49
+ ruby-progressbar (1.11.0)
50
+ strong_versions (0.4.5)
51
+ i18n (>= 0.5)
52
+ paint (~> 2.0)
53
+ unicode-display_width (2.0.0)
54
+
55
+ PLATFORMS
56
+ ruby
57
+
58
+ DEPENDENCIES
59
+ devpack (~> 0.3.2)
60
+ rspec (~> 3.10)
61
+ rspec-file_fixtures (~> 0.1.3)
62
+ rspec-its (~> 1.3)
63
+ rubocop (~> 1.13)
64
+ rubocop-rspec (~> 2.2)
65
+ strong_versions (~> 0.4.5)
66
+
67
+ BUNDLED WITH
68
+ 2.2.16
data/LICENSE.txt ADDED
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2011 Robert May, Robert Farrell
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/Makefile ADDED
@@ -0,0 +1,5 @@
1
+ .PHONY: test
2
+ test:
3
+ bundle exec rspec
4
+ bundle exec rubocop
5
+ bundle exec strong_versions
data/README.md ADDED
@@ -0,0 +1,45 @@
1
+ # Rightmove BLM
2
+
3
+ A simple parser for the _Rightmove_ `.blm` [Bulk Load Mass](https://www.rightmove.co.uk/ps/pdf/guides/RightmoveDatafeedFormatV3iOVS_1.6.pdf) file format.
4
+
5
+ Originally forked from the [BLM](https://github.com/robotmay/blm) gem by Robert May.
6
+
7
+ This library is not affiliated with or endorsed by _Rightmove Plc_ in any way.
8
+
9
+ ## Usage
10
+
11
+ ### Loading a BLM file
12
+
13
+ Load a BLM file by passing the `source` parameter to `RightmoveBLM::Document.new`:
14
+
15
+ ```ruby
16
+ blm = RightmoveBLM::Document.new(source: File.read('example_data.blm'))
17
+ ```
18
+
19
+ The returned `RightmoveBLM::Document` instance implements:
20
+
21
+ * `#header` - the header containing information about the document's structure.
22
+ * `#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).
24
+
25
+ `RightmoveBLM::Row` also implements `#to_h` which provides a _Hash_ of the row data.
26
+
27
+ #### Example
28
+
29
+ ```ruby
30
+ blm.data.each do |row|
31
+ puts row.address_1
32
+ puts row.to_h
33
+ end
34
+ ```
35
+
36
+ ### Writing BLM data
37
+
38
+ An array of _hashes_ can be converted to a `RightmoveBLM::Document` object which can then be used to create an output string by calling `#to_blm`.
39
+
40
+ The keys from the first _hash_ in the provided _array_ are used to provide the field definition. All _hashes_ **must** contain the same keys.
41
+
42
+ ```ruby
43
+ document = RightmoveBLM::Document.from_array_of_hashes([{ field1: 'foo', field2: 'bar' }, { field1: 'baz', field2: 'foobar' }])
44
+ File.write('my_data.blm', document.to_blm)
45
+ ```
data/Rakefile ADDED
@@ -0,0 +1,8 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'bundler/gem_tasks'
4
+ require 'rspec/core/rake_task'
5
+
6
+ RSpec::Core::RakeTask.new(:spec)
7
+
8
+ task default: :spec
data/VERSION ADDED
@@ -0,0 +1 @@
1
+ 0.1.5
@@ -0,0 +1,11 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'rightmove_blm/document'
4
+ require 'rightmove_blm/row'
5
+
6
+ require 'time'
7
+
8
+ # Rightmove BLM (Bulk Load Mass) data format parsing tools.
9
+ # https://www.rightmove.co.uk/ps/pdf/guides/RightmoveDatafeedFormatV3iOVS_1.6.pdf
10
+ module RightmoveBLM
11
+ end
@@ -0,0 +1,86 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RightmoveBLM
4
+ # A BLM document including its header, definition, and data content.
5
+ class Document
6
+ def self.from_array_of_hashes(array)
7
+ date = Time.now.utc.strftime('%d-%b-%Y %H:%M').upcase
8
+ header = { version: '3', eof: '^', eor: '~', "property count": array.size.to_s, "generated date": date }
9
+ new(header: header, definition: array.first.keys.map(&:to_sym), data: array)
10
+ end
11
+
12
+ def initialize(source: nil, header: nil, definition: nil, data: nil)
13
+ @source = source
14
+ @header = header
15
+ @definition = definition
16
+ @data = data&.map { |row| Row.new(row) }
17
+ end
18
+
19
+ def to_blm
20
+ [
21
+ header_string,
22
+ definition_string,
23
+ data_string
24
+ ].join("\n")
25
+ end
26
+
27
+ def header
28
+ @header ||= contents(:header).each_line.map do |line|
29
+ next nil if line.empty?
30
+
31
+ key, _, value = line.partition(' : ')
32
+ next nil if value.nil?
33
+
34
+ [key.downcase.to_sym, value.tr("'", '').strip]
35
+ end.compact.to_h
36
+ end
37
+
38
+ def definition
39
+ @definition ||= contents(:definition).split(header[:eor]).first.split(header[:eof]).map do |field|
40
+ next nil if field.empty?
41
+
42
+ field.downcase.strip
43
+ end.compact
44
+ end
45
+
46
+ def data
47
+ @data ||= contents.split(header[:eor]).map do |line|
48
+ row(line)
49
+ end
50
+ end
51
+
52
+ private
53
+
54
+ def contents(section = :data)
55
+ marker = "##{section.to_s.upcase}#"
56
+ start = @source.index(marker) + marker.size
57
+ finish = @source.index('#', start) - 1
58
+ @source[start..finish].strip
59
+ end
60
+
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)
67
+ end
68
+
69
+ def generated_date
70
+ header[:'generated date'] || Time.now.utc.strftime('%d-%b-%Y %H:%M').upcase
71
+ end
72
+
73
+ def header_string
74
+ ['#HEADER#', "VERSION : #{header[:version]}", "EOF : '|'", "EOR : '~'",
75
+ "Property Count : #{data.size}", "Generated Date : #{generated_date}", '']
76
+ end
77
+
78
+ def definition_string
79
+ ['#DEFINITION#', "#{definition.join('|')}|~", '']
80
+ end
81
+
82
+ def data_string
83
+ ['#DATA#', *data.map { |row| "#{row.attributes.values.join('|')}~" }, '#END#']
84
+ end
85
+ end
86
+ end
@@ -0,0 +1,24 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RightmoveBLM
4
+ # A row in a BLM document.
5
+ class Row
6
+ attr_accessor :attributes
7
+
8
+ def initialize(hash)
9
+ @attributes = hash
10
+ end
11
+
12
+ def to_h
13
+ @attributes
14
+ end
15
+
16
+ def method_missing(method, *_arguments)
17
+ return @attributes[method] unless @attributes[method].nil?
18
+ end
19
+
20
+ def respond_to_missing?(method, _ = false)
21
+ !@attributes[method].nil?
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,5 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RightmoveBLM
4
+ VERSION = '0.1.0'
5
+ end
@@ -0,0 +1,28 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'lib/rightmove_blm/version'
4
+
5
+ Gem::Specification.new do |spec|
6
+ spec.name = 'rightmove_blm'
7
+ spec.version = RightmoveBLM::VERSION
8
+ spec.authors = ['Robert Farrell']
9
+ spec.email = 'git@bob.frl'
10
+
11
+ spec.summary
12
+ spec.description = 'Parse and generate Rightmove BLM files'
13
+ spec.required_ruby_version = '~> 2.5'
14
+
15
+ spec.files = Dir.chdir(File.expand_path(__dir__)) do
16
+ `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
17
+ end
18
+
19
+ spec.homepage = 'http://github.com/robertmay/blm'
20
+ spec.licenses = ['MIT']
21
+ spec.require_paths = ['lib']
22
+ spec.rubygems_version = '1.3.7'
23
+ spec.summary = 'A parser for the Rightmove .blm format'
24
+ spec.test_files = [
25
+ 'spec/blm_spec.rb',
26
+ 'spec/spec_helper.rb'
27
+ ]
28
+ end
data/spec/blm_spec.rb ADDED
@@ -0,0 +1,72 @@
1
+ # frozen_string_literal: true
2
+
3
+ RSpec.describe RightmoveBLM do
4
+ context 'reading a .blm file' do
5
+ let(:data) { fixture('example_data.blm') }
6
+ let(:blm) { RightmoveBLM::Document.new(source: data.read) }
7
+
8
+ it 'should parse settings from the header' do
9
+ expect(blm.header).to be_a(Hash)
10
+ expect(blm.header[:version]).to_not be_nil
11
+ expect(blm.header[:eof]).to_not be_nil
12
+ expect(blm.header[:eor]).to_not be_nil
13
+ end
14
+
15
+ it 'should parse the column definition' do
16
+ expect(blm.definition).to be_a(Array)
17
+ expect(blm.definition.size).to be >= 1
18
+ end
19
+
20
+ it 'should parse the data into an array of hashes' do
21
+ expect(blm.data).to be_a(Array)
22
+ expect(blm.data.size).to be >= 1
23
+ expect(blm.data).to respond_to(:each, :each_with_index)
24
+ blm.data.each { |row| expect(row).to be_a(RightmoveBLM::Row) }
25
+ end
26
+
27
+ it 'should allow access to data values via methods' do
28
+ blm.data.each { |row| expect(row.address_1).to_not be_nil }
29
+ end
30
+
31
+ it 'should allow access to the @attributes hash directly' do
32
+ blm.data.each { |row| expect(row.attributes).to be_a(Hash) }
33
+ end
34
+ end
35
+
36
+ context 'creating a .blm file' do
37
+ subject(:document) { RightmoveBLM::Document.from_array_of_hashes(data) }
38
+
39
+ let(:data) do
40
+ [{ field1: 'row 1 field 1 data', field2: 'row 1 field 2 data', field3: 'row 1 field 3 data' },
41
+ { field1: 'row 2 field 1 data', field2: 'row 2 field 2 data', field3: 'row 2 field 3 data' }]
42
+ end
43
+
44
+ its(:header) { is_expected.to include({ 'property count': '2' }) }
45
+ its(:header) { is_expected.to include({ version: '3' }) }
46
+ its(:definition) { is_expected.to eql %i[field1 field2 field3] }
47
+
48
+ describe '#to_blm' do
49
+ let(:loaded_document) { RightmoveBLM::Document.new(source: subject.to_blm) }
50
+
51
+ it 'has a property count' do
52
+ expect(loaded_document.header[:'property count']).to eql '2'
53
+ end
54
+
55
+ it 'has a version' do
56
+ expect(loaded_document.header[:version]).to eql '3'
57
+ end
58
+
59
+ it 'has a "generated date" timestamp' do
60
+ expect(loaded_document.header[:'generated date']).to start_with Time.now.utc.strftime('%d-%b-%Y').upcase
61
+ end
62
+
63
+ it 'has property data' do
64
+ expect(loaded_document.data.map(&:to_h)).to eql data
65
+ end
66
+
67
+ it 'has a field definition' do
68
+ expect(loaded_document.definition).to eql %w[field1 field2 field3]
69
+ end
70
+ end
71
+ end
72
+ end
@@ -0,0 +1,16 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'bundler/setup'
4
+ require 'devpack'
5
+ require 'rightmove_blm'
6
+
7
+ require 'rspec/file_fixtures'
8
+ require 'rspec/its'
9
+
10
+ RSpec.configure do |config|
11
+ config.example_status_persistence_file_path = '.rspec_status'
12
+ config.disable_monkey_patching!
13
+ config.expect_with :rspec do |c|
14
+ c.syntax = :expect
15
+ end
16
+ end
metadata ADDED
@@ -0,0 +1,64 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: rightmove_blm
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Robert Farrell
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2021-05-02 00:00:00.000000000 Z
12
+ dependencies: []
13
+ description: Parse and generate Rightmove BLM files
14
+ email: git@bob.frl
15
+ executables: []
16
+ extensions: []
17
+ extra_rdoc_files: []
18
+ files:
19
+ - ".document"
20
+ - ".gitignore"
21
+ - ".rspec"
22
+ - ".rubocop.yml"
23
+ - ".ruby-version"
24
+ - Gemfile
25
+ - Gemfile.lock
26
+ - LICENSE.txt
27
+ - Makefile
28
+ - README.md
29
+ - Rakefile
30
+ - VERSION
31
+ - lib/rightmove_blm.rb
32
+ - lib/rightmove_blm/document.rb
33
+ - lib/rightmove_blm/row.rb
34
+ - lib/rightmove_blm/version.rb
35
+ - rightmove_blm.gemspec
36
+ - spec/blm_spec.rb
37
+ - spec/spec_helper.rb
38
+ homepage: http://github.com/robertmay/blm
39
+ licenses:
40
+ - MIT
41
+ metadata: {}
42
+ post_install_message:
43
+ rdoc_options: []
44
+ require_paths:
45
+ - lib
46
+ required_ruby_version: !ruby/object:Gem::Requirement
47
+ requirements:
48
+ - - "~>"
49
+ - !ruby/object:Gem::Version
50
+ version: '2.5'
51
+ required_rubygems_version: !ruby/object:Gem::Requirement
52
+ requirements:
53
+ - - ">="
54
+ - !ruby/object:Gem::Version
55
+ version: '0'
56
+ requirements: []
57
+ rubyforge_project:
58
+ rubygems_version: 2.7.6.2
59
+ signing_key:
60
+ specification_version: 4
61
+ summary: A parser for the Rightmove .blm format
62
+ test_files:
63
+ - spec/blm_spec.rb
64
+ - spec/spec_helper.rb