dart 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (51) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +18 -0
  3. data/Gemfile +4 -0
  4. data/LICENSE.txt +22 -0
  5. data/README.md +31 -0
  6. data/Rakefile +2 -0
  7. data/dart.gemspec +28 -0
  8. data/lib/dart.rb +1 -0
  9. data/lib/dart/active_record_model_reflection.rb +7 -0
  10. data/lib/dart/core.rb +17 -0
  11. data/lib/dart/core/association.rb +29 -0
  12. data/lib/dart/core/direct_association.rb +36 -0
  13. data/lib/dart/core/foreign_key_info.rb +8 -0
  14. data/lib/dart/core/many_to_many_association.rb +55 -0
  15. data/lib/dart/core/many_to_one_association.rb +18 -0
  16. data/lib/dart/core/one_to_many_association.rb +13 -0
  17. data/lib/dart/core/one_to_one_association.rb +17 -0
  18. data/lib/dart/core/relation.rb +46 -0
  19. data/lib/dart/database.rb +8 -0
  20. data/lib/dart/database/many_to_many_association.rb +14 -0
  21. data/lib/dart/database/many_to_one_association.rb +14 -0
  22. data/lib/dart/database/one_to_many_association.rb +14 -0
  23. data/lib/dart/database/relation.rb +21 -0
  24. data/lib/dart/database/test_helpers.rb +23 -0
  25. data/lib/dart/naming_conventions.rb +18 -0
  26. data/lib/dart/naming_conventions/abstract_base.rb +71 -0
  27. data/lib/dart/naming_conventions/association_helpers.rb +16 -0
  28. data/lib/dart/naming_conventions/direct_association_helpers.rb +21 -0
  29. data/lib/dart/naming_conventions/foreign_key_finder.rb +26 -0
  30. data/lib/dart/naming_conventions/many_to_many_association_helpers.rb +52 -0
  31. data/lib/dart/naming_conventions/many_to_one_association_helpers.rb +20 -0
  32. data/lib/dart/naming_conventions/one_to_many_association_helpers.rb +26 -0
  33. data/lib/dart/naming_conventions/relation_helpers.rb +40 -0
  34. data/lib/dart/reflection/abstract_resolver.rb +7 -0
  35. data/lib/dart/reflection/active_record_model/resolver.rb +122 -0
  36. data/lib/dart/reflection/orm_model_resolver.rb +64 -0
  37. data/lib/dart/reflection/sequel/naming_conventions.rb +25 -0
  38. data/lib/dart/reflection/sequel/sequelizer.rb +14 -0
  39. data/lib/dart/reflection/sequel_model/resolver.rb +78 -0
  40. data/lib/dart/reflection/sequel_table/foreign_key_finder.rb +50 -0
  41. data/lib/dart/reflection/sequel_table/reflector.rb +151 -0
  42. data/lib/dart/reflection/sequel_table/resolver.rb +60 -0
  43. data/lib/dart/reflection/sequel_table/schema.rb +52 -0
  44. data/lib/dart/sequel_model_reflection.rb +10 -0
  45. data/lib/dart/sequel_table_reflection.rb +26 -0
  46. data/lib/dart/version.rb +3 -0
  47. data/test/dart/database/many_to_many_association_test.rb +80 -0
  48. data/test/dart/naming_conventions/abstract_base_test.rb +38 -0
  49. data/test/dart/reflection/orm_model_resolver_test.rb +66 -0
  50. data/test/test_helper.rb +6 -0
  51. metadata +182 -0
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 34a16d3441cb65b527d15f07df704baa20a934ac
4
+ data.tar.gz: 9d3ecf9a3c691056893402b58d8bd6c7bb8413b8
5
+ SHA512:
6
+ metadata.gz: d7d392408a9436d8ec671b16f9983ff1d474c031ebb58a43e68a6963e61b26cb1f4e0dcdf38d2d1bfe491309491ebabdea5eb42351fe8c64535e9ba82f4dd006
7
+ data.tar.gz: cd0601ae56191ca328a8d0879f316eb3a6a87c841c21f4d535244c02ad7917ee3d0c1ac1bb9f79acd37c759bb5dd361e0c2a2a9654186e779b871815afbe74b6
@@ -0,0 +1,18 @@
1
+ /.bundle/
2
+ /.yardoc
3
+ /Gemfile.lock
4
+ /_yardoc/
5
+ /coverage/
6
+ /doc/
7
+ /pkg/
8
+ /spec/reports/
9
+ /tmp/
10
+ *.bundle
11
+ *.so
12
+ *.o
13
+ *.a
14
+ mkmf.log
15
+
16
+ .idea
17
+ /vendor
18
+
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in dart.gemspec
4
+ gemspec
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2015 Ed Posnak
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,31 @@
1
+ # Dart
2
+
3
+ TODO: Write a gem description
4
+
5
+ ## Installation
6
+
7
+ Add this line to your application's Gemfile:
8
+
9
+ ```ruby
10
+ gem 'dart'
11
+ ```
12
+
13
+ And then execute:
14
+
15
+ $ bundle
16
+
17
+ Or install it yourself as:
18
+
19
+ $ gem install dart
20
+
21
+ ## Usage
22
+
23
+ TODO: Write usage instructions here
24
+
25
+ ## Contributing
26
+
27
+ 1. Fork it ( https://github.com/[my-github-username]/dart/fork )
28
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
29
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
30
+ 4. Push to the branch (`git push origin my-new-feature`)
31
+ 5. Create a new Pull Request
@@ -0,0 +1,2 @@
1
+ require "bundler/gem_tasks"
2
+
@@ -0,0 +1,28 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'dart/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = "dart"
8
+ spec.version = Dart::VERSION
9
+ spec.authors = ["Ed Posnak"]
10
+ spec.email = ["ed.posnak@gmail.com"]
11
+ spec.summary = %q{database association resolver toolkit}
12
+ spec.description = %q{database association resolver toolkit for postgres, activemodel, sequel, etc.}
13
+ spec.homepage = ""
14
+ spec.license = "MIT"
15
+
16
+ spec.files = `git ls-files -z`.split("\x0")
17
+ spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
18
+ spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
19
+ spec.require_paths = ["lib"]
20
+
21
+ spec.add_dependency 'abstract_method'
22
+
23
+ spec.add_development_dependency 'pg'
24
+ spec.add_development_dependency 'sequel'
25
+ spec.add_development_dependency 'bundler', '~> 1.7'
26
+ spec.add_development_dependency 'rake', '~> 10.0'
27
+ spec.add_development_dependency 'minitest'
28
+ end
@@ -0,0 +1 @@
1
+ require 'dart/core'
@@ -0,0 +1,7 @@
1
+ # require 'activerecord'
2
+
3
+ require_relative 'core'
4
+ require_relative 'reflection/abstract_resolver'
5
+ require_relative 'reflection/orm_model_resolver'
6
+ require_relative 'reflection/active_record_model/resolver'
7
+
@@ -0,0 +1,17 @@
1
+ require 'ostruct'
2
+ require 'singleton'
3
+ require 'abstract_method'
4
+
5
+ require_relative 'version'
6
+ require_relative 'naming_conventions/abstract_base'
7
+
8
+ require_relative 'core/foreign_key_info'
9
+
10
+ require_relative 'core/association'
11
+ require_relative 'core/direct_association'
12
+ require_relative 'core/one_to_one_association'
13
+ require_relative 'core/many_to_one_association'
14
+ require_relative 'core/one_to_many_association'
15
+ require_relative 'core/many_to_many_association'
16
+
17
+ require_relative 'core/relation'
@@ -0,0 +1,29 @@
1
+ module Dart
2
+ class Association
3
+
4
+ ONE_TO_ONE_TYPE = :one_to_one
5
+ ONE_TO_MANY_TYPE = :one_to_many
6
+ MANY_TO_ONE_TYPE = :many_to_one
7
+ MANY_TO_MANY_TYPE = :many_to_many
8
+
9
+ # used by ORM implementations to store the associated ORM model class and association options
10
+ attr_accessor :model_class
11
+ attr_accessor :scope
12
+
13
+ abstract_method :type, :associated_table
14
+
15
+ attr_reader :name
16
+
17
+ # @param [String|Symbol] ass_name
18
+ def set_name!(ass_name)
19
+ @name = ass_name.to_s
20
+ end
21
+
22
+ # can be overriddent by *_to_one association types
23
+ def to_one?
24
+ false
25
+ end
26
+
27
+
28
+ end
29
+ end
@@ -0,0 +1,36 @@
1
+ module Dart
2
+ class DirectAssociation < Association
3
+ ATTRIBUTES = [:child_table, :foreign_key, :parent_table, :primary_key]
4
+ attr_reader *ATTRIBUTES
5
+
6
+ # Constructs a DirectAssociation from the given attributes, which must correspond to ATTRIBUTES defined above
7
+ # given either as separate arguments, a Hash, or an object that responds to methods corresponding to ATTRIBUTES
8
+ def initialize(*args)
9
+ if args.length == 1
10
+ obj_or_hash = args.first
11
+ obj = obj_or_hash.is_a?(Hash) ? OpenStruct.new(obj_or_hash) : obj_or_hash
12
+ else
13
+ obj = OpenStruct.new
14
+ ATTRIBUTES.each_with_index {|a, i| obj.send("#{a}=", args[i])}
15
+ end
16
+ @child_table = obj.child_table.to_s.freeze or raise "No child table in #{obj_or_hash}"
17
+ @foreign_key = obj.foreign_key.to_s.freeze or raise "No foreign_key in #{obj_or_hash}"
18
+ @parent_table = obj.parent_table.to_s.freeze or raise "No parent_table in #{obj_or_hash}"
19
+ @primary_key = obj.primary_key.to_s.freeze or raise "No primary_key in #{obj_or_hash}"
20
+ end
21
+
22
+ def eql?(other)
23
+ ATTRIBUTES.all? { |f| send(f) == other.send(f) }
24
+ end
25
+ alias == eql?
26
+
27
+ def hash
28
+ ATTRIBUTES.map { |a| send(a) }.hash
29
+ end
30
+
31
+ def to_s
32
+ "#{self.class} #{ATTRIBUTES.map { |a| "#{a}: #{send(a)}" }.join(', ')}"
33
+ end
34
+
35
+ end
36
+ end
@@ -0,0 +1,8 @@
1
+ ForeignKeyInfo = Struct.new :child_table, :foreign_key, :parent_table, :primary_key do
2
+ module Constructors
3
+ def from_hash(attrs)
4
+ new(attrs[:child_table], attrs[:foreign_key], attrs[:parent_table], attrs[:primary_key])
5
+ end
6
+ end
7
+ extend Constructors
8
+ end
@@ -0,0 +1,55 @@
1
+ module Dart
2
+ class ManyToManyAssociation < Association
3
+
4
+ attr_reader :left_ass, :right_ass
5
+ protected :left_ass, :right_ass
6
+
7
+ # for an m2m association on users we'd pass in:
8
+ # left_ass: badge_users.user_id -> users.id
9
+ # right_ass: badge_users.badge_id -> badges.id
10
+ # =>
11
+ # many_to_many :badges, join_table: :badge_users
12
+
13
+ def initialize(left_ass, right_ass)
14
+ @left_ass, @right_ass = left_ass, right_ass
15
+ end
16
+
17
+ def join_associations
18
+ [left_ass, right_ass]
19
+ end
20
+
21
+ def type
22
+ MANY_TO_MANY_TYPE
23
+ end
24
+
25
+ def associated_table
26
+ right_ass.parent_table
27
+ end
28
+
29
+ def join_table
30
+ right_ass.child_table
31
+ end
32
+
33
+ def left_foreign_key
34
+ left_ass.foreign_key
35
+ end
36
+
37
+ def right_foreign_key
38
+ right_ass.foreign_key
39
+ end
40
+
41
+ def eql?(other)
42
+ join_associations.eql? other.join_associations
43
+ end
44
+ alias == eql?
45
+
46
+ def hash
47
+ join_associations.hash
48
+ end
49
+
50
+ def to_s
51
+ "#{self.class}\n left:#{left_ass}\n right:#{right_ass}"
52
+ end
53
+
54
+ end
55
+ end
@@ -0,0 +1,18 @@
1
+ module Dart
2
+ class ManyToOneAssociation < DirectAssociation
3
+
4
+ def type
5
+ MANY_TO_ONE_TYPE
6
+ end
7
+
8
+ def associated_table
9
+ parent_table
10
+ end
11
+
12
+ def to_one?
13
+ true
14
+ end
15
+
16
+ end
17
+ end
18
+
@@ -0,0 +1,13 @@
1
+ module Dart
2
+ class OneToManyAssociation < DirectAssociation
3
+
4
+ def type
5
+ ONE_TO_MANY_TYPE
6
+ end
7
+
8
+ def associated_table
9
+ child_table
10
+ end
11
+
12
+ end
13
+ end
@@ -0,0 +1,17 @@
1
+ module Dart
2
+ class OneToOneAssociation < DirectAssociation
3
+
4
+ def type
5
+ ONE_TO_ONE_TYPE
6
+ end
7
+
8
+ def associated_table
9
+ child_table
10
+ end
11
+
12
+ def to_one?
13
+ true
14
+ end
15
+
16
+ end
17
+ end
@@ -0,0 +1,46 @@
1
+ module Dart
2
+ class Relation
3
+ attr_reader :table_name, :column_names
4
+
5
+ attr_reader :associations
6
+ private :associations
7
+
8
+ def initialize(table, columns)
9
+ @table_name = table.to_s.freeze
10
+ @column_names = columns.map(&:to_s).map(&:freeze)
11
+ @associations = []
12
+ end
13
+
14
+ # @return [Array<Association>] list of all associations on this relation
15
+ def all_associations
16
+ associations
17
+ end
18
+
19
+ # @return [Array<Association>] list of all direct (many_to_one or one_to_many) associations on this relation
20
+ def direct_associations
21
+ # associations - join_associations
22
+ parent_associations + child_associations
23
+ end
24
+
25
+ # @return [Array<Association>] list of all join (many_to_many) associations on this relation
26
+ def join_associations
27
+ associations.select { |a| a.is_a?(ManyToManyAssociation) }
28
+ end
29
+
30
+ def parent_associations
31
+ associations.select { |a| a.is_a?(ManyToOneAssociation) }
32
+ end
33
+
34
+ def child_associations
35
+ associations.select { |a| a.is_a?(OneToManyAssociation) }
36
+ end
37
+
38
+ def add_association(ass)
39
+ associations << ass
40
+ end
41
+
42
+ def to_s
43
+ table_name
44
+ end
45
+ end
46
+ end
@@ -0,0 +1,8 @@
1
+ require_relative 'core'
2
+ require_relative 'naming_conventions'
3
+
4
+ require_relative 'database/relation'
5
+ require_relative 'database/many_to_many_association'
6
+ require_relative 'database/many_to_one_association'
7
+ require_relative 'database/one_to_many_association'
8
+
@@ -0,0 +1,14 @@
1
+ module Dart
2
+ module Database
3
+ # A Database::ManyToManyAssociation extends Dart::ManyToManyAssociation with naming conventions
4
+ class ManyToManyAssociation < Dart::ManyToManyAssociation
5
+ include NamingConventions::ManyToManyAssociationHelpers
6
+
7
+ def initialize(*)
8
+ super
9
+ set_conventional_name!
10
+ end
11
+
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,14 @@
1
+ module Dart
2
+ module Database
3
+ # A Database::ManyToOneAssociation extends Dart::ManyToOneAssociation with naming conventions
4
+ class ManyToOneAssociation < Dart::ManyToOneAssociation
5
+ include NamingConventions::ManyToOneAssociationHelpers
6
+
7
+ def initialize(*)
8
+ super
9
+ set_conventional_name!
10
+ end
11
+
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,14 @@
1
+ module Dart
2
+ module Database
3
+ # A Database::OneToManyAssociation extends Dart::OneToManyAssociation with naming conventions
4
+ class OneToManyAssociation < Dart::OneToManyAssociation
5
+ include NamingConventions::OneToManyAssociationHelpers
6
+
7
+ def initialize(*)
8
+ super
9
+ set_conventional_name!
10
+ end
11
+
12
+ end
13
+ end
14
+ end