lazy_store 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 2abe70f24b49ea6365679ea579a963e405893abc
4
+ data.tar.gz: 54d61cad2e0a7b705448c9a7bf541806c16d5667
5
+ SHA512:
6
+ metadata.gz: 18da4714b82b14060c1f3b928550f464e6c1fdcefb8bf418f9f987559394801a694b364362d6ad8f79a6604f7bf315dfcb75693196aa738dc4b5a41d0d522247
7
+ data.tar.gz: df963507e91572dc0159ba9bb2470146b1ba3103c38ef804c3f1d266c15ea7af90c9cde2a7ed7fecf39f8664b1f23a063c62ccb20fb5a828cc170bc359ef5192
data/.document ADDED
@@ -0,0 +1,5 @@
1
+ lib/**/*.rb
2
+ bin/*
3
+ -
4
+ features/**/*.feature
5
+ LICENSE.txt
data/.rspec ADDED
@@ -0,0 +1 @@
1
+ --color
data/Gemfile ADDED
@@ -0,0 +1,19 @@
1
+ source 'http://rubygems.org'
2
+ # Add dependencies required to use your gem here.
3
+ # Example:
4
+ # gem "activesupport", ">= 2.3.5"
5
+ gem 'totally_lazy'
6
+ gem 'lock_method'
7
+ gem 'encrypted_strings'
8
+ gem 'mysql2'
9
+ # gem 'tiny_tds'
10
+
11
+ # Add dependencies to develop your gem here.
12
+ # Include everything needed to run rake, tests, features, etc.
13
+ group :development do
14
+ gem 'rspec', '~> 3.0.0.rc1'
15
+ gem 'rdoc', '~> 3.12'
16
+ gem 'bundler', '~> 1.0'
17
+ gem 'jeweler', '~> 2.0.1'
18
+ gem 'simplecov', '>= 0'
19
+ end
data/Gemfile.lock ADDED
@@ -0,0 +1,98 @@
1
+ GEM
2
+ remote: http://rubygems.org/
3
+ specs:
4
+ activesupport (4.1.6)
5
+ i18n (~> 0.6, >= 0.6.9)
6
+ json (~> 1.7, >= 1.7.7)
7
+ minitest (~> 5.1)
8
+ thread_safe (~> 0.1)
9
+ tzinfo (~> 1.1)
10
+ addressable (2.3.6)
11
+ builder (3.2.2)
12
+ cache (0.4.0)
13
+ descendants_tracker (0.0.4)
14
+ thread_safe (~> 0.3, >= 0.3.1)
15
+ diff-lcs (1.2.5)
16
+ docile (1.1.5)
17
+ encrypted_strings (0.3.3)
18
+ faraday (0.9.0)
19
+ multipart-post (>= 1.2, < 3)
20
+ git (1.2.8)
21
+ github_api (0.12.1)
22
+ addressable (~> 2.3)
23
+ descendants_tracker (~> 0.0.4)
24
+ faraday (~> 0.8, < 0.10)
25
+ hashie (>= 3.2)
26
+ multi_json (>= 1.7.5, < 2.0)
27
+ nokogiri (~> 1.6.3)
28
+ oauth2
29
+ hashie (3.3.1)
30
+ highline (1.6.21)
31
+ i18n (0.6.11)
32
+ jeweler (2.0.1)
33
+ builder
34
+ bundler (>= 1.0)
35
+ git (>= 1.2.5)
36
+ github_api
37
+ highline (>= 1.6.15)
38
+ nokogiri (>= 1.5.10)
39
+ rake
40
+ rdoc
41
+ json (1.8.1)
42
+ jwt (1.0.0)
43
+ lock_method (0.5.5)
44
+ activesupport
45
+ cache (>= 0.2.1)
46
+ mini_portile (0.6.0)
47
+ minitest (5.4.1)
48
+ multi_json (1.10.1)
49
+ multi_xml (0.5.5)
50
+ multipart-post (2.0.0)
51
+ mysql2 (0.3.16)
52
+ nokogiri (1.6.3.1)
53
+ mini_portile (= 0.6.0)
54
+ oauth2 (1.0.0)
55
+ faraday (>= 0.8, < 0.10)
56
+ jwt (~> 1.0)
57
+ multi_json (~> 1.3)
58
+ multi_xml (~> 0.5)
59
+ rack (~> 1.2)
60
+ rack (1.5.2)
61
+ rake (10.3.2)
62
+ rdoc (3.12.2)
63
+ json (~> 1.4)
64
+ rspec (3.0.0)
65
+ rspec-core (~> 3.0.0)
66
+ rspec-expectations (~> 3.0.0)
67
+ rspec-mocks (~> 3.0.0)
68
+ rspec-core (3.0.4)
69
+ rspec-support (~> 3.0.0)
70
+ rspec-expectations (3.0.4)
71
+ diff-lcs (>= 1.2.0, < 2.0)
72
+ rspec-support (~> 3.0.0)
73
+ rspec-mocks (3.0.4)
74
+ rspec-support (~> 3.0.0)
75
+ rspec-support (3.0.4)
76
+ simplecov (0.9.1)
77
+ docile (~> 1.1.0)
78
+ multi_json (~> 1.0)
79
+ simplecov-html (~> 0.8.0)
80
+ simplecov-html (0.8.0)
81
+ thread_safe (0.3.4)
82
+ totally_lazy (0.0.5)
83
+ tzinfo (1.2.2)
84
+ thread_safe (~> 0.1)
85
+
86
+ PLATFORMS
87
+ ruby
88
+
89
+ DEPENDENCIES
90
+ bundler (~> 1.0)
91
+ encrypted_strings
92
+ jeweler (~> 2.0.1)
93
+ lock_method
94
+ mysql2
95
+ rdoc (~> 3.12)
96
+ rspec (~> 3.0.0.rc1)
97
+ simplecov
98
+ totally_lazy
data/LICENSE.txt ADDED
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2014 Kingsley Hendrickse
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/README.md ADDED
@@ -0,0 +1,71 @@
1
+ # Lazy Records for Ruby
2
+
3
+ This is a port of the java functional library [Lazy Records](https://code.google.com/p/totallylazy/) to the ruby language. It still needs a lot of tidy and re-working in several places. But it works and is a first cut.
4
+
5
+
6
+ ### Summary
7
+
8
+ * Tries to be as lazy as possible
9
+ * Supports method chaining
10
+ * Is primarily based on totally lazy
11
+
12
+ ### Install
13
+
14
+ This gem requires ruby 2.x.x
15
+
16
+ In your bundler Gemfile
17
+
18
+ ```ruby
19
+ gem lazy_records, '~>0.0.1'
20
+ ```
21
+
22
+ Or with rubygems
23
+
24
+ ```
25
+ gem install lazy_records
26
+ ```
27
+
28
+ ### Examples
29
+
30
+ The following are some simple examples of the currently implemented functionality.
31
+
32
+ With MemoryRecords (Run in memory only)
33
+
34
+ ```ruby
35
+ require 'lazy_records'
36
+
37
+ name = keyword(:name)
38
+ age = keyword(:age)
39
+ people = definition(:people, name, age)
40
+
41
+ records = MemoryRecords.new
42
+
43
+ records.add(people, sequence(
44
+ record(name, 'kostas', age, 25),
45
+ record(name, 'kings', age, 34)))
46
+
47
+ records.get(people).count # returns 2
48
+ records.get(people).head.name) # returns 'kostas'
49
+
50
+ ```
51
+
52
+ with SqlRecords (Run against either mysql or mssql currently)
53
+
54
+ ```ruby
55
+ require 'lazy_records'
56
+ require 'adpaters/mysql'
57
+
58
+ name = keyword(:name)
59
+ age = keyword(:age)
60
+ people = definition(:people, name, age)
61
+
62
+ records = SqlRecords.new(Mysql.new(username:'user1',password:'pass1',database:'mydb'))
63
+
64
+ records.add(people, sequence(
65
+ record(name, 'kostas', age, 25),
66
+ record(name, 'kings', age, 34)))
67
+
68
+ records.get(people).count # returns 2
69
+ records.get(people).head.name) # returns 'kostas'
70
+
71
+ ```
data/Rakefile ADDED
@@ -0,0 +1,50 @@
1
+ # encoding: utf-8
2
+
3
+ require 'rubygems'
4
+ require 'bundler'
5
+ begin
6
+ Bundler.setup(:default, :development)
7
+ rescue Bundler::BundlerError => e
8
+ $stderr.puts e.message
9
+ $stderr.puts "Run `bundle install` to install missing gems"
10
+ exit e.status_code
11
+ end
12
+ require 'rake'
13
+
14
+ require 'jeweler'
15
+ Jeweler::Tasks.new do |gem|
16
+ # gem is a Gem::Specification... see http://guides.rubygems.org/specification-reference/ for more options
17
+ gem.name = "lazy_store"
18
+ gem.homepage = "http://github.com/kingsleyh/lazy_records"
19
+ gem.license = "MIT"
20
+ gem.summary = %Q{port of lazy records to ruby}
21
+ gem.description = %Q{port of lazy records to ruby}
22
+ gem.email = "kingsley.hendrickse@gmail.com"
23
+ gem.authors = ["Kingsley Hendrickse"]
24
+ # dependencies defined in Gemfile
25
+ end
26
+ Jeweler::RubygemsDotOrgTasks.new
27
+
28
+ require 'rspec/core'
29
+ require 'rspec/core/rake_task'
30
+ RSpec::Core::RakeTask.new(:spec) do |spec|
31
+ spec.pattern = FileList['spec/**/*_spec.rb']
32
+ end
33
+
34
+ desc "Code coverage detail"
35
+ task :simplecov do
36
+ ENV['COVERAGE'] = "true"
37
+ Rake::Task['spec'].execute
38
+ end
39
+
40
+ task :default => :spec
41
+
42
+ require 'rdoc/task'
43
+ Rake::RDocTask.new do |rdoc|
44
+ version = File.exist?('VERSION') ? File.read('VERSION') : ""
45
+
46
+ rdoc.rdoc_dir = 'rdoc'
47
+ rdoc.title = "lazy_store #{version}"
48
+ rdoc.rdoc_files.include('README*')
49
+ rdoc.rdoc_files.include('lib/**/*.rb')
50
+ end
data/VERSION ADDED
@@ -0,0 +1 @@
1
+ 0.0.1
@@ -0,0 +1,18 @@
1
+ require 'tiny_tds'
2
+
3
+ class Mssql
4
+
5
+ def initialize(details)
6
+ @client = TinyTds::Client.new(details)
7
+ end
8
+
9
+ def query(sql)
10
+ @client.execute(sql)
11
+ end
12
+
13
+ def fields(table)
14
+ query('select * from ' + table.to_s).fields
15
+ end
16
+
17
+ end
18
+
@@ -0,0 +1,21 @@
1
+ require 'mysql2'
2
+
3
+ class Mysql
4
+
5
+ def initialize(details,show_sql=false)
6
+ @client = Mysql2::Client.new(details)
7
+ @show_sql = show_sql
8
+ end
9
+
10
+ def query(sql)
11
+ puts sql if @show_sql
12
+ @client.query(sql)
13
+ end
14
+
15
+ def fields(table)
16
+ query('select * from ' + table.to_s).fields
17
+ end
18
+
19
+ end
20
+
21
+
data/lib/definition.rb ADDED
@@ -0,0 +1,40 @@
1
+ module LazyRecords
2
+
3
+ def definition(name, *columns)
4
+ Definition.new(name, columns)
5
+ end
6
+
7
+ class Definition
8
+
9
+ attr_reader :name, :columns
10
+
11
+ def initialize(name, *columns)
12
+ @name = name
13
+ @columns = columns
14
+ @client = none
15
+ @add_exclusions = none
16
+ @show_sql = false
17
+ end
18
+
19
+ def columns_as_list
20
+ columns.first.map(&:name)
21
+ end
22
+
23
+ def add_exclusions=(*values)
24
+ @add_exclusions = sequence(values.flatten)
25
+ end
26
+
27
+ def add_exclusions
28
+ option(@add_exclusions)
29
+ end
30
+
31
+ def suggest_keywords(connection)
32
+ fields = connection.fields(@name)
33
+ keywords = fields.map { |field| "#{field} = keyword(:#{field})" }.join("\n")
34
+ puts keywords
35
+ puts "#{@name} = definition(:#{@name}, #{fields.join(', ')})"
36
+ end
37
+
38
+ end
39
+
40
+ end
data/lib/keyword.rb ADDED
@@ -0,0 +1,17 @@
1
+ module LazyRecords
2
+
3
+ def keyword(name, encrypt=false)
4
+ Keyword.new(name, encrypt)
5
+ end
6
+
7
+ class Keyword
8
+
9
+ attr_reader :name, :encrypt
10
+
11
+ def initialize(name, encrypt=false)
12
+ @name = name
13
+ @encrypt = encrypt
14
+ end
15
+ end
16
+
17
+ end
@@ -0,0 +1,12 @@
1
+ require 'lock_method'
2
+ require 'totally_lazy'
3
+ require 'encrypted_strings'
4
+ require 'ostruct'
5
+ require_relative 'record'
6
+ require_relative 'keyword'
7
+ require_relative 'definition'
8
+ require_relative 'memory_records'
9
+ require_relative 'predicate_to_sql'
10
+ require_relative 'sql_records'
11
+ require_relative 'predicates'
12
+ include LazyRecords
@@ -0,0 +1,93 @@
1
+ module LazyRecords
2
+
3
+ class MemoryRecords
4
+
5
+ def initialize
6
+ @store = empty
7
+ end
8
+
9
+ def add(definition, records)
10
+ raise(UnsupportedTypeException.new, "records must be of type: #{Sequence}<#{Record}> but was: #{records.class}") unless records.is_a?(Sequences::Sequence)
11
+ table = @store.filter(where(key: equals(definition.name)))
12
+ if table.empty?
13
+ @store = @store.join(sequence(pair(definition.name, records)))
14
+ else
15
+ remaining_tables = @store.reject(where(key: equals(definition.name)))
16
+ updated_table = table.update(value: table.head.value.join(records))
17
+ @store = remaining_tables.join(updated_table)
18
+ end
19
+ end
20
+
21
+ def get(definition, selection=nil)
22
+ if selection
23
+ @store.filter(where(key: equals(definition.name))).send(:filter, selection).map { |row| row.value }.head
24
+ else
25
+ @store.filter(where(key: equals(definition.name))).map { |row| row.value }.head
26
+ end
27
+ end
28
+
29
+ def set(definition, selection, *updates)
30
+ table = @store.filter(where(key: equals(definition.name)))
31
+ updated = get(definition).send(:filter, selection).update(Maps.merge(sequence(updates).in_pairs.map { |e| {e.key.name.to_sym => e.value} }))
32
+ remaining = get(definition).send(:reject, selection)
33
+ records = remaining.join(updated)
34
+ remaining_tables = @store.reject(where(key: equals(definition.name)))
35
+ updated_table = table.update(value: records)
36
+ @store = remaining_tables.join(updated_table)
37
+ end
38
+
39
+ def remove_definition(definition)
40
+ name = definition.is_a?(Symbol) ? definition : definition.name
41
+ @store = @store.reject(where(key: equals(name)))
42
+ end
43
+
44
+ def remove(definition, selection)
45
+ table = @store.filter(where(key: equals(definition.name)))
46
+ records = get(definition).send(:reject, selection)
47
+ remaining_tables = @store.reject(where(key: equals(definition.name)))
48
+ updated_table = table.update(value: records)
49
+ @store = remaining_tables.join(updated_table)
50
+ end
51
+
52
+ def inner_join(def1, def2, keyword_map)
53
+ get(def1).flat_map { |d1| get(def2).filter { |d2| process_keywords(keyword_map, d1, d2) }.map { |n| Record.new(process_columns(def1, def2, d1.get_hash, n.get_hash)) } }
54
+ end
55
+
56
+ def process_keywords(keyword_map, d1, d2)
57
+ eval(keyword_map.map { |k, v| "d1.send(:#{k.name}) == d2.send(:#{v.name})" }.to_a.join(' and '))
58
+ end
59
+
60
+ def process_columns(d1, d2, h1, h2)
61
+ one = h1.map { |k, v| {"#{d1.name}_#{k}" => v} }.reduce({}) { |a, b| a.merge(b) }
62
+ two = h2.map { |k, v| {"#{d2.name}_#{k}" => v} }.reduce({}) { |a, b| a.merge(b) }
63
+ one.merge(two)
64
+ end
65
+
66
+
67
+ def as_lock
68
+ 'lazy_store'
69
+ end
70
+
71
+ def read_data(location)
72
+ if File.exists?(location)
73
+ f = File.open(location)
74
+ @store = deserialize(Marshal.load(f))
75
+ end
76
+ end
77
+
78
+ lock_method :read_data
79
+
80
+ def write_data(location)
81
+ f = File.new(location, 'w')
82
+ Marshal.dump(@store.serialize, f)
83
+ f.close
84
+ end
85
+
86
+ lock_method :write_data
87
+
88
+ end
89
+
90
+ end
91
+
92
+
93
+
@@ -0,0 +1,29 @@
1
+ module LazyRecords
2
+
3
+ class PredicateToSql
4
+ def initialize
5
+ @pred_map = {
6
+ equals: '=',
7
+ equal_to: '=',
8
+ greater_than: '>',
9
+ less_than: '<',
10
+ like: 'like'
11
+ }
12
+ end
13
+
14
+ def custom(pred_map)
15
+ @pred_map = @pred_map.merge(pred_map)
16
+ end
17
+
18
+ def convert(predicate)
19
+ predicate.predicates.map do |pred|
20
+ operation = option(@pred_map[pred.value.name]).get_or_throw(NoSuchElementException, "Operation not supported: #{pred.value.name}")
21
+ column = pred.key.to_s
22
+ value = pred.value.value
23
+ "#{column} #{operation} '#{value}'"
24
+ end.to_a.join(' and ')
25
+ end
26
+
27
+ end
28
+
29
+ end
data/lib/predicates.rb ADDED
@@ -0,0 +1,4 @@
1
+ def like(value)
2
+ value_predicate(:like, '=', value)
3
+ end
4
+
data/lib/record.rb ADDED
@@ -0,0 +1,23 @@
1
+ module LazyRecords
2
+
3
+ def record(*data)
4
+ Record.new(sequence(data).in_pairs.map { |r| {r.key.name => r.value} }.reduce({}) { |a, b| a.merge(b) })
5
+ end
6
+
7
+ class Record < OpenStruct
8
+
9
+ def get_hash
10
+ self.instance_variable_get("@table")
11
+ end
12
+
13
+ def get_keywords
14
+ get_hash.keys
15
+ end
16
+
17
+ def get_values
18
+ get_hash.values
19
+ end
20
+
21
+ end
22
+
23
+ end
@@ -0,0 +1,60 @@
1
+ module LazyRecords
2
+
3
+ class SqlRecords
4
+
5
+ def initialize(connection)
6
+ @c = connection
7
+ @predicate_to_sql = PredicateToSql.new
8
+ end
9
+
10
+ def add(definition, records)
11
+ raise(UnsupportedTypeException.new, "records must be of type: #{Sequence}<#{Record}> but was: #{records.class}") unless records.is_a?(Sequences::Sequence)
12
+ excludes = definition.add_exclusions.get_or_else(empty).map(&:name)
13
+ records.each do |r|
14
+ data = r.get_hash.reject { |k, v| excludes.contains?(k) }
15
+ sql = 'insert into ' + definition.name.to_s + " (#{data.keys.join(',')}) values (#{data.values.map(&:inspect).join(',')})"
16
+ @c.query(sql)
17
+ end
18
+ end
19
+
20
+ def get(definition, selection=nil)
21
+ if selection
22
+ sql = 'select * from ' + definition.name.to_s + ' where ' + @predicate_to_sql.convert(selection)
23
+ sequence(@c.query(sql).map { |r| Record.new(r) })
24
+ else
25
+ sql = 'select * from ' + definition.name.to_s
26
+ sequence(@c.query(sql).map { |r| Record.new(r) })
27
+ end
28
+ end
29
+
30
+ def set(definition, selection, *updates)
31
+ pending_fields = Maps.merge(sequence(updates).in_pairs.map { |e| {e.key.name.to_sym => e.value} })
32
+ sql = 'update ' + definition.name.to_s + ' set ' + pending_fields.map { |k, v| "#{k}='#{v}'" }.join(',') + ' where ' + @predicate_to_sql.convert(selection)
33
+ sequence(@c.query(sql))
34
+ end
35
+
36
+ def remove(definition, selection)
37
+ sql = 'delete from ' + definition.name.to_s + ' where ' + @predicate_to_sql.convert(selection)
38
+ sequence(@c.query(sql))
39
+ end
40
+
41
+ def inner_join(def1, def2, keyword_map)
42
+ sql = 'select ' + process_columns(def1, def2) + ' from ' + def1.name.to_s + ' inner join ' + def2.name.to_s + ' on ' + process_keywords(keyword_map, def1, def2)
43
+ sequence(@c.query(sql).map { |r| Record.new(r) })
44
+ end
45
+
46
+ private
47
+
48
+ def process_keywords(keyword_map, d1, d2)
49
+ keyword_map.map { |k, v| d1.name.to_s + ".#{k.name} = " + d2.name.to_s + ".#{v.name}" }.to_a.join(' and ')
50
+ end
51
+
52
+ def process_columns(d1, d2)
53
+ one = d1.columns_as_list.map{|k| " #{d1.name}.#{k} as '#{d1.name}_#{k}'"}.join(',')
54
+ two = d2.columns_as_list.map{|k| " #{d2.name}.#{k} as '#{d2.name}_#{k}'"}.join(',')
55
+ one + two
56
+ end
57
+
58
+ end
59
+
60
+ end
@@ -0,0 +1,160 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
2
+
3
+ describe MemoryRecords do
4
+
5
+ before(:each) do
6
+ @records = MemoryRecords.new
7
+ @records.remove_definition(:people)
8
+ end
9
+
10
+ it 'should add records' do
11
+ name = keyword(:name)
12
+ age = keyword(:age)
13
+ people = definition(:people, name, age)
14
+
15
+ @records.add(people, sequence(
16
+ record(name, 'kostas', age, 25),
17
+ record(name, 'kings', age, 34)))
18
+
19
+
20
+ expect(@records.get(people).count).to eq(2)
21
+ expect(@records.get(people).head.name).to eq('kostas')
22
+ end
23
+
24
+ it 'should update records with set' do
25
+ name = keyword(:name)
26
+ age = keyword(:age)
27
+ people = definition(:people, name, age)
28
+
29
+ @records.add(people, sequence(
30
+ record(name, 'kostas', age, 25)))
31
+
32
+ @records.add(people, sequence(
33
+ record(name, 'kings', age, 34)))
34
+
35
+ @records.set(people, where(name: equals('kostas')), age, 35)
36
+ expect(@records.get(people).filter(where(name: equals('kostas'))).head.age).to eq(35)
37
+ end
38
+
39
+ it 'should filter records' do
40
+ name = keyword(:name)
41
+ age = keyword(:age)
42
+ people = definition(:people, name, age)
43
+
44
+ @records.add(people, sequence(
45
+ record(name, 'kostas', age, 25),
46
+ record(name, 'andrew', age, 26),
47
+ record(name, 'david', age, 27),
48
+ record(name, 'mike', age, 28),
49
+ record(name, 'kings', age, 29)))
50
+
51
+
52
+ expect(@records.get(people).filter(where name: matches(/k/)).count).to eq(3)
53
+ end
54
+
55
+ it 'should remove records' do
56
+ name = keyword(:name)
57
+ age = keyword(:age)
58
+ people = definition(:people, name, age)
59
+
60
+ @records.add(people, sequence(
61
+ record(name, 'andrew', age, 25),
62
+ record(name, 'kostas', age, 26),
63
+ ))
64
+
65
+ @records.remove(people, where(name: equals('andrew')))
66
+ expect(@records.get(people).head).to eq(record(name, 'kostas', age, 26))
67
+
68
+ end
69
+
70
+ it 'should write to file' do
71
+ name = keyword(:name)
72
+ age = keyword(:age)
73
+ people = definition(:people, name, age)
74
+
75
+ @records.add(people, sequence(
76
+ record(name, 'kostas', age, 25),
77
+ record(name, 'kings', age, 34)))
78
+
79
+ @records.write_data(File.dirname(__FILE__) + '/test_data/people.db')
80
+ end
81
+
82
+ it 'should read from file' do
83
+ name = keyword(:name)
84
+ age = keyword(:age)
85
+ people = definition(:people, name, age)
86
+ @records.read_data(File.dirname(__FILE__) + '/test_data/people.db')
87
+ expect(@records.get(people).count).to eq(2)
88
+ end
89
+
90
+ it 'should inner join' do
91
+ data_for_joins
92
+
93
+ id = keyword(:id)
94
+ name = keyword(:name)
95
+ age = keyword(:age)
96
+ order_id = keyword(:order_id)
97
+ date = keyword(:date)
98
+ amount = keyword(:amount)
99
+
100
+ people = definition(:people, id, name, age)
101
+ orders = definition(:orders, order_id, id, date, amount)
102
+
103
+ people_id = keyword(:people_id)
104
+ people_name = keyword(:people_name)
105
+ people_age = keyword(:people_age)
106
+ people_address = keyword(:people_address)
107
+ people_salary = keyword(:people_salary)
108
+ order_id = keyword(:orders_id)
109
+ order_order_id = keyword(:orders_order_id)
110
+ order_date = keyword(:orders_date)
111
+ order_amount = keyword(:orders_amount)
112
+
113
+ expected = sequence(
114
+ record(people_id, 2, people_name, 'Khilan', people_age, 25, people_address, 'Delhi', people_salary, 1500.00, order_order_id, 101, order_id, 2, order_date, '2012', order_amount, 1560),
115
+ record(people_id, 3, people_name, 'kaushik', people_age, 23, people_address, 'Kota', people_salary, 2000.00, order_order_id, 102, order_id, 3, order_date, '2014', order_amount, 3000),
116
+ record(people_id, 3, people_name, 'kaushik', people_age, 23, people_address, 'Kota', people_salary, 2000.00, order_order_id, 100, order_id, 3, order_date, '2013', order_amount, 1500),
117
+ record(people_id, 4, people_name, 'Chaitali',people_age, 25, people_address, 'Mumbai', people_salary, 6500.00, order_order_id, 103, order_id, 4, order_date, '2012', order_amount, 2060)
118
+ )
119
+ expect(@records.inner_join(people, orders, id => id).entries).to eq(expected.entries)
120
+ end
121
+
122
+ def data_for_joins
123
+ id = keyword(:id)
124
+ name = keyword(:name)
125
+ age = keyword(:age)
126
+ address = keyword(:address)
127
+ salary = keyword(:salary)
128
+ people = definition(:people, id, name, age)
129
+
130
+ people_list = sequence(
131
+ record(id, 1, name, 'Ramesh', age, 32, address, 'Ahmedabad', salary, 2000.00),
132
+ record(id, 2, name, 'Khilan', age, 25, address, 'Delhi', salary, 1500.00),
133
+ record(id, 3, name, 'kaushik', age, 23, address, 'Kota', salary, 2000.00),
134
+ record(id, 4, name, 'Chaitali', age, 25, address, 'Mumbai', salary, 6500.00),
135
+ record(id, 5, name, 'Hardik', age, 27, address, 'Bhopal', salary, 8500.00),
136
+ record(id, 6, name, 'Komal', age, 22, address, 'MP', salary, 4500.00),
137
+ record(id, 7, name, 'Muffy', age, 24, address, 'Indore', salary, 10000.00)
138
+ )
139
+
140
+ @records.add(people, people_list)
141
+
142
+
143
+ order_id = keyword(:order_id)
144
+ date = keyword(:date)
145
+ amount = keyword(:amount)
146
+
147
+ orders = definition(:orders, order_id, id, date, amount)
148
+
149
+ orders_list = sequence(
150
+ record(order_id, 102, id, 3, date, '2014', amount, 3000),
151
+ record(order_id, 100, id, 3, date, '2013', amount, 1500),
152
+ record(order_id, 101, id, 2, date, '2012', amount, 1560),
153
+ record(order_id, 103, id, 4, date, '2012', amount, 2060)
154
+ )
155
+
156
+ @records.add(orders, orders_list)
157
+ end
158
+
159
+
160
+ end
@@ -0,0 +1,29 @@
1
+ require 'simplecov'
2
+
3
+ module SimpleCov::Configuration
4
+ def clean_filters
5
+ @filters = []
6
+ end
7
+ end
8
+
9
+ SimpleCov.configure do
10
+ clean_filters
11
+ load_profile 'test_frameworks'
12
+ end
13
+
14
+ ENV["COVERAGE"] && SimpleCov.start do
15
+ add_filter "/.rvm/"
16
+ end
17
+ $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
18
+ $LOAD_PATH.unshift(File.dirname(__FILE__))
19
+
20
+ require 'rspec'
21
+ require 'lazy_records'
22
+
23
+ # Requires supporting files with custom matchers and macros, etc,
24
+ # in ./support/ and its subdirectories.
25
+ Dir["#{File.dirname(__FILE__)}/support/**/*.rb"].each {|f| require f}
26
+
27
+ RSpec.configure do |config|
28
+
29
+ end
@@ -0,0 +1,194 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
2
+
3
+ describe SqlRecords do
4
+
5
+ before(:each) do
6
+ @c = double("DbConnection")
7
+ @records = SqlRecords.new(@c)
8
+ end
9
+
10
+ it 'should add records' do
11
+ name = keyword(:name)
12
+ age = keyword(:age)
13
+ people = definition(:people, name, age)
14
+
15
+ allow(@c).to receive(:query).with('insert into people (name,age) values ("kostas",25)')
16
+ allow(@c).to receive(:query).with('insert into people (name,age) values ("kings",34)')
17
+ allow(@c).to receive(:query).with('select * from people') {
18
+ [record(name, 'kostas', age, 25), record(name, 'kings', age, 34)]
19
+ }
20
+
21
+ @records.add(people, sequence(
22
+ record(name, 'kostas', age, 25),
23
+ record(name, 'kings', age, 34)))
24
+
25
+
26
+ expect(@records.get(people).count).to eq(2)
27
+ expect(@records.get(people).head.name).to eq('kostas')
28
+ end
29
+
30
+ it 'should update records with set' do
31
+ name = keyword(:name)
32
+ age = keyword(:age)
33
+ people = definition(:people, name, age)
34
+
35
+ allow(@c).to receive(:query).with('insert into people (name,age) values ("kostas",25)')
36
+ allow(@c).to receive(:query).with('insert into people (name,age) values ("kings",34)')
37
+ allow(@c).to receive(:query).with("update people set age='35' where name = 'kostas'")
38
+ allow(@c).to receive(:query).with('select * from people') {
39
+ [record(name, 'kostas', age, 35), record(name, 'kings', age, 34)]
40
+ }
41
+
42
+ @records.add(people, sequence(
43
+ record(name, 'kostas', age, 25)))
44
+
45
+ @records.add(people, sequence(
46
+ record(name, 'kings', age, 34)))
47
+
48
+ @records.set(people, where(name: equals('kostas')), age, 35)
49
+ expect(@records.get(people).filter(where(name: equals('kostas'))).head.age).to eq(35)
50
+ end
51
+
52
+
53
+ it 'should remove records' do
54
+ name = keyword(:name)
55
+ age = keyword(:age)
56
+ people = definition(:people, name, age)
57
+
58
+ allow(@c).to receive(:query).with('insert into people (name,age) values ("andrew",25)')
59
+ allow(@c).to receive(:query).with('insert into people (name,age) values ("kostas",26)')
60
+ allow(@c).to receive(:query).with("delete from people where name = 'andrew'")
61
+ allow(@c).to receive(:query).with('select * from people') {
62
+ [record(name, 'kostas', age, 26)]
63
+ }
64
+
65
+ @records.add(people, sequence(
66
+ record(name, 'andrew', age, 25),
67
+ record(name, 'kostas', age, 26),
68
+ ))
69
+
70
+ @records.remove(people, where(name: equals('andrew')))
71
+ expect(@records.get(people).head).to eq(record(name, 'kostas', age, 26))
72
+
73
+ end
74
+
75
+ it 'should filter records' do
76
+ name = keyword(:name)
77
+ age = keyword(:age)
78
+ people = definition(:people, name, age)
79
+
80
+ allow(@c).to receive(:query).with('insert into people (name,age) values ("kostas",25)')
81
+ allow(@c).to receive(:query).with('insert into people (name,age) values ("andrew",26)')
82
+ allow(@c).to receive(:query).with('insert into people (name,age) values ("david",27)')
83
+ allow(@c).to receive(:query).with('insert into people (name,age) values ("mike",28)')
84
+ allow(@c).to receive(:query).with('insert into people (name,age) values ("kings",29)')
85
+
86
+ @records.add(people, sequence(
87
+ record(name, 'kostas', age, 25),
88
+ record(name, 'andrew', age, 26),
89
+ record(name, 'david', age, 27),
90
+ record(name, 'mike', age, 28),
91
+ record(name, 'kings', age, 29)))
92
+
93
+ allow(@c).to receive(:query).with("select * from people where name like '%k%'") {
94
+ [record(name, 'kostas', age, 25),
95
+ record(name, 'mike', age, 28),
96
+ record(name, 'kings', age, 29)]
97
+ }
98
+
99
+ expect(@records.get(people,where(name: like('%k%'))).count).to eq(3)
100
+ end
101
+
102
+ it 'should support inner join' do
103
+ data_for_joins
104
+
105
+ id = keyword(:id)
106
+ name = keyword(:name)
107
+ age = keyword(:age)
108
+ order_id = keyword(:order_id)
109
+ date = keyword(:date)
110
+ amount = keyword(:amount)
111
+
112
+ people = definition(:people, id, name, age)
113
+ orders = definition(:orders, order_id, id, date, amount)
114
+
115
+ people_id = keyword(:people_id)
116
+ people_name = keyword(:people_name)
117
+ people_age = keyword(:people_age)
118
+ people_address = keyword(:people_address)
119
+ people_salary = keyword(:people_salary)
120
+ order_id = keyword(:orders_id)
121
+ order_order_id = keyword(:orders_order_id)
122
+ order_date = keyword(:orders_date)
123
+ order_amount = keyword(:orders_amount)
124
+
125
+ expected = sequence(
126
+ record(people_id, 2, people_name, 'Khilan', people_age, 25, people_address, 'Delhi', people_salary, 1500.00, order_order_id, 101, order_id, 2, order_date, '2012', order_amount, 1560),
127
+ record(people_id, 3, people_name, 'kaushik', people_age, 23, people_address, 'Kota', people_salary, 2000.00, order_order_id, 102, order_id, 3, order_date, '2014', order_amount, 3000),
128
+ record(people_id, 3, people_name, 'kaushik', people_age, 23, people_address, 'Kota', people_salary, 2000.00, order_order_id, 100, order_id, 3, order_date, '2013', order_amount, 1500),
129
+ record(people_id, 4, people_name, 'Chaitali', people_age, 25, people_address, 'Mumbai', people_salary, 6500.00, order_order_id, 103, order_id, 4, order_date, '2012', order_amount, 2060)
130
+ )
131
+
132
+ allow(@c).to receive(:query).with("select people.id as 'people_id', people.name as 'people_name', people.age as 'people_age' orders.order_id as 'orders_order_id', orders.id as 'orders_id', orders.date as 'orders_date', orders.amount as 'orders_amount' from people inner join orders on people.id = orders.id") {
133
+ [record(people_id, 2, people_name, 'Khilan', people_age, 25, people_address, 'Delhi', people_salary, 1500.00, order_order_id, 101, order_id, 2, order_date, '2012', order_amount, 1560),
134
+ record(people_id, 3, people_name, 'kaushik', people_age, 23, people_address, 'Kota', people_salary, 2000.00, order_order_id, 102, order_id, 3, order_date, '2014', order_amount, 3000),
135
+ record(people_id, 3, people_name, 'kaushik', people_age, 23, people_address, 'Kota', people_salary, 2000.00, order_order_id, 100, order_id, 3, order_date, '2013', order_amount, 1500),
136
+ record(people_id, 4, people_name, 'Chaitali', people_age, 25, people_address, 'Mumbai', people_salary, 6500.00, order_order_id, 103, order_id, 4, order_date, '2012', order_amount, 2060)]
137
+ }
138
+
139
+ expect(@records.inner_join(people, orders, id => id).entries).to eq(expected.entries)
140
+ end
141
+
142
+
143
+ def data_for_joins
144
+ id = keyword(:id)
145
+ name = keyword(:name)
146
+ age = keyword(:age)
147
+ address = keyword(:address)
148
+ salary = keyword(:salary)
149
+ people = definition(:people, id, name, age)
150
+
151
+ allow(@c).to receive(:query).with('insert into people (id,name,age,address,salary) values (1,"Ramesh",32,"Ahmedabad",2000.0)')
152
+ allow(@c).to receive(:query).with('insert into people (id,name,age,address,salary) values (2,"Khilan",25,"Delhi",1500.0)')
153
+ allow(@c).to receive(:query).with('insert into people (id,name,age,address,salary) values (3,"kaushik",23,"Kota",2000.0)')
154
+ allow(@c).to receive(:query).with('insert into people (id,name,age,address,salary) values (4,"Chaitali",25,"Mumbai",6500.0)')
155
+ allow(@c).to receive(:query).with('insert into people (id,name,age,address,salary) values (5,"Hardik",27,"Bhopal",8500.0)')
156
+ allow(@c).to receive(:query).with('insert into people (id,name,age,address,salary) values (6,"Komal",22,"MP",4500.0)')
157
+ allow(@c).to receive(:query).with('insert into people (id,name,age,address,salary) values (7,"Muffy",24,"Indore",10000.0)')
158
+
159
+ people_list = sequence(
160
+ record(id, 1, name, 'Ramesh', age, 32, address, 'Ahmedabad', salary, 2000.00),
161
+ record(id, 2, name, 'Khilan', age, 25, address, 'Delhi', salary, 1500.00),
162
+ record(id, 3, name, 'kaushik', age, 23, address, 'Kota', salary, 2000.00),
163
+ record(id, 4, name, 'Chaitali', age, 25, address, 'Mumbai', salary, 6500.00),
164
+ record(id, 5, name, 'Hardik', age, 27, address, 'Bhopal', salary, 8500.00),
165
+ record(id, 6, name, 'Komal', age, 22, address, 'MP', salary, 4500.00),
166
+ record(id, 7, name, 'Muffy', age, 24, address, 'Indore', salary, 10000.00)
167
+ )
168
+
169
+ @records.add(people, people_list)
170
+
171
+
172
+ order_id = keyword(:order_id)
173
+ date = keyword(:date)
174
+ amount = keyword(:amount)
175
+
176
+ orders = definition(:orders, order_id, id, date, amount)
177
+
178
+ allow(@c).to receive(:query).with('insert into orders (order_id,id,date,amount) values (102,3,"2014",3000)')
179
+ allow(@c).to receive(:query).with('insert into orders (order_id,id,date,amount) values (100,3,"2013",1500)')
180
+ allow(@c).to receive(:query).with('insert into orders (order_id,id,date,amount) values (101,2,"2012",1560)')
181
+ allow(@c).to receive(:query).with('insert into orders (order_id,id,date,amount) values (103,4,"2012",2060)')
182
+
183
+ orders_list = sequence(
184
+ record(order_id, 102, id, 3, date, '2014', amount, 3000),
185
+ record(order_id, 100, id, 3, date, '2013', amount, 1500),
186
+ record(order_id, 101, id, 2, date, '2012', amount, 1560),
187
+ record(order_id, 103, id, 4, date, '2012', amount, 2060)
188
+ )
189
+
190
+ @records.add(orders, orders_list)
191
+ end
192
+
193
+
194
+ end
File without changes
metadata ADDED
@@ -0,0 +1,193 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: lazy_store
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ platform: ruby
6
+ authors:
7
+ - Kingsley Hendrickse
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2014-10-03 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: totally_lazy
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ">="
18
+ - !ruby/object:Gem::Version
19
+ version: '0'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ">="
25
+ - !ruby/object:Gem::Version
26
+ version: '0'
27
+ - !ruby/object:Gem::Dependency
28
+ name: lock_method
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: '0'
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ">="
39
+ - !ruby/object:Gem::Version
40
+ version: '0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: encrypted_strings
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ">="
46
+ - !ruby/object:Gem::Version
47
+ version: '0'
48
+ type: :runtime
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ">="
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
55
+ - !ruby/object:Gem::Dependency
56
+ name: mysql2
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - ">="
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ type: :runtime
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - ">="
67
+ - !ruby/object:Gem::Version
68
+ version: '0'
69
+ - !ruby/object:Gem::Dependency
70
+ name: rspec
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - "~>"
74
+ - !ruby/object:Gem::Version
75
+ version: 3.0.0.rc1
76
+ type: :development
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - "~>"
81
+ - !ruby/object:Gem::Version
82
+ version: 3.0.0.rc1
83
+ - !ruby/object:Gem::Dependency
84
+ name: rdoc
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - "~>"
88
+ - !ruby/object:Gem::Version
89
+ version: '3.12'
90
+ type: :development
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - "~>"
95
+ - !ruby/object:Gem::Version
96
+ version: '3.12'
97
+ - !ruby/object:Gem::Dependency
98
+ name: bundler
99
+ requirement: !ruby/object:Gem::Requirement
100
+ requirements:
101
+ - - "~>"
102
+ - !ruby/object:Gem::Version
103
+ version: '1.0'
104
+ type: :development
105
+ prerelease: false
106
+ version_requirements: !ruby/object:Gem::Requirement
107
+ requirements:
108
+ - - "~>"
109
+ - !ruby/object:Gem::Version
110
+ version: '1.0'
111
+ - !ruby/object:Gem::Dependency
112
+ name: jeweler
113
+ requirement: !ruby/object:Gem::Requirement
114
+ requirements:
115
+ - - "~>"
116
+ - !ruby/object:Gem::Version
117
+ version: 2.0.1
118
+ type: :development
119
+ prerelease: false
120
+ version_requirements: !ruby/object:Gem::Requirement
121
+ requirements:
122
+ - - "~>"
123
+ - !ruby/object:Gem::Version
124
+ version: 2.0.1
125
+ - !ruby/object:Gem::Dependency
126
+ name: simplecov
127
+ requirement: !ruby/object:Gem::Requirement
128
+ requirements:
129
+ - - ">="
130
+ - !ruby/object:Gem::Version
131
+ version: '0'
132
+ type: :development
133
+ prerelease: false
134
+ version_requirements: !ruby/object:Gem::Requirement
135
+ requirements:
136
+ - - ">="
137
+ - !ruby/object:Gem::Version
138
+ version: '0'
139
+ description: port of lazy records to ruby
140
+ email: kingsley.hendrickse@gmail.com
141
+ executables: []
142
+ extensions: []
143
+ extra_rdoc_files:
144
+ - LICENSE.txt
145
+ - README.md
146
+ files:
147
+ - ".document"
148
+ - ".rspec"
149
+ - Gemfile
150
+ - Gemfile.lock
151
+ - LICENSE.txt
152
+ - README.md
153
+ - Rakefile
154
+ - VERSION
155
+ - lib/adapters/mssql.rb
156
+ - lib/adapters/mysql.rb
157
+ - lib/definition.rb
158
+ - lib/keyword.rb
159
+ - lib/lazy_records.rb
160
+ - lib/memory_records.rb
161
+ - lib/predicate_to_sql.rb
162
+ - lib/predicates.rb
163
+ - lib/record.rb
164
+ - lib/sql_records.rb
165
+ - spec/memory_records_spec.rb
166
+ - spec/spec_helper.rb
167
+ - spec/sql_records_spec.rb
168
+ - spec/test_data/.keep
169
+ homepage: http://github.com/kingsleyh/lazy_records
170
+ licenses:
171
+ - MIT
172
+ metadata: {}
173
+ post_install_message:
174
+ rdoc_options: []
175
+ require_paths:
176
+ - lib
177
+ required_ruby_version: !ruby/object:Gem::Requirement
178
+ requirements:
179
+ - - ">="
180
+ - !ruby/object:Gem::Version
181
+ version: '0'
182
+ required_rubygems_version: !ruby/object:Gem::Requirement
183
+ requirements:
184
+ - - ">="
185
+ - !ruby/object:Gem::Version
186
+ version: '0'
187
+ requirements: []
188
+ rubyforge_project:
189
+ rubygems_version: 2.2.2
190
+ signing_key:
191
+ specification_version: 4
192
+ summary: port of lazy records to ruby
193
+ test_files: []