rmodel 0.4.0.dev → 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (75) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +1 -0
  3. data/.rubocop.yml +4 -0
  4. data/.travis.yml +4 -3
  5. data/README.md +119 -153
  6. data/Rakefile +1 -2
  7. data/examples/mongo_embedded.rb +27 -21
  8. data/examples/scopes.rb +28 -0
  9. data/examples/sql_repository.rb +14 -26
  10. data/examples/timestamps.rb +7 -10
  11. data/examples/webapp/models/task.rb +9 -0
  12. data/examples/webapp/repositories/task_repository.rb +14 -0
  13. data/examples/webapp/server.rb +25 -0
  14. data/examples/webapp/support/mappers.rb +11 -0
  15. data/examples/webapp/support/repositories.rb +12 -0
  16. data/examples/webapp/support/sources.rb +13 -0
  17. data/examples/webapp/views/index.erb +20 -0
  18. data/lib/rmodel.rb +11 -8
  19. data/lib/rmodel/array_mapper.rb +23 -0
  20. data/lib/rmodel/base_mapper.rb +56 -0
  21. data/lib/rmodel/dummy_mapper.rb +15 -0
  22. data/lib/rmodel/mongo/mapper.rb +11 -0
  23. data/lib/rmodel/mongo/source.rb +50 -0
  24. data/lib/rmodel/repository.rb +36 -0
  25. data/lib/rmodel/repository_ext/scopable.rb +44 -0
  26. data/lib/rmodel/repository_ext/sugarable.rb +35 -0
  27. data/lib/rmodel/repository_ext/timestampable.rb +29 -0
  28. data/lib/rmodel/scope.rb +31 -0
  29. data/lib/rmodel/sequel/mapper.rb +6 -0
  30. data/lib/rmodel/sequel/source.rb +43 -0
  31. data/lib/rmodel/uni_hash.rb +16 -0
  32. data/lib/rmodel/version.rb +1 -1
  33. data/rmodel.gemspec +9 -3
  34. data/spec/rmodel/array_mapper_spec.rb +43 -0
  35. data/spec/rmodel/mongo/mapper_spec.rb +154 -0
  36. data/spec/rmodel/mongo/repository_spec.rb +16 -37
  37. data/spec/rmodel/mongo/source_spec.rb +113 -0
  38. data/spec/rmodel/sequel/mapper_spec.rb +57 -0
  39. data/spec/rmodel/sequel/repository_spec.rb +27 -38
  40. data/spec/rmodel/sequel/source_spec.rb +121 -0
  41. data/spec/shared/base_mapper.rb +39 -0
  42. data/spec/shared/clean_moped.rb +6 -2
  43. data/spec/shared/clean_sequel.rb +1 -1
  44. data/spec/shared/{repository_ext → repository}/crud.rb +20 -14
  45. data/spec/shared/repository/initialization.rb +39 -0
  46. data/spec/shared/repository/scopable.rb +137 -0
  47. data/spec/shared/repository/sugarable.rb +67 -0
  48. data/spec/shared/repository/timestampable.rb +137 -0
  49. data/spec/spec_helper.rb +17 -18
  50. metadata +120 -54
  51. data/examples/advanced_creation_of_repository.rb +0 -15
  52. data/examples/user.rb +0 -48
  53. data/lib/rmodel/base/repository.rb +0 -12
  54. data/lib/rmodel/base/repository_ext/sugarable.rb +0 -17
  55. data/lib/rmodel/base/repository_ext/timestampable.rb +0 -19
  56. data/lib/rmodel/mongo/repository.rb +0 -62
  57. data/lib/rmodel/mongo/repository_ext/query.rb +0 -34
  58. data/lib/rmodel/mongo/repository_ext/queryable.rb +0 -34
  59. data/lib/rmodel/mongo/setup.rb +0 -17
  60. data/lib/rmodel/mongo/simple_factory.rb +0 -78
  61. data/lib/rmodel/sequel/repository.rb +0 -61
  62. data/lib/rmodel/sequel/repository_ext/query.rb +0 -34
  63. data/lib/rmodel/sequel/repository_ext/queryable.rb +0 -30
  64. data/lib/rmodel/sequel/setup.rb +0 -12
  65. data/lib/rmodel/sequel/simple_factory.rb +0 -28
  66. data/lib/rmodel/setup.rb +0 -34
  67. data/spec/rmodel/mongo/repository_ext/queryable_spec.rb +0 -103
  68. data/spec/rmodel/mongo/repository_initialize_spec.rb +0 -174
  69. data/spec/rmodel/mongo/simple_factory_spec.rb +0 -195
  70. data/spec/rmodel/sequel/repository_ext/queryable_spec.rb +0 -114
  71. data/spec/rmodel/sequel/repository_initialize_spec.rb +0 -118
  72. data/spec/rmodel/sequel/simple_factory_spec.rb +0 -55
  73. data/spec/rmodel/setup_spec.rb +0 -54
  74. data/spec/shared/repository_ext/sugarable.rb +0 -44
  75. data/spec/shared/repository_ext/timestampable.rb +0 -67
@@ -1,19 +0,0 @@
1
- module Rmodel::Base
2
- module RepositoryExt
3
- module Timestampable
4
- def insert(object)
5
- if object.respond_to?(:created_at) && object.respond_to?(:created_at=)
6
- object.created_at ||= Time.now
7
- end
8
- super
9
- end
10
-
11
- def update(object)
12
- if object.respond_to?(:updated_at) && object.respond_to?(:updated_at=)
13
- object.updated_at = Time.now
14
- end
15
- super
16
- end
17
- end
18
- end
19
- end
@@ -1,62 +0,0 @@
1
- require 'mongo'
2
- require 'rmodel/base/repository'
3
- require 'active_support/inflector'
4
- require 'rmodel/mongo/repository_ext/queryable'
5
-
6
- module Rmodel::Mongo
7
- class Repository < Rmodel::Base::Repository
8
- include RepositoryExt::Queryable
9
-
10
- def initialize(client = nil, collection = nil, factory = nil)
11
- @client = client || Rmodel.setup.establish_mongo_client(self.class.client_name || :default) or
12
- raise ArgumentError.new('Client driver is not setup')
13
-
14
- @collection = collection || self.class.setting_collection ||
15
- self.class.collection_by_convention or
16
- raise ArgumentError.new('Collection can not be guessed')
17
-
18
- @factory = factory || self.class.setting_factory or
19
- raise ArgumentError.new('Factory can not be guessed')
20
- end
21
-
22
- def find(id)
23
- result = @client[@collection].find(_id: id).first
24
- result && @factory.fromHash(result)
25
- end
26
-
27
- def insert(object)
28
- object.id ||= BSON::ObjectId.new
29
- @client[@collection].insert_one(@factory.toHash(object, true))
30
- end
31
-
32
- def update(object)
33
- @client[@collection].find(_id: object.id).update_one(@factory.toHash(object, false))
34
- end
35
-
36
- def remove(object)
37
- @client[@collection].find(_id: object.id).delete_one
38
- end
39
-
40
- class << self
41
- attr_reader :client_name, :setting_collection, :setting_factory
42
-
43
- def client(name)
44
- @client_name = name
45
- end
46
-
47
- def collection(name)
48
- @setting_collection = name
49
- end
50
-
51
- def collection_by_convention
52
- if name =~ /(.*)Repository$/
53
- ActiveSupport::Inflector.tableize($1).to_sym
54
- end
55
- end
56
-
57
- def simple_factory(klass, *attributes, &block)
58
- @setting_factory = SimpleFactory.new(klass, *attributes, &block)
59
- end
60
- end
61
- end
62
- end
@@ -1,34 +0,0 @@
1
- require 'origin'
2
-
3
- module Rmodel::Mongo
4
- module RepositoryExt
5
- class Query
6
- include Enumerable
7
-
8
- class Queryable
9
- include Origin::Queryable
10
- end
11
-
12
- def initialize(repo, queryable = nil)
13
- @repo = repo
14
- @queryable = queryable || Queryable.new
15
- end
16
-
17
- def each(&block)
18
- @repo.find_by_query(@queryable.selector, @queryable.options).each(&block)
19
- self
20
- end
21
-
22
- def remove
23
- @repo.execute_query(@queryable.selector, @queryable.options).delete_many
24
- end
25
-
26
- def self.define_scope(name, &block)
27
- define_method name do |*args|
28
- new_queryable = @queryable.instance_exec(*args, &block)
29
- self.class.new(@repo, new_queryable)
30
- end
31
- end
32
- end
33
- end
34
- end
@@ -1,34 +0,0 @@
1
- require 'rmodel/mongo/repository_ext/query'
2
-
3
- module Rmodel::Mongo
4
- module RepositoryExt
5
- module Queryable
6
- def self.included(base)
7
- base.extend ClassMethods
8
- end
9
-
10
- def query
11
- (self.class.query_klass ||= Class.new(Query)).new(self)
12
- end
13
-
14
- def find_by_query(selector, options)
15
- execute_query(selector, options).map do |hash|
16
- @factory.fromHash(hash)
17
- end
18
- end
19
-
20
- def execute_query(selector, options)
21
- @client[@collection].find(selector, options)
22
- end
23
-
24
- module ClassMethods
25
- attr_accessor :query_klass
26
-
27
- def scope(name, &block)
28
- self.query_klass ||= Class.new(Query)
29
- self.query_klass.define_scope(name, &block)
30
- end
31
- end
32
- end
33
- end
34
- end
@@ -1,17 +0,0 @@
1
- module Rmodel::Mongo
2
- module Setup
3
- def establish_mongo_client(name)
4
- config = @clients_config[name]
5
- if config
6
- options = config.dup
7
- options.delete :hosts
8
-
9
- establish_client(name) { Mongo::Client.new(config[:hosts], options) }
10
- end
11
- end
12
- end
13
- end
14
-
15
- class Rmodel::Setup
16
- include Rmodel::Mongo::Setup
17
- end
@@ -1,78 +0,0 @@
1
- module Rmodel::Mongo
2
- class SimpleFactory
3
- def initialize(klass, *attributes, &block)
4
- @klass = klass
5
- @attributes = attributes
6
- @embeds_many = {}
7
- @embeds_one = {}
8
- instance_eval(&block) if block
9
- end
10
-
11
- def fromHash(hash)
12
- object = @klass.new
13
- object.id = hash['_id']
14
- @attributes.each do |attribute|
15
- object.public_send "#{attribute}=", hash[attribute.to_s]
16
- end
17
- @embeds_many.each do |attribute, factory|
18
- if hash[attribute.to_s]
19
- object.public_send "#{attribute}=", []
20
- hash[attribute.to_s].each do |sub_hash|
21
- object.public_send(attribute) << factory.fromHash(sub_hash)
22
- end
23
- end
24
- end
25
- @embeds_one.each do |attribute, factory|
26
- sub_hash = hash[attribute.to_s]
27
- if sub_hash
28
- object.public_send "#{attribute}=", factory.fromHash(sub_hash)
29
- end
30
- end
31
- object
32
- end
33
-
34
- def toHash(object, id_included)
35
- hash = {}
36
- @attributes.each do |attribute|
37
- hash[attribute.to_s] = object.public_send(attribute)
38
- end
39
- if id_included
40
- hash['_id'] = object.id
41
- end
42
- @embeds_many.each do |attribute, factory|
43
- hash[attribute.to_s] = []
44
- sub_objects = object.public_send(attribute)
45
- if sub_objects
46
- sub_objects.each do |sub_object|
47
- sub_object.id ||= BSON::ObjectId.new
48
- hash[attribute.to_s] << factory.toHash(sub_object, true)
49
- end
50
- end
51
- end
52
- @embeds_one.each do |attribute, factory|
53
- sub_object = object.public_send(attribute)
54
- if sub_object
55
- sub_object.id ||= BSON::ObjectId.new
56
- hash[attribute.to_s] = factory.toHash(sub_object, true)
57
- end
58
- end
59
- hash
60
- end
61
-
62
- private
63
-
64
- def embeds_many(attribute, factory, &block)
65
- factory.instance_eval(&block) if block
66
- @embeds_many[attribute.to_sym] = factory
67
- end
68
-
69
- def embeds_one(attribute, factory, &block)
70
- factory.instance_eval(&block) if block
71
- @embeds_one[attribute.to_sym] = factory
72
- end
73
-
74
- def simple_factory(klass, *attributes, &block)
75
- self.class.new(klass, *attributes, &block)
76
- end
77
- end
78
- end
@@ -1,61 +0,0 @@
1
- require 'sequel'
2
- require 'rmodel/base/repository'
3
- require 'rmodel/sequel/repository_ext/queryable'
4
-
5
- module Rmodel::Sequel
6
- class Repository < Rmodel::Base::Repository
7
- include RepositoryExt::Queryable
8
-
9
- def initialize(client = nil, table = nil, factory = nil)
10
- @client = client || Rmodel.setup.establish_sequel_client(self.class.client_name || :default) or
11
- raise ArgumentError.new('Client driver is not setup')
12
-
13
- @table = table || self.class.setting_table ||
14
- self.class.table_by_convention or
15
- raise ArgumentError.new('Table can not be guessed')
16
-
17
- @factory = factory || self.class.setting_factory or
18
- raise ArgumentError.new('Factory can not be guessed')
19
- end
20
-
21
- def find(id)
22
- result = @client[@table].where(id: id).first
23
- result && @factory.fromHash(result)
24
- end
25
-
26
- def insert(object)
27
- id = @client[@table].insert(@factory.toHash(object, true))
28
- object.id ||= id
29
- end
30
-
31
- def update(object)
32
- @client[@table].where(id: object.id).update(@factory.toHash(object, false))
33
- end
34
-
35
- def remove(object)
36
- @client[@table].where(id: object.id).delete
37
- end
38
-
39
- class << self
40
- attr_reader :client_name, :setting_table, :setting_factory
41
-
42
- def client(name)
43
- @client_name = name
44
- end
45
-
46
- def table(name)
47
- @setting_table = name
48
- end
49
-
50
- def table_by_convention
51
- if name =~ /(.*)Repository$/
52
- ActiveSupport::Inflector.tableize($1).to_sym
53
- end
54
- end
55
-
56
- def simple_factory(klass, *attributes)
57
- @setting_factory = SimpleFactory.new(klass, *attributes)
58
- end
59
- end
60
- end
61
- end
@@ -1,34 +0,0 @@
1
- require 'origin'
2
-
3
- module Rmodel::Sequel
4
- module RepositoryExt
5
- class Query
6
- include Enumerable
7
-
8
- def initialize(repo, dataset)
9
- @repo = repo
10
- @dataset = dataset
11
- end
12
-
13
- def each(&block)
14
- @repo.find_by_query(@dataset).each(&block)
15
- self
16
- end
17
-
18
- def remove
19
- @dataset.delete
20
- end
21
-
22
- def to_sql
23
- @dataset.sql
24
- end
25
-
26
- def self.define_scope(name, &block)
27
- define_method name do |*args|
28
- new_dataset = @dataset.instance_exec(*args, &block)
29
- self.class.new(@repo, new_dataset)
30
- end
31
- end
32
- end
33
- end
34
- end
@@ -1,30 +0,0 @@
1
- require 'rmodel/sequel/repository_ext/query'
2
-
3
- module Rmodel::Sequel
4
- module RepositoryExt
5
- module Queryable
6
- def self.included(base)
7
- base.extend ClassMethods
8
- end
9
-
10
- def query
11
- (self.class.query_klass ||= Class.new(Query)).new(self, @client[@table])
12
- end
13
-
14
- def find_by_query(dataset)
15
- dataset.map do |hash|
16
- @factory.fromHash(hash)
17
- end
18
- end
19
-
20
- module ClassMethods
21
- attr_accessor :query_klass
22
-
23
- def scope(name, &block)
24
- self.query_klass ||= Class.new(Query)
25
- self.query_klass.define_scope(name, &block)
26
- end
27
- end
28
- end
29
- end
30
- end
@@ -1,12 +0,0 @@
1
- module Rmodel::Sequel
2
- module Setup
3
- def establish_sequel_client(name)
4
- config = @clients_config[name]
5
- config && establish_client(name) { Sequel.connect(config) }
6
- end
7
- end
8
- end
9
-
10
- class Rmodel::Setup
11
- include Rmodel::Sequel::Setup
12
- end
@@ -1,28 +0,0 @@
1
- module Rmodel::Sequel
2
- class SimpleFactory
3
- def initialize(klass, *attributes)
4
- @klass = klass
5
- @attributes = attributes
6
- end
7
-
8
- def fromHash(hash)
9
- object = @klass.new
10
- object.id = hash[:id]
11
- @attributes.each do |attribute|
12
- object.public_send "#{attribute}=", hash[attribute.to_sym]
13
- end
14
- object
15
- end
16
-
17
- def toHash(object, id_included)
18
- hash = {}
19
- @attributes.each do |attribute|
20
- hash[attribute.to_sym] = object.public_send(attribute)
21
- end
22
- if id_included
23
- hash[:id] = object.id
24
- end
25
- hash
26
- end
27
- end
28
- end
data/lib/rmodel/setup.rb DELETED
@@ -1,34 +0,0 @@
1
- require 'singleton'
2
-
3
- module Rmodel
4
- class Setup
5
- include Singleton
6
-
7
- def initialize
8
- @clients_config = {}
9
- @established_clients = {}
10
- end
11
-
12
- def client(name, config)
13
- @clients_config[name] = config
14
- end
15
-
16
- def clear
17
- @clients_config.clear
18
- @established_clients.clear
19
- end
20
-
21
- private
22
-
23
- def establish_client(name)
24
- @established_clients[name] ||= yield
25
- end
26
- end
27
-
28
- def self.setup(&block)
29
- if block
30
- Setup.instance.instance_eval &block
31
- end
32
- Setup.instance
33
- end
34
- end