shoden 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.
Files changed (10) hide show
  1. checksums.yaml +7 -0
  2. data/.gems +1 -0
  3. data/HUGS +15 -0
  4. data/LICENSE +20 -0
  5. data/README.md +46 -0
  6. data/Rakefile +8 -0
  7. data/lib/shoden.rb +126 -0
  8. data/shoden.gemspec +15 -0
  9. data/test/shoden_test.rb +56 -0
  10. metadata +83 -0
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: ffad286c05b142a30dd2c56bcc1767d0811fdbe3
4
+ data.tar.gz: b30190789b1c0c31bd2f47bb4bfca193762d9f80
5
+ SHA512:
6
+ metadata.gz: 1aa71426212fa8d9bac34f40ea4ccd54002e1853711c40d991b0107b1f902f1ef20b2cf04ff0bd862280ad73de83148bad8bd979ebb1f294936249e0c57a4aa4
7
+ data.tar.gz: 1859a5eb54cb8efb7ba572e138eca892c44d7dbf30e99d1e06985ed75e63e01056fe54962c0550d3daa48885c1c44d5ab597cdd89026106bec87820500c46e8f
data/.gems ADDED
@@ -0,0 +1 @@
1
+ pg:0.17.1
data/HUGS ADDED
@@ -0,0 +1,15 @@
1
+ THE HUGWARE LICENSE
2
+
3
+ LICENSE
4
+
5
+ If there is no other license you can do whatever you want with this while you
6
+ retain the attribution to the author.
7
+
8
+ HUGS
9
+
10
+ The author spent time to make this software so please show some gratitude,
11
+ in any
12
+ form. A hug, a tweet, a beer on a conference or just a plain old email. Your
13
+ choice.
14
+
15
+ Less hate, more hugs.
data/LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2014 Bruno Aguirre
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,46 @@
1
+ # Shoden
2
+
3
+ Shoden is a persistance library on top of Postgres.
4
+ It is basically an [Ohm](https://github.com/soveran/ohm) clone but using
5
+ Postgres as a main database.
6
+
7
+ ## Installation
8
+
9
+ ```bash
10
+ gem install shoden
11
+ ```
12
+
13
+ ## Models
14
+
15
+ ```ruby
16
+ class Fruit < Shoden::Model
17
+ attribute :type
18
+ end
19
+ ```
20
+
21
+ ```ruby
22
+ Fruit.create type: "Banana"
23
+ ```
24
+
25
+ To find by an id:
26
+
27
+ ```ruby
28
+ Fruit[1]
29
+ ```
30
+
31
+ ## Relations
32
+
33
+ ```ruby
34
+ class User < Shoden::Model
35
+ attribute :email
36
+
37
+ collection :posts, :Post
38
+ end
39
+
40
+ class Post < Shoden::Model
41
+ attribute :title
42
+ attribute :content
43
+
44
+ reference :owner, :User
45
+ end
46
+ ```
data/Rakefile ADDED
@@ -0,0 +1,8 @@
1
+ require "rake/testtask"
2
+
3
+ Rake::TestTask.new("test") do |t|
4
+ t.libs << "test"
5
+ t.pattern = "test/**/*_test.rb"
6
+ end
7
+
8
+ task :default => [:test]
data/lib/shoden.rb ADDED
@@ -0,0 +1,126 @@
1
+ require 'sequel'
2
+
3
+ Sequel.extension :pg_hstore, :pg_hstore_ops
4
+
5
+ module Shoden
6
+ MissingID = Class.new(StandardError)
7
+
8
+ Proxy = Struct.new(:klass, :parent) do
9
+ def create(args = {})
10
+ key = "#{parent.class.to_reference}_id"
11
+ klass.create(args.merge(
12
+ key => parent.id
13
+ ))
14
+ end
15
+ end
16
+
17
+ def self.url=(url)
18
+ @_url = url
19
+ end
20
+
21
+ def self.url
22
+ @_url ||= ENV['DATABASE_URL']
23
+ end
24
+
25
+ def self.connection
26
+ @_connection ||= Sequel.connect(url)
27
+ end
28
+
29
+ class Model
30
+ def initialize(attrs = {})
31
+ @_id = attrs.delete(:id) if attrs[:id]
32
+ @attributes = Sequel::Postgres::HStore.new({})
33
+ update(attrs)
34
+ end
35
+
36
+ def id
37
+ raise MissingID if !defined?(@_id)
38
+ @_id.to_i
39
+ end
40
+
41
+ def update(attrs = {})
42
+ attrs.each { |name, value| send(:"#{name}=", value) }
43
+ end
44
+
45
+ def update_attributes(attrs = {})
46
+ update(attrs)
47
+ save
48
+ end
49
+
50
+ def save
51
+ conn.execute("CREATE EXTENSION IF NOT EXISTS hstore")
52
+ conn.create_table? table_name do
53
+ primary_key :id
54
+ hstore :data
55
+ end
56
+
57
+ if defined? @_id
58
+ table.where(id: @_id).update data: @attributes
59
+ else
60
+ @_id = table.insert data: @attributes
61
+ end
62
+
63
+ self
64
+ end
65
+
66
+ def load!
67
+ ret = table.where(id: @_id)
68
+ update(ret.to_a.first[:data])
69
+ self
70
+ end
71
+
72
+ def self.create(attrs = {})
73
+ new(attrs).save
74
+ end
75
+
76
+ def self.[](id)
77
+ new(id: id).load!
78
+ end
79
+
80
+ def self.attribute(name)
81
+ define_method(name) { @attributes[name] }
82
+ define_method(:"#{name}=") { |value| @attributes[name] = value }
83
+ end
84
+
85
+ def self.collection(name, model)
86
+ define_method(name) do
87
+ klass = Kernel.const_get(model)
88
+ Proxy.new(klass, self)
89
+ end
90
+ end
91
+
92
+ def self.reference(name, model)
93
+ reader = :"#{name}_id"
94
+ writer = :"#{name}_id="
95
+
96
+ define_method(reader) { @attributes[reader] }
97
+ define_method(writer) { |value| @attributes[reader] = value }
98
+
99
+ define_method(name) do
100
+ klass = Kernel.const_get(model)
101
+ klass[send(reader)]
102
+ end
103
+ end
104
+
105
+ private
106
+
107
+ def self.to_reference
108
+ name.to_s.
109
+ match(/^(?:.*::)*(.*)$/)[1].
110
+ gsub(/([a-z\d])([A-Z])/, '\1_\2').
111
+ downcase.to_sym
112
+ end
113
+
114
+ def table_name
115
+ :"Shoden::#{self.class.name}"
116
+ end
117
+
118
+ def table
119
+ conn[table_name]
120
+ end
121
+
122
+ def conn
123
+ Shoden.connection
124
+ end
125
+ end
126
+ end
data/shoden.gemspec ADDED
@@ -0,0 +1,15 @@
1
+ Gem::Specification.new do |s|
2
+ s.name = "shoden"
3
+ s.version = "0.1.0"
4
+ s.summary = "Object hash mapper for postgres"
5
+ s.description = "Slim postgres models"
6
+ s.authors = ["elcuervo"]
7
+ s.licenses = ["MIT", "HUGWARE"]
8
+ s.email = ["yo@brunoaguirre.com"]
9
+ s.homepage = "http://github.com/elcuervo/shoden"
10
+ s.files = `git ls-files`.split("\n")
11
+ s.test_files = `git ls-files test`.split("\n")
12
+
13
+ s.add_dependency("sequel", "~> 4.11.0")
14
+ s.add_development_dependency("cutest", "~> 1.2.1")
15
+ end
@@ -0,0 +1,56 @@
1
+ require 'cutest'
2
+ require 'shoden'
3
+
4
+ Model = Class.new(Shoden::Model)
5
+
6
+ class User < Shoden::Model
7
+ attribute :name
8
+ end
9
+
10
+ test 'model' do
11
+ model = Model.create
12
+ assert_equal model.id.class, Fixnum
13
+ end
14
+
15
+ test 'attributes' do
16
+ user = User.create name: 'Michel'
17
+ assert_equal user.name, 'Michel'
18
+ end
19
+
20
+ test 'update' do
21
+ user = User.create name: 'Cyril'
22
+ id = user.id
23
+
24
+ assert_equal user.name, 'Cyril'
25
+
26
+ user.name = 'cyx'
27
+ user.save
28
+
29
+ assert_equal user.name, 'cyx'
30
+ assert_equal user.id, id
31
+
32
+ user.update_attributes(name: 'Cyril')
33
+ assert_equal user.name, 'Cyril'
34
+ end
35
+
36
+ test 'relations' do
37
+ class Tree < Shoden::Model
38
+ attribute :name
39
+ collection :sprouts, :Sprout
40
+ end
41
+
42
+ class Sprout < Shoden::Model
43
+ attribute :leaves
44
+ reference :tree, :Tree
45
+ end
46
+
47
+ tree = Tree.create(name: 'asd')
48
+
49
+ assert tree.id
50
+ assert_equal tree.name, 'asd'
51
+
52
+ sprout = tree.sprouts.create(leaves: 4)
53
+
54
+ assert sprout.is_a?(Sprout)
55
+ assert_equal sprout.tree.id, tree.id
56
+ end
metadata ADDED
@@ -0,0 +1,83 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: shoden
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - elcuervo
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2014-10-24 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: sequel
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ~>
18
+ - !ruby/object:Gem::Version
19
+ version: 4.11.0
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ~>
25
+ - !ruby/object:Gem::Version
26
+ version: 4.11.0
27
+ - !ruby/object:Gem::Dependency
28
+ name: cutest
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ~>
32
+ - !ruby/object:Gem::Version
33
+ version: 1.2.1
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ~>
39
+ - !ruby/object:Gem::Version
40
+ version: 1.2.1
41
+ description: Slim postgres models
42
+ email:
43
+ - yo@brunoaguirre.com
44
+ executables: []
45
+ extensions: []
46
+ extra_rdoc_files: []
47
+ files:
48
+ - .gems
49
+ - HUGS
50
+ - LICENSE
51
+ - README.md
52
+ - Rakefile
53
+ - lib/shoden.rb
54
+ - shoden.gemspec
55
+ - test/shoden_test.rb
56
+ homepage: http://github.com/elcuervo/shoden
57
+ licenses:
58
+ - MIT
59
+ - HUGWARE
60
+ metadata: {}
61
+ post_install_message:
62
+ rdoc_options: []
63
+ require_paths:
64
+ - lib
65
+ required_ruby_version: !ruby/object:Gem::Requirement
66
+ requirements:
67
+ - - '>='
68
+ - !ruby/object:Gem::Version
69
+ version: '0'
70
+ required_rubygems_version: !ruby/object:Gem::Requirement
71
+ requirements:
72
+ - - '>='
73
+ - !ruby/object:Gem::Version
74
+ version: '0'
75
+ requirements: []
76
+ rubyforge_project:
77
+ rubygems_version: 2.0.14
78
+ signing_key:
79
+ specification_version: 4
80
+ summary: Object hash mapper for postgres
81
+ test_files:
82
+ - test/shoden_test.rb
83
+ has_rdoc: