baza_models 0.0.0 → 0.0.1

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 (71) hide show
  1. checksums.yaml +4 -4
  2. data/.rubocop_todo.yml +35 -0
  3. data/Gemfile +9 -3
  4. data/Gemfile.lock +90 -51
  5. data/README.md +98 -3
  6. data/Rakefile +20 -17
  7. data/VERSION +1 -1
  8. data/baza_models.gemspec +149 -0
  9. data/config/best_project_practice_rubocop.yml +2 -0
  10. data/config/best_project_practice_rubocop_todo.yml +35 -0
  11. data/lib/baza_models.rb +15 -0
  12. data/lib/baza_models/autoloader.rb +135 -0
  13. data/lib/baza_models/baza_orm_adapter.rb +39 -0
  14. data/lib/baza_models/can_can_adapter.rb +9 -0
  15. data/lib/baza_models/class_translation.rb +44 -0
  16. data/lib/baza_models/errors.rb +24 -2
  17. data/lib/baza_models/model.rb +236 -115
  18. data/lib/baza_models/model/belongs_to_relations.rb +49 -0
  19. data/lib/baza_models/model/custom_validations.rb +24 -0
  20. data/lib/baza_models/model/delegation.rb +21 -0
  21. data/lib/baza_models/model/has_many_relations.rb +85 -0
  22. data/lib/baza_models/model/has_one_relations.rb +93 -0
  23. data/lib/baza_models/model/manipulation.rb +123 -0
  24. data/lib/baza_models/model/queries.rb +45 -0
  25. data/lib/baza_models/model/scopes.rb +19 -0
  26. data/lib/baza_models/model/translation_functionality.rb +30 -0
  27. data/lib/baza_models/model/validations.rb +95 -0
  28. data/lib/baza_models/query.rb +447 -0
  29. data/lib/baza_models/query/inspector.rb +74 -0
  30. data/lib/baza_models/query/not.rb +34 -0
  31. data/lib/baza_models/ransacker.rb +30 -0
  32. data/lib/baza_models/test_database_cleaner.rb +23 -0
  33. data/lib/baza_models/validators/base_validator.rb +14 -0
  34. data/lib/baza_models/validators/confirmation_validator.rb +12 -0
  35. data/lib/baza_models/validators/format_validator.rb +11 -0
  36. data/lib/baza_models/validators/length_validator.rb +16 -0
  37. data/lib/baza_models/validators/uniqueness_validator.rb +21 -0
  38. data/shippable.yml +3 -1
  39. data/spec/baza_models/autoloader_spec.rb +57 -0
  40. data/spec/baza_models/baza_orm_adapter_spec.rb +52 -0
  41. data/spec/baza_models/class_translation_spec.rb +25 -0
  42. data/spec/baza_models/factory_girl_spec.rb +13 -0
  43. data/spec/baza_models/model/belongs_to_relations_spec.rb +26 -0
  44. data/spec/baza_models/model/custom_validations_spec.rb +18 -0
  45. data/spec/baza_models/model/delgation_spec.rb +16 -0
  46. data/spec/baza_models/model/has_many_relations_spec.rb +68 -0
  47. data/spec/baza_models/model/has_one_relations_spec.rb +35 -0
  48. data/spec/baza_models/model/manipulation_spec.rb +25 -0
  49. data/spec/baza_models/model/queries_spec.rb +59 -0
  50. data/spec/baza_models/model/scopes_spec.rb +23 -0
  51. data/spec/baza_models/model/translate_functionality_spec.rb +13 -0
  52. data/spec/baza_models/model/validations_spec.rb +52 -0
  53. data/spec/baza_models/model_spec.rb +75 -98
  54. data/spec/baza_models/query/not_spec.rb +16 -0
  55. data/spec/baza_models/query_spec.rb +155 -0
  56. data/spec/baza_models/ransacker_spec.rb +15 -0
  57. data/spec/baza_models/validators/confirmation_validator_spec.rb +28 -0
  58. data/spec/baza_models/validators/format_validator_spec.rb +17 -0
  59. data/spec/baza_models/validators/length_validator_spec.rb +19 -0
  60. data/spec/baza_models/validators/uniqueness_validator_spec.rb +24 -0
  61. data/spec/factories/organization.rb +5 -0
  62. data/spec/factories/user.rb +7 -0
  63. data/spec/spec_helper.rb +17 -5
  64. data/spec/support/database_helper.rb +87 -0
  65. data/spec/test_classes/organization.rb +3 -0
  66. data/spec/test_classes/person.rb +3 -0
  67. data/spec/test_classes/role.rb +12 -0
  68. data/spec/test_classes/user.rb +40 -0
  69. data/spec/test_classes/user_passport.rb +3 -0
  70. metadata +146 -7
  71. data/spec/test_classes/user_test.rb +0 -17
@@ -0,0 +1,149 @@
1
+ # Generated by jeweler
2
+ # DO NOT EDIT THIS FILE DIRECTLY
3
+ # Instead, edit Jeweler::Tasks in Rakefile, and run 'rake gemspec'
4
+ # -*- encoding: utf-8 -*-
5
+ # stub: baza_models 0.0.1 ruby lib
6
+
7
+ Gem::Specification.new do |s|
8
+ s.name = "baza_models"
9
+ s.version = "0.0.1"
10
+
11
+ s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
12
+ s.require_paths = ["lib"]
13
+ s.authors = ["kaspernj"]
14
+ s.date = "2015-12-30"
15
+ s.description = "ActiveRecord like models for the Baza database framework"
16
+ s.email = "k@spernj.org"
17
+ s.extra_rdoc_files = [
18
+ "LICENSE.txt",
19
+ "README.md"
20
+ ]
21
+ s.files = [
22
+ ".document",
23
+ ".rspec",
24
+ ".rubocop_todo.yml",
25
+ "Gemfile",
26
+ "Gemfile.lock",
27
+ "LICENSE.txt",
28
+ "README.md",
29
+ "Rakefile",
30
+ "VERSION",
31
+ "baza_models.gemspec",
32
+ "config/best_project_practice_rubocop.yml",
33
+ "config/best_project_practice_rubocop_todo.yml",
34
+ "lib/baza_models.rb",
35
+ "lib/baza_models/autoloader.rb",
36
+ "lib/baza_models/baza_orm_adapter.rb",
37
+ "lib/baza_models/can_can_adapter.rb",
38
+ "lib/baza_models/class_translation.rb",
39
+ "lib/baza_models/errors.rb",
40
+ "lib/baza_models/model.rb",
41
+ "lib/baza_models/model/belongs_to_relations.rb",
42
+ "lib/baza_models/model/custom_validations.rb",
43
+ "lib/baza_models/model/delegation.rb",
44
+ "lib/baza_models/model/has_many_relations.rb",
45
+ "lib/baza_models/model/has_one_relations.rb",
46
+ "lib/baza_models/model/manipulation.rb",
47
+ "lib/baza_models/model/queries.rb",
48
+ "lib/baza_models/model/scopes.rb",
49
+ "lib/baza_models/model/translation_functionality.rb",
50
+ "lib/baza_models/model/validations.rb",
51
+ "lib/baza_models/query.rb",
52
+ "lib/baza_models/query/inspector.rb",
53
+ "lib/baza_models/query/not.rb",
54
+ "lib/baza_models/ransacker.rb",
55
+ "lib/baza_models/test_database_cleaner.rb",
56
+ "lib/baza_models/validators/base_validator.rb",
57
+ "lib/baza_models/validators/confirmation_validator.rb",
58
+ "lib/baza_models/validators/format_validator.rb",
59
+ "lib/baza_models/validators/length_validator.rb",
60
+ "lib/baza_models/validators/presence_validator.rb",
61
+ "lib/baza_models/validators/uniqueness_validator.rb",
62
+ "shippable.yml",
63
+ "spec/baza_models/autoloader_spec.rb",
64
+ "spec/baza_models/baza_orm_adapter_spec.rb",
65
+ "spec/baza_models/class_translation_spec.rb",
66
+ "spec/baza_models/factory_girl_spec.rb",
67
+ "spec/baza_models/model/belongs_to_relations_spec.rb",
68
+ "spec/baza_models/model/custom_validations_spec.rb",
69
+ "spec/baza_models/model/delgation_spec.rb",
70
+ "spec/baza_models/model/has_many_relations_spec.rb",
71
+ "spec/baza_models/model/has_one_relations_spec.rb",
72
+ "spec/baza_models/model/manipulation_spec.rb",
73
+ "spec/baza_models/model/queries_spec.rb",
74
+ "spec/baza_models/model/scopes_spec.rb",
75
+ "spec/baza_models/model/translate_functionality_spec.rb",
76
+ "spec/baza_models/model/validations_spec.rb",
77
+ "spec/baza_models/model_spec.rb",
78
+ "spec/baza_models/query/not_spec.rb",
79
+ "spec/baza_models/query_spec.rb",
80
+ "spec/baza_models/ransacker_spec.rb",
81
+ "spec/baza_models/validators/confirmation_validator_spec.rb",
82
+ "spec/baza_models/validators/format_validator_spec.rb",
83
+ "spec/baza_models/validators/length_validator_spec.rb",
84
+ "spec/baza_models/validators/uniqueness_validator_spec.rb",
85
+ "spec/baza_models_spec.rb",
86
+ "spec/factories/organization.rb",
87
+ "spec/factories/user.rb",
88
+ "spec/spec_helper.rb",
89
+ "spec/support/database_helper.rb",
90
+ "spec/test_classes/organization.rb",
91
+ "spec/test_classes/person.rb",
92
+ "spec/test_classes/role.rb",
93
+ "spec/test_classes/user.rb",
94
+ "spec/test_classes/user_passport.rb"
95
+ ]
96
+ s.homepage = "http://github.com/kaspernj/baza_models"
97
+ s.licenses = ["MIT"]
98
+ s.rubygems_version = "2.4.0"
99
+ s.summary = "ActiveRecord like models for the Baza database framework"
100
+
101
+ if s.respond_to? :specification_version then
102
+ s.specification_version = 4
103
+
104
+ if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
105
+ s.add_runtime_dependency(%q<array_enumerator>, [">= 0"])
106
+ s.add_runtime_dependency(%q<baza>, ["~> 0.0.20"])
107
+ s.add_runtime_dependency(%q<string-cases>, [">= 0"])
108
+ s.add_development_dependency(%q<rspec>, ["~> 3.3.0"])
109
+ s.add_development_dependency(%q<rdoc>, ["~> 3.12"])
110
+ s.add_development_dependency(%q<bundler>, ["~> 1.0"])
111
+ s.add_development_dependency(%q<jeweler>, ["~> 2.0.1"])
112
+ s.add_development_dependency(%q<factory_girl>, [">= 0"])
113
+ s.add_development_dependency(%q<sqlite3>, [">= 0"])
114
+ s.add_development_dependency(%q<jdbc-sqlite3>, [">= 0"])
115
+ s.add_development_dependency(%q<best_practice_project>, [">= 0"])
116
+ s.add_development_dependency(%q<rubocop>, [">= 0"])
117
+ s.add_development_dependency(%q<orm_adapter>, [">= 0"])
118
+ else
119
+ s.add_dependency(%q<array_enumerator>, [">= 0"])
120
+ s.add_dependency(%q<baza>, ["~> 0.0.20"])
121
+ s.add_dependency(%q<string-cases>, [">= 0"])
122
+ s.add_dependency(%q<rspec>, ["~> 3.3.0"])
123
+ s.add_dependency(%q<rdoc>, ["~> 3.12"])
124
+ s.add_dependency(%q<bundler>, ["~> 1.0"])
125
+ s.add_dependency(%q<jeweler>, ["~> 2.0.1"])
126
+ s.add_dependency(%q<factory_girl>, [">= 0"])
127
+ s.add_dependency(%q<sqlite3>, [">= 0"])
128
+ s.add_dependency(%q<jdbc-sqlite3>, [">= 0"])
129
+ s.add_dependency(%q<best_practice_project>, [">= 0"])
130
+ s.add_dependency(%q<rubocop>, [">= 0"])
131
+ s.add_dependency(%q<orm_adapter>, [">= 0"])
132
+ end
133
+ else
134
+ s.add_dependency(%q<array_enumerator>, [">= 0"])
135
+ s.add_dependency(%q<baza>, ["~> 0.0.20"])
136
+ s.add_dependency(%q<string-cases>, [">= 0"])
137
+ s.add_dependency(%q<rspec>, ["~> 3.3.0"])
138
+ s.add_dependency(%q<rdoc>, ["~> 3.12"])
139
+ s.add_dependency(%q<bundler>, ["~> 1.0"])
140
+ s.add_dependency(%q<jeweler>, ["~> 2.0.1"])
141
+ s.add_dependency(%q<factory_girl>, [">= 0"])
142
+ s.add_dependency(%q<sqlite3>, [">= 0"])
143
+ s.add_dependency(%q<jdbc-sqlite3>, [">= 0"])
144
+ s.add_dependency(%q<best_practice_project>, [">= 0"])
145
+ s.add_dependency(%q<rubocop>, [">= 0"])
146
+ s.add_dependency(%q<orm_adapter>, [">= 0"])
147
+ end
148
+ end
149
+
@@ -0,0 +1,2 @@
1
+ ---
2
+ inherit_from: best_project_practice_rubocop_todo.yml
@@ -0,0 +1,35 @@
1
+
2
+
3
+
4
+
5
+
6
+
7
+ # This configuration was generated by
8
+ # `rubocop --auto-gen-config`
9
+ # on 2015-12-20 19:19:55 +0100 using RuboCop version 0.35.1.
10
+ # The point is for the user to remove these configuration records
11
+ # one by one as the offenses are removed from the code base.
12
+ # Note that changes in the inspected code, or installation of new
13
+ # versions of RuboCop, may require this file to be generated again.
14
+
15
+ # Offense count: 6
16
+ Metrics/AbcSize:
17
+ Max: 41
18
+
19
+ # Offense count: 1
20
+ # Configuration parameters: CountComments.
21
+ Metrics/ClassLength:
22
+ Max: 400
23
+
24
+ # Offense count: 5
25
+ Metrics/CyclomaticComplexity:
26
+ Max: 15
27
+
28
+ # Offense count: 2
29
+ # Configuration parameters: CountComments.
30
+ Metrics/MethodLength:
31
+ Max: 77
32
+
33
+ # Offense count: 6
34
+ Metrics/PerceivedComplexity:
35
+ Max: 21
data/lib/baza_models.rb CHANGED
@@ -1,17 +1,32 @@
1
1
  class BazaModels
