dart 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 (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,52 @@
1
+ module Dart
2
+ module Reflection
3
+ module SequelTable
4
+
5
+ # Schema holds all the relations in a schema
6
+ class Schema
7
+ include Sequel::Sequelizer
8
+
9
+ attr_reader :db, :relation_map
10
+ private :db, :relation_map
11
+
12
+ def initialize(db, db_tables=nil)
13
+ @db = db
14
+
15
+ # default to using all tables unless db_tables is passed in
16
+ table_names = (db_tables || db.tables).map(&method(:sequelize))
17
+ @relation_map = Hash[table_names.map { |table| [table, Database::Relation.new(table, db[table].columns)] }]
18
+ end
19
+
20
+ def execute!(sql)
21
+ db[sql]
22
+ end
23
+
24
+ # Returns true if this schema has the given table
25
+ # @param [Symbol|String] table
26
+ def has_table?(table)
27
+ tables.include? sequelize(table)
28
+ end
29
+
30
+ # @return [Array<Symbol>] list of table names in this schema
31
+ def tables
32
+ relation_map.keys
33
+ end
34
+
35
+ # @return [Array<Relation>] list of +Relations+ in this schema
36
+ def relations
37
+ relation_map.values
38
+ end
39
+
40
+ # Returns a relation from this schema corresponding to the given table
41
+ # @param [Symbol|String] table the name of the table
42
+ # @return [Relation] the relation corresponding to the given table
43
+ def relation(table)
44
+ relation_map[sequelize(table)]
45
+ end
46
+ alias [] relation
47
+
48
+ private
49
+ end
50
+ end
51
+ end
52
+ end
@@ -0,0 +1,10 @@
1
+ # require 'sequel'
2
+
3
+ require_relative 'core'
4
+ require_relative 'reflection/sequel/sequelizer'
5
+
6
+ require_relative 'reflection/abstract_resolver'
7
+ require_relative 'reflection/orm_model_resolver'
8
+
9
+ require_relative 'reflection/sequel_model/resolver'
10
+
@@ -0,0 +1,26 @@
1
+ require 'sequel'
2
+
3
+ # Install the Sequel table based naming conventions and resolver
4
+ require_relative 'core'
5
+
6
+ # require_relative 'naming_conventions'
7
+ require_relative 'database'
8
+
9
+ require_relative 'reflection/abstract_resolver'
10
+
11
+ require_relative 'reflection/sequel/naming_conventions'
12
+ require_relative 'reflection/sequel/sequelizer'
13
+
14
+ require_relative 'reflection/sequel_table/foreign_key_finder'
15
+ require_relative 'reflection/sequel_table/schema'
16
+ require_relative 'reflection/sequel_table/resolver'
17
+ require_relative 'reflection/sequel_table/reflector'
18
+
19
+ # Table reflection relies on some naming conventions to discover and name many_to_many associations from foreign keys
20
+ # has_direct_conventional_parent? - to prevent creation of many_to_many when direct already exists
21
+ # disambiguate_conflicting_join_names! - to allow short names in most cases and only disambiguate in conflicting cases
22
+
23
+ # If/when we make the resolvers search for possible join tables only when a direct association doesn't exist, then
24
+ # we might be able to decouple sequel table resolvers from naming conventions. However, naming conventions would be very
25
+ # useful to choose the best join association when multiple possibilities exist.
26
+
@@ -0,0 +1,3 @@
1
+ module Dart
2
+ VERSION = "0.0.1"
3
+ end
@@ -0,0 +1,80 @@
1
+ require_relative '../../test_helper'
2
+ require_relative '../../../lib/dart/database'
3
+ require_relative '../../../lib/dart/database/test_helpers'
4
+ require_relative '../../../lib/dart/reflection/sequel/naming_conventions' # install Sequel naming conventions
5
+
6
+ module Dart
7
+ module Database
8
+ class ManyToManyAssociationTest < Minitest::Test
9
+
10
+ include Dart::Database::TestHelpers
11
+
12
+ ##############################################################################################################
13
+ # describe #disambiguate_name!
14
+
15
+ def test_disambiguate_name_with_conventional_join_table
16
+ join = many_to_many_ass many_to_one_ass(:groups_users, :user_id, :users, :id),
17
+ many_to_one_ass(:groups_users, :group_id, :groups, :id)
18
+ join.disambiguate_name!
19
+ assert_equal 'groups', join.name
20
+ end
21
+
22
+ def test_disambiguate_name_with_semi_conventional_join_table
23
+ join = many_to_many_ass many_to_one_ass(:user_groups, :group_id, :groups, :id),
24
+ many_to_one_ass(:user_groups, :user_id, :users, :id)
25
+ join.disambiguate_name!
26
+ assert_equal 'users', join.name
27
+ end
28
+
29
+ def test_disambiguate_name_with_unconventional_join_table
30
+ join = many_to_many_ass many_to_one_ass(:membership, :user_id, :users, :id),
31
+ many_to_one_ass(:membership, :group_id, :groups, :id)
32
+ join.disambiguate_name!
33
+ assert_equal 'membership_groups', join.name
34
+ end
35
+
36
+ def test_disambiguate_name_with_unconventional_left_foreign_key
37
+ join = many_to_many_ass many_to_one_ass(:user_groups, :member_id, :users, :id),
38
+ many_to_one_ass(:user_groups, :groups_id, :groups, :id)
39
+ join.disambiguate_name!
40
+ assert_equal 'groups', join.name
41
+ end
42
+
43
+ def test_disambiguate_name_with_unconventional_right_foreign_key
44
+ join = many_to_many_ass many_to_one_ass(:user_groups, :user_id, :users, :id),
45
+ many_to_one_ass(:user_groups, :team_id, :groups, :id)
46
+ join.disambiguate_name!
47
+ assert_equal 'teams', join.name
48
+ end
49
+
50
+ def test_disambiguate_name_with_unconventional_left_and_right_foreign_keys
51
+ join = many_to_many_ass many_to_one_ass(:user_groups, :member_id, :users, :id),
52
+ many_to_one_ass(:user_groups, :team_id, :groups, :id)
53
+ join.disambiguate_name!
54
+ assert_equal 'teams', join.name
55
+ end
56
+
57
+ def test_disambiguate_name_with_unconventional_join_table_and_left_foreign_key
58
+ join = many_to_many_ass many_to_one_ass(:membership, :member_id, :users, :id),
59
+ many_to_one_ass(:membership, :group_id, :items, :id)
60
+ join.disambiguate_name!
61
+ assert_equal 'membership_member_id_groups', join.name
62
+ end
63
+
64
+ def test_disambiguate_name_with_unconventional_join_table_and_right_foreign_key
65
+ join = many_to_many_ass many_to_one_ass(:membership, :user_id, :users, :id),
66
+ many_to_one_ass(:membership, :team_id, :items, :id)
67
+ join.disambiguate_name!
68
+ assert_equal 'membership_teams', join.name
69
+ end
70
+
71
+ def test_disambiguate_name_with_unconventional_join_table_and_left_and_right_foreign_keys
72
+ join = many_to_many_ass many_to_one_ass(:membership, :member_id, :users, :id),
73
+ many_to_one_ass(:membership, :team_id, :items, :id)
74
+ join.disambiguate_name!
75
+ assert_equal 'membership_member_id_teams', join.name
76
+ end
77
+
78
+ end
79
+ end
80
+ end
@@ -0,0 +1,38 @@
1
+ require_relative '../../test_helper'
2
+ require_relative '../../../lib/dart/naming_conventions'
3
+ require_relative '../../../lib/dart/reflection/sequel/naming_conventions' # install Sequel naming conventions
4
+
5
+ module Dart
6
+ module NamingConventions
7
+ class AbstractBaseTest < Minitest::Test
8
+
9
+ def subject
10
+ NamingConventions.instance
11
+ end
12
+
13
+ def test_parent_table_for # (possible_foreign_key)
14
+ assert_equal 'groups', subject.parent_table_for('group_id')
15
+ assert_nil subject.parent_table_for('created_by')
16
+ end
17
+
18
+ def test_singular_association_name # (foreign_key)
19
+ assert_equal 'group', subject.singular_association_name('group_id')
20
+ end
21
+
22
+ def test_plural_association_name # (foreign_key)
23
+ assert_equal 'groups', subject.plural_association_name('group_id')
24
+ end
25
+
26
+ def test_long_association_name # (join_table, left_key, left_table, right_key)
27
+ assert_equal 'topic_assignment_users', subject.long_association_name('topic_assignments', 'group_id', 'groups', 'user_id')
28
+ assert_equal 'broadcast_created_by_items', subject.long_association_name('broadcasts', 'created_by', 'users', 'item_id')
29
+ end
30
+
31
+ def test_conventional_join_table_names # (left_table_name, right_table_name)
32
+ expected = %w(groups_users group_users groups_user group_user users_groups user_groups users_group user_group)
33
+ assert_equal expected.sort, subject.conventional_join_table_names('users', 'groups').sort
34
+ end
35
+
36
+ end
37
+ end
38
+ end
@@ -0,0 +1,66 @@
1
+ require_relative '../../test_helper'
2
+ require 'dart/sequel_model_reflection'
3
+
4
+ module Dart
5
+ module Reflection
6
+ class OrmModelResolverTest < Minitest::Test
7
+
8
+ # describe #scope_hash_from
9
+
10
+ def subject
11
+ model_class = OpenStruct.new
12
+ OrmModelResolver.new(model_class)
13
+ end
14
+
15
+ def test_scope_hash_from_select_only
16
+ sql = "SELECT * FROM users"
17
+ actual = subject.scope_hash_from(sql)
18
+ assert_nil actual[:where]
19
+ assert_nil actual[:order]
20
+ assert_nil actual[:limit]
21
+ end
22
+
23
+ def test_scope_hash_from_where
24
+ expected_where = "occupation = 'Brewer' AND first_name = 'Samuel'"
25
+ sql = "SELECT * FROM users WHERE #{expected_where}"
26
+ actual = subject.scope_hash_from(sql)
27
+ assert_equal expected_where, actual[:where]
28
+ assert_nil actual[:order]
29
+ assert_nil actual[:limit]
30
+ end
31
+
32
+ def test_scope_hash_from_where_order
33
+ expected_where = "occupation = 'Brewer' AND first_name = 'Samuel'"
34
+ expected_order = '"users"."last_name" ASC'
35
+ sql = "SELECT * FROM users WHERE #{expected_where} ORDER BY #{expected_order}"
36
+ actual = subject.scope_hash_from(sql)
37
+ assert_equal expected_where, actual[:where]
38
+ assert_equal expected_order, actual[:order]
39
+ assert_nil actual[:limit]
40
+ end
41
+
42
+ def test_scope_hash_from_where_order_limit
43
+ expected_where = "occupation = 'Brewer' AND first_name = 'Samuel'"
44
+ expected_order = '"users"."last_name" ASC'
45
+ expected_limit = '5'
46
+ sql = "SELECT * FROM users WHERE #{expected_where} ORDER BY #{expected_order} LIMIT #{expected_limit}"
47
+ actual = subject.scope_hash_from(sql)
48
+ assert_equal expected_where, actual[:where]
49
+ assert_equal expected_order, actual[:order]
50
+ assert_equal expected_limit, actual[:limit]
51
+ end
52
+
53
+ def test_scope_hash_from_order_limit
54
+ expected_order = '"users"."last_name" ASC'
55
+ expected_limit = '5'
56
+ sql = "SELECT * FROM users ORDER BY #{expected_order} LIMIT #{expected_limit}"
57
+ actual = subject.scope_hash_from(sql)
58
+ assert_nil actual[:where]
59
+ assert_equal expected_order, actual[:order]
60
+ assert_equal expected_limit, actual[:limit]
61
+ end
62
+
63
+
64
+ end
65
+ end
66
+ end
@@ -0,0 +1,6 @@
1
+ require 'minitest/autorun'
2
+
3
+ require 'dart'
4
+
5
+
6
+
metadata ADDED
@@ -0,0 +1,182 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: dart
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ platform: ruby
6
+ authors:
7
+ - Ed Posnak
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2015-05-11 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: abstract_method
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ">="
18
+ - !ruby/object:Gem::Version
19
+ version: '0'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ">="
25
+ - !ruby/object:Gem::Version
26
+ version: '0'
27
+ - !ruby/object:Gem::Dependency
28
+ name: pg
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: '0'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ">="
39
+ - !ruby/object:Gem::Version
40
+ version: '0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: sequel
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ">="
46
+ - !ruby/object:Gem::Version
47
+ version: '0'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ">="
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
55
+ - !ruby/object:Gem::Dependency
56
+ name: bundler
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - "~>"
60
+ - !ruby/object:Gem::Version
61
+ version: '1.7'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - "~>"
67
+ - !ruby/object:Gem::Version
68
+ version: '1.7'
69
+ - !ruby/object:Gem::Dependency
70
+ name: rake
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - "~>"
74
+ - !ruby/object:Gem::Version
75
+ version: '10.0'
76
+ type: :development
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - "~>"
81
+ - !ruby/object:Gem::Version
82
+ version: '10.0'
83
+ - !ruby/object:Gem::Dependency
84
+ name: minitest
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - ">="
88
+ - !ruby/object:Gem::Version
89
+ version: '0'
90
+ type: :development
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - ">="
95
+ - !ruby/object:Gem::Version
96
+ version: '0'
97
+ description: database association resolver toolkit for postgres, activemodel, sequel,
98
+ etc.
99
+ email:
100
+ - ed.posnak@gmail.com
101
+ executables: []
102
+ extensions: []
103
+ extra_rdoc_files: []
104
+ files:
105
+ - ".gitignore"
106
+ - Gemfile
107
+ - LICENSE.txt
108
+ - README.md
109
+ - Rakefile
110
+ - dart.gemspec
111
+ - lib/dart.rb
112
+ - lib/dart/active_record_model_reflection.rb
113
+ - lib/dart/core.rb
114
+ - lib/dart/core/association.rb
115
+ - lib/dart/core/direct_association.rb
116
+ - lib/dart/core/foreign_key_info.rb
117
+ - lib/dart/core/many_to_many_association.rb
118
+ - lib/dart/core/many_to_one_association.rb
119
+ - lib/dart/core/one_to_many_association.rb
120
+ - lib/dart/core/one_to_one_association.rb
121
+ - lib/dart/core/relation.rb
122
+ - lib/dart/database.rb
123
+ - lib/dart/database/many_to_many_association.rb
124
+ - lib/dart/database/many_to_one_association.rb
125
+ - lib/dart/database/one_to_many_association.rb
126
+ - lib/dart/database/relation.rb
127
+ - lib/dart/database/test_helpers.rb
128
+ - lib/dart/naming_conventions.rb
129
+ - lib/dart/naming_conventions/abstract_base.rb
130
+ - lib/dart/naming_conventions/association_helpers.rb
131
+ - lib/dart/naming_conventions/direct_association_helpers.rb
132
+ - lib/dart/naming_conventions/foreign_key_finder.rb
133
+ - lib/dart/naming_conventions/many_to_many_association_helpers.rb
134
+ - lib/dart/naming_conventions/many_to_one_association_helpers.rb
135
+ - lib/dart/naming_conventions/one_to_many_association_helpers.rb
136
+ - lib/dart/naming_conventions/relation_helpers.rb
137
+ - lib/dart/reflection/abstract_resolver.rb
138
+ - lib/dart/reflection/active_record_model/resolver.rb
139
+ - lib/dart/reflection/orm_model_resolver.rb
140
+ - lib/dart/reflection/sequel/naming_conventions.rb
141
+ - lib/dart/reflection/sequel/sequelizer.rb
142
+ - lib/dart/reflection/sequel_model/resolver.rb
143
+ - lib/dart/reflection/sequel_table/foreign_key_finder.rb
144
+ - lib/dart/reflection/sequel_table/reflector.rb
145
+ - lib/dart/reflection/sequel_table/resolver.rb
146
+ - lib/dart/reflection/sequel_table/schema.rb
147
+ - lib/dart/sequel_model_reflection.rb
148
+ - lib/dart/sequel_table_reflection.rb
149
+ - lib/dart/version.rb
150
+ - test/dart/database/many_to_many_association_test.rb
151
+ - test/dart/naming_conventions/abstract_base_test.rb
152
+ - test/dart/reflection/orm_model_resolver_test.rb
153
+ - test/test_helper.rb
154
+ homepage: ''
155
+ licenses:
156
+ - MIT
157
+ metadata: {}
158
+ post_install_message:
159
+ rdoc_options: []
160
+ require_paths:
161
+ - lib
162
+ required_ruby_version: !ruby/object:Gem::Requirement
163
+ requirements:
164
+ - - ">="
165
+ - !ruby/object:Gem::Version
166
+ version: '0'
167
+ required_rubygems_version: !ruby/object:Gem::Requirement
168
+ requirements:
169
+ - - ">="
170
+ - !ruby/object:Gem::Version
171
+ version: '0'
172
+ requirements: []
173
+ rubyforge_project:
174
+ rubygems_version: 2.4.5
175
+ signing_key:
176
+ specification_version: 4
177
+ summary: database association resolver toolkit
178
+ test_files:
179
+ - test/dart/database/many_to_many_association_test.rb
180
+ - test/dart/naming_conventions/abstract_base_test.rb
181
+ - test/dart/reflection/orm_model_resolver_test.rb
182
+ - test/test_helper.rb