baza_models 0.0.0 → 0.0.1

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