shoden 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
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: