rmodel 0.4.0.dev → 1.0.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 (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