2
2
  path = "#{File.realpath(File.dirname(__FILE__))}/baza_models"
3
3
 
4
+ autoload :Autoloader, "#{path}/autoloader"
5
+ autoload :BazaOrmAdapter, "#{path}/baza_orm_adapter"
6
+ autoload :CanCanAdapter, "#{path}/can_can_adapter"
7
+ autoload :ClassTranslation, "#{path}/class_translation"
4
8
  autoload :Errors, "#{path}/errors"
5
9
  autoload :Model, "#{path}/model"
10
+ autoload :Ransacker, "#{path}/ransacker"
11
+ autoload :Query, "#{path}/query"
12
+ autoload :TestDatabaseCleaner, "#{path}/test_database_cleaner"
6
13
 
7
14
  class << self
8
15
  attr_accessor :primary_db
16
+
17
+ def load_can_can
18
+ BazaModels::CanCanAdapter # Loading the model will make CanCan aware because of inherited hook CanCan implements
19
+ end
9
20
  end
10
21
 
11
22
  class Validators
12
23
  path = "#{File.realpath(File.dirname(__FILE__))}/baza_models/validators"
13
24
 
14
25
  autoload :BaseValidator, "#{path}/base_validator"
26
+ autoload :ConfirmationValidator, "#{path}/confirmation_validator"
27
+ autoload :FormatValidator, "#{path}/format_validator"
28
+ autoload :LengthValidator, "#{path}/length_validator"
15
29
  autoload :PresenceValidator, "#{path}/presence_validator"
