active_pstore 0.4.0

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: ce4d5fd7b68f1d584089e97ec4def1991c31bc0b
4
+ data.tar.gz: 35d4299645636ba48b0ee2201eed2c531ca69e1c
5
+ SHA512:
6
+ metadata.gz: 96b1291e03675054463557a341f2b41ad8318c91973538e3cea7392ac1bc89d523156f6d00b7588a55814d3875e0630b91116920a29d6d4408fa1c51974430dd
7
+ data.tar.gz: 1462643017e90750bab55d9cd0a5dd8d4b4e2037b3653dc4505e44a2415bc5858a8eedffff66b60fa662654113ddee50962fc3ddc460dc77d98355ba1546abb1
data/LICENSE ADDED
@@ -0,0 +1,19 @@
1
+ Copyright (c) 2015 Koichi ITO
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining a copy
4
+ of this software and associated documentation files (the "Software"), to deal
5
+ in the Software without restriction, including without limitation the rights
6
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7
+ copies of the Software, and to permit persons to whom the Software is
8
+ furnished to do so, subject to the following conditions:
9
+
10
+ The above copyright notice and this permission notice shall be included in
11
+ all copies or substantial portions of the Software.
12
+
13
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
19
+ THE SOFTWARE.
data/README.ja.md ADDED
@@ -0,0 +1,109 @@
1
+ # Active PStore [Active Record](https://github.com/rails/rails/tree/master/activerecord)に似たインターフェイスを持ったライブラリです。
2
+ データの保存には[pstore](http://docs.ruby-lang.org/ja/2.2.0/library/pstore.html)を使います。
3
+
4
+ ## FEATURES/PROBLEMS
5
+
6
+ * それなりに問題を持っています
7
+ * トランザクションをサポートしてません
8
+ * データマイグレーションをサポートしてません
9
+ * パフォーマンス (特に実装面とか)
10
+ * これらのことからエンタープライズ要件には向かないです
11
+
12
+ ## SYNOPSIS
13
+
14
+ ### クラス定義とインスタンスの生成
15
+
16
+ ```
17
+ require 'active_pstore'
18
+
19
+ class Artist < ActivePStore::Base
20
+ def initialize(name)
21
+ @name = name
22
+ end
23
+
24
+ attr_reader :name
25
+ end
26
+
27
+ randy_rhoads = Artist.new('Randy Rhoads')
28
+ ```
29
+
30
+ ### データの保存先のファイルパス指定
31
+
32
+ ```
33
+ Artist.establish_connection(database: '/path/to/file')
34
+ ```
35
+
36
+ ### インスタンスの保存
37
+
38
+ ```
39
+ randy_rhoads.save
40
+ ```
41
+
42
+ saveメソッドの対象オブジェクトのクラス名がPStoreのキーになります。
43
+
44
+ ```
45
+ database = PStore.new('/path/to/file')
46
+ database.transaction {|db| artist = db['Artist'] } # fetch instances of Artist class.
47
+ ```
48
+
49
+ 保存時に[SecureRandom.hex](http://docs.ruby-lang.org/ja/2.2.0/class/SecureRandom.html#S_HEX)の値を使ったActivePStore::Base#idが付与されます。
50
+
51
+ ```
52
+ > randy_rhoads.id # => nil
53
+ > randy_rhoads.save
54
+ > randy_rhoads.id # => "0b84ece5d5be3bce3ee2101c1c4f6fda"
55
+ ```
56
+
57
+ ### 検索系
58
+
59
+ ```
60
+ Artist.all
61
+ Artist.first
62
+ Artist.last
63
+ Artist.find('388980778246cbcbfcbb7a8292f28c37')
64
+ Artist.where(name: 'Randy Rhoads')
65
+ ```
66
+
67
+ 範囲指定
68
+
69
+ ```
70
+ Artist.where(birth_date: Date.new(1948, 12, 3)..Date.new(1956, 12, 6))
71
+ ```
72
+
73
+ 続きはテストコードをご参照ください。
74
+
75
+ ## REQUIREMENTS
76
+
77
+ * no requirements
78
+
79
+ ## INSTALL
80
+
81
+ Add these lines to your application's Gemfile:
82
+
83
+ ```
84
+ gem 'active_pstore'
85
+ ```
86
+
87
+ And then execute:
88
+
89
+ ```
90
+ $ bundle
91
+ ```
92
+
93
+ Or install it yourself as:
94
+
95
+ ```
96
+ $ gem install active_pstore
97
+ ```
98
+
99
+ ## LICENCE
100
+
101
+ The MIT Licence
102
+
103
+ ## Contributing
104
+
105
+ 1. Fork it
106
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
107
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
108
+ 4. Push to the branch (`git push origin my-new-feature`)
109
+ 5. Create new Pull Request
data/README.md ADDED
@@ -0,0 +1,110 @@
1
+ # Active PStore [![Build Status](https://travis-ci.org/koic/active-pstore.svg)](https://travis-ci.org/koic/active-pstore) [![Code Climate](https://codeclimate.com/github/koic/active-pstore/badges/gpa.svg)](https://codeclimate.com/github/koic/active-pstore) [![Test Coverage](https://codeclimate.com/github/koic/active-pstore/badges/coverage.svg)](https://codeclimate.com/github/koic/active-pstore/coverage) [![Gem Version](https://badge.fury.io/rb/active_pstore.svg)](http://badge.fury.io/rb/active_pstore)
2
+
3
+ This library has [Active Record](https://github.com/rails/rails/tree/master/activerecord) like interface. Use [pstore](http://docs.ruby-lang.org/en/2.2.0/PStore.html) to store data.
4
+
5
+ ## FEATURES/PROBLEMS
6
+
7
+ * Oh so many problems...
8
+ * Transaction NOT supported
9
+ * Data Migration NOT supported
10
+ * Performance (caused by implementation)
11
+ * and Not solving the root cause for enterprise...
12
+
13
+ ## SYNOPSIS
14
+
15
+ ### class definition and instantiate
16
+
17
+ ```
18
+ require 'active_pstore'
19
+
20
+ class Artist < ActivePStore::Base
21
+ def initialize(name)
22
+ @name = name
23
+ end
24
+
25
+ attr_reader :name
26
+ end
27
+
28
+ randy_rhoads = Artist.new('Randy Rhoads')
29
+ ```
30
+
31
+ ### specify data store path
32
+
33
+ ```
34
+ Artist.establish_connection(database: '/path/to/file')
35
+ ```
36
+
37
+ ### save
38
+
39
+ ```
40
+ randy_rhoads.save
41
+ ```
42
+
43
+ database key is string of class name.
44
+
45
+ ```
46
+ database = PStore.new('/path/to/file')
47
+ database.transaction {|db| artist = db['Artist'] } # fetch instances of Artist class.
48
+ ```
49
+
50
+ allocate value of ActivePStore::Base#id using [SecureRandom.hex](http://ruby-doc.org/stdlib-2.2.0/libdoc/securerandom//rdoc/SecureRandom.html#method-c-hex).
51
+
52
+ ```
53
+ > foo.id # => nil
54
+ > randy_rhoads.save
55
+ > foo.id # => "0b84ece5d5be3bce3ee2101c1c4f6fda"
56
+ ```
57
+
58
+ ### find series
59
+
60
+ ```
61
+ Artist.all
62
+ Artist.first
63
+ Artist.last
64
+ Artist.find('388980778246cbcbfcbb7a8292f28c37') # ActivePStore::Base#id is an SecureRandom.hex value
65
+ Artist.where(name: 'Randy Rhoads')
66
+ ```
67
+
68
+ Range
69
+
70
+ ```
71
+ Artist.where(birth_date: Date.new(1948, 12, 3)..Date.new(1956, 12, 6))
72
+ ```
73
+
74
+ see spec codes for more information.
75
+
76
+ ## REQUIREMENTS
77
+
78
+ no requirements
79
+
80
+ ## INSTALL
81
+
82
+ Add these lines to your application's Gemfile:
83
+
84
+ ```
85
+ gem 'active_pstore'
86
+ ```
87
+
88
+ And then execute:
89
+
90
+ ```
91
+ $ bundle
92
+ ```
93
+
94
+ Or install it yourself as:
95
+
96
+ ```
97
+ $ gem install active_pstore
98
+ ```
99
+
100
+ ## LICENCE
101
+
102
+ The MIT Licence
103
+
104
+ ## Contributing
105
+
106
+ 1. Fork it
107
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
108
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
109
+ 4. Push to the branch (`git push origin my-new-feature`)
110
+ 5. Create new Pull Request
@@ -0,0 +1,23 @@
1
+ module ActivePStore
2
+ class Base
3
+ extend ActivePStore::ConnectionHandling
4
+ extend ActivePStore::FinderMethods
5
+ extend ActivePStore::Inheritance
6
+ extend ActivePStore::Querying
7
+ extend ActivePStore::QueryMethods
8
+ include ActivePStore::Core
9
+ include ActivePStore::Persistence
10
+
11
+ class << self
12
+ def all
13
+ use_connection do |connection|
14
+ ActivePStore::Collection.new(connection[self.pstore_key] || [])
15
+ end
16
+ end
17
+
18
+ def pstore_key
19
+ self.to_s
20
+ end
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,33 @@
1
+ module ActivePStore
2
+ class Collection
3
+ def initialize(objects)
4
+ @objects = objects
5
+ end
6
+
7
+ def update_all(updates)
8
+ @objects.each {|obj|
9
+ obj.update_attributes(updates)
10
+ }.count
11
+ end
12
+
13
+ def destroy_all
14
+ @objects.inject(0) {|result, obj|
15
+ obj.destroy
16
+
17
+ result += 1
18
+ }
19
+ end
20
+
21
+ def count
22
+ @objects.count
23
+ end
24
+
25
+ def empty?
26
+ @objects.empty?
27
+ end
28
+
29
+ def method_missing(method_name, *args, &block)
30
+ @objects.__send__(method_name, *args, &block)
31
+ end
32
+ end
33
+ end
@@ -0,0 +1,21 @@
1
+ require 'pstore'
2
+
3
+ module ActivePStore
4
+ module ConnectionHandling
5
+ def establish_connection(options)
6
+ unless options.is_a? Hash
7
+ raise ArgumentError, "You must specify at database configuration. Example: ActivePStore::Base.establish_connection(database: '/path/to/file')"
8
+ end
9
+
10
+ @@db = PStore.new((options[:database] || options['database']).to_s)
11
+ end
12
+
13
+ def use_connection
14
+ @@db.transaction do |pstore|
15
+ yield pstore
16
+ end
17
+ rescue # uninitialized class variable @@db in ActivePStore::Base
18
+ raise ActivePStore::ConnectionNotEstablished, "Raised when connection to the pstore file path could not been established (for example when ActivePStore.establish_connection(database: '/path/to/file') is given a nil object)."
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,20 @@
1
+ module ActivePStore
2
+ module Core
3
+ def ==(comparison_object)
4
+ if id
5
+ comparison_object.instance_of?(self.class) && comparison_object.id == id
6
+ else
7
+ super
8
+ end
9
+ end
10
+ alias :eql? :==
11
+
12
+ def hash
13
+ if id
14
+ id.hash
15
+ else
16
+ super
17
+ end
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,4 @@
1
+ module ActivePStore
2
+ class ConnectionNotEstablished < StandardError; end
3
+ class RecordNotFound < StandardError; end
4
+ end
@@ -0,0 +1,29 @@
1
+ module ActivePStore
2
+ module FinderMethods
3
+ def find(id)
4
+ id = id.is_a?(ActivePStore::Base) ? id.id : id
5
+
6
+ all.find {|obj| obj.id == id } || (raise ActivePStore::RecordNotFound, "Couldn't find #{self} with 'id'=#{id}")
7
+ end
8
+
9
+ def find_by(conditions = {})
10
+ where(conditions).first
11
+ end
12
+
13
+ def find_by!(conditions = {})
14
+ find_by(conditions) || (raise ActivePStore::RecordNotFound, "Couldn't find #{self} with conditions=#{conditions}")
15
+ end
16
+
17
+ def first
18
+ all.first
19
+ end
20
+
21
+ def last
22
+ all.last
23
+ end
24
+
25
+ def take(limit = nil)
26
+ limit ? all.take(limit) : first
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,11 @@
1
+ module ActivePStore
2
+ module Inheritance
3
+ def new(*args)
4
+ if self == ActivePStore::Base
5
+ raise NotImplementedError, "#{self} is an abstract class and cannot be instantiated."
6
+ else
7
+ super
8
+ end
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,51 @@
1
+ require 'securerandom'
2
+
3
+ module ActivePStore
4
+ module Persistence
5
+ attr_reader :id
6
+
7
+ def destroy
8
+ ActivePStore::Base.use_connection do |connection|
9
+ connection[self.class.pstore_key].delete_if {|obj| obj.id == self.id }
10
+ end
11
+
12
+ self
13
+ end
14
+
15
+ def new_record?
16
+ @id.nil?
17
+ end
18
+
19
+ def save
20
+ ActivePStore::Base.use_connection do |connection|
21
+ if new_record?
22
+ @id = SecureRandom.hex
23
+
24
+ if connection[self.class.pstore_key]
25
+ connection[self.class.pstore_key] << self
26
+ else
27
+ connection[self.class.pstore_key] = [self]
28
+ end
29
+ else
30
+ connection[self.class.pstore_key].map! {|obj| obj.id == self.id ? self : obj }
31
+ end
32
+ end
33
+
34
+ true
35
+ end
36
+
37
+ def update_attribute(attr_name, attr_value)
38
+ self.__send__("#{attr_name}=", attr_value)
39
+
40
+ save
41
+ end
42
+
43
+ def update_attributes(attrs)
44
+ attrs.each do |attr_name, attr_value|
45
+ self.__send__("#{attr_name}=", attr_value)
46
+ end
47
+
48
+ save
49
+ end
50
+ end
51
+ end
@@ -0,0 +1,21 @@
1
+ module ActivePStore
2
+ module QueryMethods
3
+ def where(conditions = {})
4
+ ret = all
5
+
6
+ return ret if conditions.empty?
7
+
8
+ conditions.each do |key, value|
9
+ ret = ret.select {|obj|
10
+ if value.is_a? Range
11
+ value.include?(obj.__send__(key))
12
+ else
13
+ obj.__send__(key) == value
14
+ end
15
+ }
16
+ end
17
+
18
+ ActivePStore::Collection.new(ret)
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,19 @@
1
+ module ActivePStore
2
+ module Querying
3
+ def update_all(updates)
4
+ all.update_all(updates)
5
+ end
6
+
7
+ def destroy_all
8
+ all.destroy_all
9
+ end
10
+
11
+ def count
12
+ all.count
13
+ end
14
+
15
+ def emtpy?
16
+ all.empty?
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,14 @@
1
+ module ActivePStore
2
+ module Timestamps
3
+ module Created
4
+ attr_accessor :created_at
5
+ end
6
+
7
+ module Updated
8
+ attr_accessor :updated_at
9
+ end
10
+
11
+ include Created
12
+ include Updated
13
+ end
14
+ end
@@ -0,0 +1,3 @@
1
+ module ActivePStore
2
+ VERSION = '0.4.0'
3
+ end
@@ -0,0 +1,12 @@
1
+ module ActivePStore; end
2
+
3
+ require 'active_pstore/collection'
4
+ require 'active_pstore/connection_handling'
5
+ require 'active_pstore/core'
6
+ require 'active_pstore/finder_methods'
7
+ require 'active_pstore/inheritance'
8
+ require 'active_pstore/persistence'
9
+ require 'active_pstore/query_methods'
10
+ require 'active_pstore/querying'
11
+ require 'active_pstore/base'
12
+ require 'active_pstore/errors'
metadata ADDED
@@ -0,0 +1,87 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: active_pstore
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.4.0
5
+ platform: ruby
6
+ authors:
7
+ - Koichi ITO
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2015-06-02 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: codeclimate-test-reporter
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ">="
18
+ - !ruby/object:Gem::Version
19
+ version: '0'
20
+ type: :development
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: rspec
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: 3.0.0
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ">="
39
+ - !ruby/object:Gem::Version
40
+ version: 3.0.0
41
+ description: This library has Active Record like interface. Use pstore to store data.
42
+ email: koic.ito@gmail.com
43
+ executables: []
44
+ extensions: []
45
+ extra_rdoc_files: []
46
+ files:
47
+ - LICENSE
48
+ - README.ja.md
49
+ - README.md
50
+ - lib/active_pstore.rb
51
+ - lib/active_pstore/base.rb
52
+ - lib/active_pstore/collection.rb
53
+ - lib/active_pstore/connection_handling.rb
54
+ - lib/active_pstore/core.rb
55
+ - lib/active_pstore/errors.rb
56
+ - lib/active_pstore/finder_methods.rb
57
+ - lib/active_pstore/inheritance.rb
58
+ - lib/active_pstore/persistence.rb
59
+ - lib/active_pstore/query_methods.rb
60
+ - lib/active_pstore/querying.rb
61
+ - lib/active_pstore/timestamps.rb
62
+ - lib/active_pstore/version.rb
63
+ homepage: http://github.com/koic/active_pstore
64
+ licenses:
65
+ - MIT
66
+ metadata: {}
67
+ post_install_message:
68
+ rdoc_options: []
69
+ require_paths:
70
+ - lib
71
+ required_ruby_version: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - ">="
74
+ - !ruby/object:Gem::Version
75
+ version: 2.0.0
76
+ required_rubygems_version: !ruby/object:Gem::Requirement
77
+ requirements:
78
+ - - ">="
79
+ - !ruby/object:Gem::Version
80
+ version: '0'
81
+ requirements: []
82
+ rubyforge_project:
83
+ rubygems_version: 2.4.5
84
+ signing_key:
85
+ specification_version: 4
86
+ summary: This library has Active Record like interface. Use pstore to store data.
87
+ test_files: []