30
+ autoload :UniquenessValidator, "#{path}/uniqueness_validator"
16
31
  end
17
32
  end
@@ -0,0 +1,135 @@
1
+ class BazaModels::Autoloader
2
+ def initialize(args)
3
+ @models = args.fetch(:models)
4
+ @model_class = @models.first.class
5
+ @autoloads = args.fetch(:autoloads)
6
+ @db = args.fetch(:db)
7
+ @debug = args[:debug]
8
+
9
+ debug "Autoloading #{@autoloads} on #{@model_class.name} with ID's: #{@models.map(&:id)}" if @debug
10
+ end
11
+
12
+ def autoload
13
+ autoload_argument(@autoloads)
14
+ end
15
+
16
+ private
17
+
18
+ def debug(msg)
19
+ print "#{msg}\n" if @debug
20
+ end
21
+
22
+ def model_ids
23
+ @model_ids ||= @models.map(&:id)
24
+ end
25
+
26
+ def autoload_argument(autoload)
27
+ if autoload.is_a?(Hash)
28
+ autoload_hash(autoload)
29
+ elsif autoload.is_a?(Array)
30
+ autoload_array(autoload)
31
+ elsif autoload.is_a?(Symbol)
32
+ autoload_symbol(autoload)
33
+ else
34
+ raise "Didn't know what to do with autoload: #{autoload} (#{autoload.class.name})"
35
+ end
36
+ end
37
+
38
+ def autoload_array(autoload)
39
+ autoload.each do |autoload_i|
40
+ autoload_argument(autoload_i)
41
+ end
42
+ end
43
+
44
+ def autoload_hash(autoload)
45
+ autoload.each do |autoload_key, autoload_value|
46
+ result = autoload_symbol(autoload_key)
47
+ next if result.fetch(:models).empty?
48
+
49
+ autoloader = BazaModels::Autoloader.new(
50
+ models: result.fetch(:models),
51
+ autoloads: autoload_value,
52
+ db: @db,
53
+ debug: @debug
54
+ )
55
+ autoloader.autoload
56
+ end
57
+ end
58
+
59
+ def autoload_symbol(autoload)
60
+ relation = @model_class.relationships.fetch(autoload)
61
+
62
+ if relation.fetch(:type) == :has_many
63
+ autoload_has_many(autoload, relation)
64
+ elsif relation.fetch(:type) == :belongs_to
65
+ autoload_belongs_to(autoload, relation)
66
+ elsif relation.fetch(:type) == :has_one
67
+ autoload_has_one(autoload, relation)
68
+ else
69
+ raise "Unknown relation type: #{relation.fetch(:type)}"
70
+ end
71
+ end
72
+
73
+ def autoload_belongs_to(autoload_name, relation)
74
+ result = {models: []}
75
+
76
+ model_id_mappings = {}
77
+ model_ids = []
78
+
79
+ @models.each do |model|
80
+ key = model.data.fetch(relation.fetch(:foreign_key))
81
+ next if model_id_mappings.key?(key)
82
+
83
+ model_ids << key
84
+ model_id_mappings[key] = model.id
85
+ end
86
+
87
+ @db.select(relation.fetch(:table_name), id: model_ids) do |model_data|
88
+ model = ::Object.const_get(relation.fetch(:class_name)).new(model_data)
89
+
90
+ orig_model_id = model_id_mappings.fetch(model_data.fetch(:id))
91
+ orig_model = @models.detect { |array_model| array_model.id == orig_model_id }
92
+ orig_model.autoloads[autoload_name] ||= model
93
+
94
+ result.fetch(:models) << model
95
+ end
96
+
97
+ result
98
+ end
99
+
100
+ def autoload_has_many(autoload_name, relation)
101
+ result = {models: []}
102
+
103
+ @db.select(relation.fetch(:table_name), relation.fetch(:foreign_key) => model_ids) do |model_data|
104
+ model = ::Object.const_get(relation.fetch(:class_name)).new(model_data)
105
+
106
+ orig_model_id = model_data.fetch(relation.fetch(:foreign_key))
107
+ orig_model = @models.detect { |array_model| array_model.id == orig_model_id }
108
+
109
+ orig_model.autoloads[autoload_name] ||= []
110
+ orig_model.autoloads[autoload_name] << model
111
+
112
+ result.fetch(:models) << model
113
+ end
114
+
115
+ result
116
+ end
117
+
118
+ def autoload_has_one(autoload_name, relation)
119
+ result = {models: []}
120
+
121
+ @db.select(relation.fetch(:table_name), relation.fetch(:foreign_key) => model_ids) do |model_data|
122
+ model = ::Object.const_get(relation.fetch(:class_name)).new(model_data)
123
+
124
+ orig_model_id = model_data.fetch(relation.fetch(:foreign_key))
125
+ orig_model = @models.detect { |array_model| array_model.id == orig_model_id }
126
+
127
+ raise "Already autoloaded?" if orig_model.autoloads.key?(autoload_name)
128
+ orig_model.autoloads[autoload_name] = model
129
+
130
+ result.fetch(:models) << model
131
+ end
132
+
133
+ result
134
+ end
135
+ end
@@ -0,0 +1,39 @@
1
+ require "orm_adapter"
2
+
3
+ class BazaModels::BazaOrmAdapter < ::OrmAdapter::Base
4
+ def initialize(args)
5
+ @klass = args.fetch(:class)
6
+ end
7
+
8
+ def column_names
9
+ klass.column_names
10
+ end
11
+
12
+ def get!(id)
13
+ klass.find(wrap_key(id))
14
+ end
15
+
16
+ def get(id)
17
+ klass.where(id: wrap_key(id)).first
18
+ end
19
+
20
+ def find_first(options)
21
+ klass.find_first(options)
22
+ end
23
+
24
+ def find_all(options = {})
25
+ klass.where(options)
26
+ end
27
+
28
+ def create!(attributes = {})
29
+ klass.create!(attributes)
30
+ end
31
+
32
+ def destroy(object)
33
+ if valid_object?(object)
34
+ object.destroy
35
+ else
36
+ false
37
+ end
38
+ end
39
+ end
@@ -0,0 +1,9 @@
1
+ class BazaModels::CanCanAdapter < CanCan::ModelAdapters::AbstractAdapter
2
+ def self.for_class?(klass)
3
+ klass.is_a?(BazaModels::Query)
4
+ end
5
+
6
+ def database_records
7
+ @model_class.all
8
+ end
9
+ end
@@ -0,0 +1,44 @@
1
+ class BazaModels::ClassTranslation
2
+ def initialize(args)
3
+ @klass = args.fetch(:class)
4
+ end
5
+
6
+ def class_name_snake
7
+ @class_name_snake ||= StringCases.camel_to_snake(@klass.name)
8
+ end
9
+
10
+ def human(args = {})
11
+ if args[:count] && args[:count] >= 2
12
+ count_key = "other"
13
+ else
14
+ count_key = "one"
15
+ end
16
+
17
+ keys = [
18
+ "baza_models.models.#{class_name_snake}.#{count_key}",
19
+ "activerecord.models.#{class_name_snake}.#{count_key}"
20
+ ]
21
+
22
+ keys.each do |key|
23
+ return I18n.t(key) if I18n.exists?(key)
24
+ end
25
+
26
+ @klass.name
27
+ end
28
+
29
+ def param_key
30
+ @param_key ||= class_name_snake
31
+ end
32
+
33
+ def route_key
34
+ "#{param_key}s"
35
+ end
36
+
37
+ def singular_route_key
38
+ param_key
39
+ end
40
+
41
+ def i18n_key
42
+ param_key.to_sym
43
+ end
44
+ end