baza_models 0.0.3 → 0.0.4

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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: b4c06e71c9d91e97504d17b5a469f2c941c68e26
4
- data.tar.gz: 9d0cc2326a8ce71b1f0b67cf2193b28c1e264e98
3
+ metadata.gz: 4edadeab01c210ce4d6eb26989945d496aa66075
4
+ data.tar.gz: 00229063065ccfcfdb6189b926e5f3c81a33b1e4
5
5
  SHA512:
6
- metadata.gz: c762af7cad3328bd461d34e07939be0ff54e87518eba020676111777d7e84425ce88f3b90fb625bfdcee635202a29e9fe5403556511238b3ed3c11c4464ffd26
7
- data.tar.gz: cb735d831b9c233a4031465feb2258689eb57ee688a20e7ab3e96d5b88b682d05dab606eaa9e66c83624a86c7bdbf6ef5b9602378d69b06a5a6412ec1502dea5
6
+ metadata.gz: 8b3e220cb2c0467ce53fdb66b754eef986069cb5d8c208558dc1f94ec71106539ffc9552aa13600133fe0adc8824614d389308fb5cd8e4a67cf7c6a351e02f98
7
+ data.tar.gz: b9b8691f657f2febae4613e57c079d8f23bd9878a184d0ff174fb8c30bbd326fcf4d92dfa89e3b84052180a3ed7f68b980c8bd9a5b886df6c6fd6c38db811685
@@ -0,0 +1,85 @@
1
+ inherit_from: .rubocop_todo.yml
2
+
3
+ AllCops:
4
+ DisplayCopNames: true
5
+ DisplayStyleGuide: true
6
+ Exclude:
7
+ - db/schema.rb
8
+ - spec/dummy/db/schema.rb
9
+
10
+ # https://github.com/AtomLinter/linter-rubocop/issues/2
11
+ Style/FileName:
12
+ Enabled: false
13
+
14
+ # Metrics/CyclomaticComplexity:
15
+ # Max: 10
16
+
17
+ Metrics/LineLength:
18
+ Max: 160
19
+
20
+ # Metrics/MethodLength:
21
+ # Max: 50
22
+
23
+ # Metrics/AbcSize:
24
+ # Max: 25
25
+
26
+ # Metrics/ClassLength:
27
+ # Max: 250
28
+
29
+ # .find_each is not the same as .each
30
+ Rails/FindEach:
31
+ Enabled: false
32
+
33
+ Style/AccessModifierIndentation:
34
+ EnforcedStyle: outdent
35
+
36
+ Style/AlignParameters:
37
+ EnforcedStyle: with_fixed_indentation
38
+
39
+ Style/ClassAndModuleChildren:
40
+ EnforcedStyle: compact
41
+
42
+ Style/ConditionalAssignment:
43
+ Enabled: false
44
+
45
+ Style/Documentation:
46
+ Enabled: false
47
+
48
+ Style/EmptyLines:
49
+ Enabled: false
50
+
51
+ # Will report offences for many places that are much more readable without using a guard clause
52
+ Style/GuardClause:
53
+ Enabled: false
54
+
55
+ Style/MultilineMethodCallIndentation:
56
+ EnforcedStyle: indented
57
+
58
+ Style/MultilineOperationIndentation:
59
+ EnforcedStyle: indented
60
+
61
+ Style/StringLiterals:
62
+ EnforcedStyle: double_quotes
63
+
64
+ Style/StringLiteralsInInterpolation:
65
+ Enabled: false
66
+
67
+ Style/NilComparison:
68
+ Enabled: false
69
+
70
+ Style/SignalException:
71
+ EnforcedStyle: only_raise
72
+
73
+ Style/MultilineOperationIndentation:
74
+ EnforcedStyle: indented
75
+
76
+ Style/SpaceInsideHashLiteralBraces:
77
+ EnforcedStyle: no_space
78
+
79
+ Style/TrivialAccessors:
80
+ ExactNameMatch: true
81
+ Enabled: true
82
+
83
+ # Disabled on purpose: https://github.com/bbatsov/rubocop/issues/1758
84
+ Style/ClosingParenthesisIndentation:
85
+ Enabled: false
@@ -1,35 +1,68 @@
1
-
2
-
3
-
4
-
5
-
6
-
7
1
  # This configuration was generated by
8
2
  # `rubocop --auto-gen-config`
9
- # on 2015-12-20 19:19:55 +0100 using RuboCop version 0.35.1.
3
+ # on 2016-04-06 18:56:17 +0200 using RuboCop version 0.37.0.
10
4
  # The point is for the user to remove these configuration records
11
5
  # one by one as the offenses are removed from the code base.
12
6
  # Note that changes in the inspected code, or installation of new
13
7
  # versions of RuboCop, may require this file to be generated again.
14
8
 
15
- # Offense count: 6
9
+ # Offense count: 2
10
+ Lint/IneffectiveAccessModifier:
11
+ Exclude:
12
+ - 'lib/baza_models/model.rb'
13
+
14
+ # Offense count: 7
16
15
  Metrics/AbcSize:
17
- Max: 41
16
+ Max: 44
18
17
 
19
- # Offense count: 1
18
+ # Offense count: 2
20
19
  # Configuration parameters: CountComments.
21
20
  Metrics/ClassLength:
22
- Max: 400
21
+ Max: 386
23
22
 
24
- # Offense count: 5
23
+ # Offense count: 1
25
24
  Metrics/CyclomaticComplexity:
26
25
  Max: 15
27
26
 
28
27
  # Offense count: 2
29
28
  # Configuration parameters: CountComments.
30
29
  Metrics/MethodLength:
31
- Max: 77
30
+ Max: 74
32
31
 
33
- # Offense count: 6
32
+ # Offense count: 7
34
33
  Metrics/PerceivedComplexity:
35
34
  Max: 21
35
+
36
+ # Offense count: 2
37
+ # Cop supports --auto-correct.
38
+ Style/MultilineIfThen:
39
+ Exclude:
40
+ - 'baza_models.gemspec'
41
+
42
+ # Offense count: 42
43
+ # Cop supports --auto-correct.
44
+ # Configuration parameters: PreferredDelimiters.
45
+ Style/PercentLiteralDelimiters:
46
+ Exclude:
47
+ - 'baza_models.gemspec'
48
+
49
+ # Offense count: 1
50
+ # Cop supports --auto-correct.
51
+ # Configuration parameters: EnforcedStyle, SupportedStyles, ConsistentQuotesInMultiline.
52
+ # SupportedStyles: single_quotes, double_quotes
53
+ Style/StringLiterals:
54
+ Enabled: false
55
+
56
+ # Offense count: 1
57
+ # Cop supports --auto-correct.
58
+ # Configuration parameters: EnforcedStyle, SupportedStyles.
59
+ # SupportedStyles: final_newline, final_blank_line
60
+ Style/TrailingBlankLines:
61
+ Exclude:
62
+ - 'baza_models.gemspec'
63
+
64
+ # Offense count: 42
65
+ # Cop supports --auto-correct.
66
+ Style/UnneededPercentQ:
67
+ Exclude:
68
+ - 'baza_models.gemspec'
data/Gemfile CHANGED
@@ -7,6 +7,7 @@ gem "array_enumerator", ">= 0.0.10"
7
7
  gem "baza", "~> 0.0.20"
8
8
  gem "string-cases", ">= 0.0.3"
9
9
  gem "auto_autoloader", ">= 0.0.1"
10
+ gem "html_gen", ">= 0.0.12", require: false
10
11
 
11
12
  # Add dependencies to develop your gem here.
12
13
  # Include everything needed to run rake, tests, features, etc.
@@ -19,7 +20,7 @@ group :development do
19
20
  gem "sqlite3", platform: :ruby
20
21
  gem "jdbc-sqlite3", platform: :jruby
21
22
  gem "best_practice_project", require: false, github: "kaspernj/best_practice_project"
22
- gem "rubocop", require: false
23
+ gem "rubocop", "0.37.0", require: false
23
24
  gem "orm_adapter", require: false
24
25
  end
25
26
 
@@ -1,8 +1,9 @@
1
1
  GIT
2
2
  remote: git://github.com/kaspernj/best_practice_project.git
3
- revision: 35df59c22465901fd31f841af7716ce770236831
3
+ revision: c83ad748c63928b446c45e6ba50caabaf7af8714
4
4
  specs:
5
- best_practice_project (0.0.7)
5
+ best_practice_project (0.0.9)
6
+ auto_autoloader
6
7
 
7
8
  GEM
8
9
  remote: http://rubygems.org/
@@ -16,9 +17,7 @@ GEM
16
17
  addressable (2.3.8)
17
18
  array_enumerator (0.0.10)
18
19
  ast (2.2.0)
19
- astrolabe (1.3.1)
20
- parser (~> 2.2)
21
- auto_autoloader (0.0.1)
20
+ auto_autoloader (0.0.4)
22
21
  string-cases
23
22
  baza (0.0.20)
24
23
  array_enumerator (~> 0.0.10)
@@ -50,6 +49,8 @@ GEM
50
49
  oauth2
51
50
  hashie (3.4.2)
52
51
  highline (1.7.2)
52
+ html_gen (0.0.12)
53
+ string-cases
53
54
  i18n (0.7.0)
54
55
  jdbc-sqlite3 (3.8.10.1)
55
56
  jeweler (2.0.1)
@@ -79,11 +80,11 @@ GEM
79
80
  multi_xml (~> 0.5)
80
81
  rack (~> 1.2)
81
82
  orm_adapter (0.5.0)
82
- parser (2.2.3.0)
83
- ast (>= 1.1, < 3.0)
83
+ parser (2.3.0.2)
84
+ ast (~> 2.2)
84
85
  powerpack (0.1.1)
85
86
  rack (1.6.4)
86
- rainbow (2.0.0)
87
+ rainbow (2.1.0)
87
88
  rake (10.4.2)
88
89
  rdoc (3.12.2)
89
90
  json (~> 1.4)
@@ -100,13 +101,12 @@ GEM
100
101
  diff-lcs (>= 1.2.0, < 2.0)
101
102
  rspec-support (~> 3.3.0)
102
103
  rspec-support (3.3.0)
103
- rubocop (0.35.1)
104
- astrolabe (~> 1.3)
105
- parser (>= 2.2.3.0, < 3.0)
104
+ rubocop (0.37.0)
105
+ parser (>= 2.3.0.2, < 3.0)
106
106
  powerpack (~> 0.1)
107
107
  rainbow (>= 1.99.1, < 3.0)
108
108
  ruby-progressbar (~> 1.7)
109
- tins (<= 1.6.0)
109
+ unicode-display_width (~> 0.3)
110
110
  ruby-progressbar (1.7.5)
111
111
  simplecov (0.10.0)
112
112
  docile (~> 1.1.0)
@@ -114,12 +114,12 @@ GEM
114
114
  simplecov-html (~> 0.10.0)
115
115
  simplecov-html (0.10.0)
116
116
  sqlite3 (1.3.10)
117
- string-cases (0.0.3)
117
+ string-cases (0.0.4)
118
118
  thread_safe (0.3.5)
119
119
  thread_safe (0.3.5-java)
120
- tins (1.6.0)
121
120
  tzinfo (1.2.2)
122
121
  thread_safe (~> 0.1)
122
+ unicode-display_width (0.3.1)
123
123
  wref (0.0.8)
124
124
 
125
125
  PLATFORMS
@@ -134,12 +134,13 @@ DEPENDENCIES
134
134
  bundler (~> 1.0)
135
135
  codeclimate-test-reporter
136
136
  factory_girl
137
+ html_gen (>= 0.0.12)
137
138
  jdbc-sqlite3
138
139
  jeweler (~> 2.0.1)
139
140
  orm_adapter
140
141
  rdoc (~> 3.12)
141
142
  rspec (~> 3.3.0)
142
- rubocop
143
+ rubocop (= 0.37.0)
143
144
  sqlite3
144
145
  string-cases (>= 0.0.3)
145
146
 
data/README.md CHANGED
@@ -81,6 +81,11 @@ User.last
81
81
  User.order(:id).reverse_order
82
82
  ```
83
83
 
84
+ ### Ransack
85
+ ```ruby
86
+ Person.ransack(user_organization_name_cont: "test").result.to_a #=> [user]
87
+ ```
88
+
84
89
 
85
90
  ## Setting and saving attributes
86
91
 
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.0.3
1
+ 0.0.4
@@ -2,16 +2,16 @@
2
2
  # DO NOT EDIT THIS FILE DIRECTLY
3
3
  # Instead, edit Jeweler::Tasks in Rakefile, and run 'rake gemspec'
4
4
  # -*- encoding: utf-8 -*-
5
- # stub: baza_models 0.0.3 ruby lib
5
+ # stub: baza_models 0.0.4 ruby lib
6
6
 
7
7
  Gem::Specification.new do |s|
8
8
  s.name = "baza_models"
9
- s.version = "0.0.3"
9
+ s.version = "0.0.4"
10
10
 
11
11
  s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
12
12
  s.require_paths = ["lib"]
13
13
  s.authors = ["kaspernj"]
14
- s.date = "2016-01-07"
14
+ s.date = "2016-04-07"
15
15
  s.description = "ActiveRecord like models for the Baza database framework"
16
16
  s.email = "k@spernj.org"
17
17
  s.extra_rdoc_files = [
@@ -21,6 +21,7 @@ Gem::Specification.new do |s|
21
21
  s.files = [
22
22
  ".document",
23
23
  ".rspec",
24
+ ".rubocop.yml",
24
25
  ".rubocop_todo.yml",
25
26
  "Gemfile",
26
27
  "Gemfile.lock",
@@ -29,14 +30,14 @@ Gem::Specification.new do |s|
29
30
  "Rakefile",
30
31
  "VERSION",
31
32
  "baza_models.gemspec",
32
- "config/best_project_practice_rubocop.yml",
33
- "config/best_project_practice_rubocop_todo.yml",
34
33
  "lib/baza_models.rb",
35
34
  "lib/baza_models/autoloader.rb",
36
35
  "lib/baza_models/baza_orm_adapter.rb",
37
36
  "lib/baza_models/can_can_adapter.rb",
38
37
  "lib/baza_models/class_translation.rb",
39
38
  "lib/baza_models/errors.rb",
39
+ "lib/baza_models/helpers.rb",
40
+ "lib/baza_models/helpers/ransacker_helper.rb",
40
41
  "lib/baza_models/model.rb",
41
42
  "lib/baza_models/model/belongs_to_relations.rb",
42
43
  "lib/baza_models/model/custom_validations.rb",
@@ -51,7 +52,9 @@ Gem::Specification.new do |s|
51
52
  "lib/baza_models/query.rb",
52
53
  "lib/baza_models/query/inspector.rb",
53
54
  "lib/baza_models/query/not.rb",
55
+ "lib/baza_models/query/sql_generator.rb",
54
56
  "lib/baza_models/ransacker.rb",
57
+ "lib/baza_models/ransacker/relationship_scanner.rb",
55
58
  "lib/baza_models/test_database_cleaner.rb",
56
59
  "lib/baza_models/validators.rb",
57
60
  "lib/baza_models/validators/base_validator.rb",
@@ -96,7 +99,7 @@ Gem::Specification.new do |s|
96
99
  ]
97
100
  s.homepage = "http://github.com/kaspernj/baza_models"
98
101
  s.licenses = ["MIT"]
99
- s.rubygems_version = "2.4.0"
102
+ s.rubygems_version = "2.2.2"
100
103
  s.summary = "ActiveRecord like models for the Baza database framework"
101
104
 
102
105
  if s.respond_to? :specification_version then
@@ -107,6 +110,7 @@ Gem::Specification.new do |s|
107
110
  s.add_runtime_dependency(%q<baza>, ["~> 0.0.20"])
108
111
  s.add_runtime_dependency(%q<string-cases>, [">= 0.0.3"])
109
112
  s.add_runtime_dependency(%q<auto_autoloader>, [">= 0.0.1"])
113
+ s.add_runtime_dependency(%q<html_gen>, [">= 0.0.12"])
110
114
  s.add_development_dependency(%q<rspec>, ["~> 3.3.0"])
111
115
  s.add_development_dependency(%q<rdoc>, ["~> 3.12"])
112
116
  s.add_development_dependency(%q<bundler>, ["~> 1.0"])
@@ -115,13 +119,14 @@ Gem::Specification.new do |s|
115
119
  s.add_development_dependency(%q<sqlite3>, [">= 0"])
116
120
  s.add_development_dependency(%q<jdbc-sqlite3>, [">= 0"])
117
121
  s.add_development_dependency(%q<best_practice_project>, [">= 0"])
118
- s.add_development_dependency(%q<rubocop>, [">= 0"])
122
+ s.add_development_dependency(%q<rubocop>, ["= 0.37.0"])
119
123
  s.add_development_dependency(%q<orm_adapter>, [">= 0"])
120
124
  else
121
125
  s.add_dependency(%q<array_enumerator>, [">= 0.0.10"])
122
126
  s.add_dependency(%q<baza>, ["~> 0.0.20"])
123
127
  s.add_dependency(%q<string-cases>, [">= 0.0.3"])
124
128
  s.add_dependency(%q<auto_autoloader>, [">= 0.0.1"])
129
+ s.add_dependency(%q<html_gen>, [">= 0.0.12"])
125
130
  s.add_dependency(%q<rspec>, ["~> 3.3.0"])
126
131
  s.add_dependency(%q<rdoc>, ["~> 3.12"])
127
132
  s.add_dependency(%q<bundler>, ["~> 1.0"])
@@ -130,7 +135,7 @@ Gem::Specification.new do |s|
130
135
  s.add_dependency(%q<sqlite3>, [">= 0"])
131
136
  s.add_dependency(%q<jdbc-sqlite3>, [">= 0"])
132
137
  s.add_dependency(%q<best_practice_project>, [">= 0"])
133
- s.add_dependency(%q<rubocop>, [">= 0"])
138
+ s.add_dependency(%q<rubocop>, ["= 0.37.0"])
134
139
  s.add_dependency(%q<orm_adapter>, [">= 0"])
135
140
  end
136
141
  else
@@ -138,6 +143,7 @@ Gem::Specification.new do |s|
138
143
  s.add_dependency(%q<baza>, ["~> 0.0.20"])
139
144
  s.add_dependency(%q<string-cases>, [">= 0.0.3"])
140
145
  s.add_dependency(%q<auto_autoloader>, [">= 0.0.1"])
146
+ s.add_dependency(%q<html_gen>, [">= 0.0.12"])
141
147
  s.add_dependency(%q<rspec>, ["~> 3.3.0"])
142
148
  s.add_dependency(%q<rdoc>, ["~> 3.12"])
143
149
  s.add_dependency(%q<bundler>, ["~> 1.0"])
@@ -146,7 +152,7 @@ Gem::Specification.new do |s|
146
152
  s.add_dependency(%q<sqlite3>, [">= 0"])
147
153
  s.add_dependency(%q<jdbc-sqlite3>, [">= 0"])
148
154
  s.add_dependency(%q<best_practice_project>, [">= 0"])
149
- s.add_dependency(%q<rubocop>, [">= 0"])
155
+ s.add_dependency(%q<rubocop>, ["= 0.37.0"])
150
156
  s.add_dependency(%q<orm_adapter>, [">= 0"])
151
157
  end
152
158
  end
@@ -0,0 +1,3 @@
1
+ class BazaModels::Helpers
2
+ AutoAutoloader.autoload_sub_classes(self, __FILE__)
3
+ end
@@ -0,0 +1,23 @@
1
+ module BazaModels::Helpers::RansackerHelper
2
+ def bm_sort_link(ransacker, attribute)
3
+ require "html_gen"
4
+
5
+ label = ransacker.klass.human_attribute_name(attribute)
6
+
7
+ new_params = params.clone
8
+ new_params[:q] ||= {}
9
+
10
+ sort_asc = "#{attribute} asc"
11
+
12
+ if new_params[:q][:s] == sort_asc
13
+ new_params[:q][:s] = "#{attribute} desc"
14
+ else
15
+ new_params[:q][:s] = sort_asc
16
+ end
17
+
18
+ href = url_for(new_params)
19
+
20
+ element = HtmlGen::Element.new(:a, str: label, attr: {href: href})
21
+ element.html
22
+ end
23
+ end
@@ -23,7 +23,7 @@ class BazaModels::Model
23
23
  :before_create, :after_create, :before_save, :after_save, :before_destroy, :after_destroy,
24
24
  :before_validation, :after_validation, :before_validation_on_create, :after_validation_on_create,
25
25
  :before_validation_on_update, :after_validation_on_update
26
- ]
26
+ ].freeze
27
27
 
28
28
  CALLBACK_TYPES.each do |callback_type|
29
29
  # rubocop:disable Style/ClassVars
@@ -44,9 +44,9 @@ class BazaModels::Model
44
44
  end
45
45
 
46
46
  QUERY_METHODS = [
47
- :all, :any?, :empty?, :none?, :count, :find, :first, :find_first, :last, :length, :select, :includes,
48
- :joins, :group, :where, :order, :limit, :to_a, :accessible_by
49
- ]
47
+ :all, :any?, :each, :empty?, :none?, :count, :find, :first, :find_first, :last, :length, :select, :includes,
48
+ :joins, :group, :where, :order, :limit, :to_a, :accessible_by, :ransack
49
+ ].freeze
50
50
  QUERY_METHODS.each do |query_method|
51
51
  (class << self; self; end).__send__(:define_method, query_method) do |*args, &blk|
52
52
  BazaModels::Query.new(model: self).__send__(query_method, *args, &blk)
@@ -54,7 +54,7 @@ class BazaModels::Model
54
54
  end
55
55
 
56
56
  def initialize(data = {}, args = {})
57
- self.class.init_model unless self.class.model_initialized?
57
+ self.class.init_model
58
58
 
59
59
  reset_errors
60
60
  @changes = {}
@@ -135,6 +135,8 @@ class BazaModels::Model
135
135
  end
136
136
 
137
137
  def self.init_model
138
+ return if @model_initialized
139
+
138
140
  @table = db.tables[table_name]
139
141
 
140
142
  @__blank_attributes ||= {}
@@ -211,13 +213,10 @@ class BazaModels::Model
211
213
  end
212
214
 
213
215
  def self.column_names
216
+ init_model
214
217
  @column_names ||= __blank_attributes.keys.map(&:to_s)
215
218
  end
216
219
 
217
- def self.ransack(params)
218
- BazaModels::Ransacker.new(class: self, params: params)
219
- end
220
-
221
220
  def [](key)
222
221
  read_attribute(key)
223
222
  end
@@ -323,7 +322,7 @@ protected
323
322
  belongs_to_relations.each do |relation|
324
323
  if attribute_name.to_s == relation[:relation_name].to_s
325
324
  attribute_name = :"#{attribute_name}_id"
326
- attribute_value = attribute_value.id
325
+ attribute_value = attribute_value.id if attribute_value
327
326
  end
328
327
  end
329
328
  end
@@ -40,22 +40,20 @@ module BazaModels::Model::HasOneRelations
40
40
  define_method(relation_name) do
41
41
  if (model = autoloads[relation_name])
42
42
  model
43
+ elsif relation[:args][:through]
44
+ __send__(relation[:args][:through]).__send__(relation_name)
43
45
  else
44
- if relation[:args][:through]
45
- __send__(relation[:args][:through]).__send__(relation_name)
46
- else
47
- class_instance = StringCases.constantize(relation.fetch(:class_name))
46
+ class_instance = StringCases.constantize(relation.fetch(:class_name))
48
47
 
49
- query = class_instance.where(relation.fetch(:foreign_key) => id)
50
- query._previous_model = self
51
- query._relation = relation
48
+ query = class_instance.where(relation.fetch(:foreign_key) => id)
49
+ query._previous_model = self
50
+ query._relation = relation
52
51
 
53
- all_args.each do |arg|
54
- query = query.instance_exec(&arg) if arg.is_a?(Proc)
55
- end
56
-
57
- query.first
52
+ all_args.each do |arg|
53
+ query = query.instance_exec(&arg) if arg.is_a?(Proc)
58
54
  end
55
+
56
+ query.first
59
57
  end
60
58
  end
61
59
  end
@@ -57,7 +57,22 @@ class BazaModels::Query
57
57
  end
58
58
 
59
59
  def length
60
- count
60
+ if @_previous_model && !any_wheres_other_than_relation? && @_previous_model.autoloads[@_relation.fetch(:relation_name)]
61
+ @_previous_model.autoloads[@_relation.fetch(:relation_name)].length
62
+ else
63
+ count
64
+ end
65
+ end
66
+
67
+ def new(attributes)
68
+ raise "No previous model" unless @_previous_model
69
+ raise "No relation" unless @_relation
70
+
71
+ new_sub_model = @model.new(@_relation.fetch(:foreign_key) => @_previous_model.id)
72
+ new_sub_model.assign_attributes(attributes)
73
+ autoloaded_cache_or_create << new_sub_model
74
+
75
+ new_sub_model
61
76
  end
62
77
 
63
78
  def find(id)
@@ -154,10 +169,10 @@ class BazaModels::Query
154
169
  args.each do |key, value|
155
170
  if value.is_a?(Hash)
156
171
  value.each do |hash_key, hash_value|
157
- @wheres << "`#{key}`.`#{key_convert(hash_key, hash_value)}` = #{@db.sqlval(value_convert(hash_value))}"
172
+ @wheres << "`#{key}`.`#{key_convert(hash_key, hash_value)}` #{value_with_mode(value_convert(hash_value))}"
158
173
  end
159
174
  else
160
- @wheres << "`#{@model.table_name}`.`#{key_convert(key, value)}` = #{@db.sqlval(value_convert(value))}"
175
+ @wheres << "`#{@model.table_name}`.`#{key_convert(key, value)}` #{value_with_mode(value_convert(value))}"
161
176
  end
162
177
  end
163
178
  end
@@ -274,84 +289,7 @@ class BazaModels::Query
274
289
  end
275
290
 
276
291
  def to_sql
277
- sql = "SELECT "
278
-
279
- if @selects.empty?
280
- sql << "`#{@model.table_name}`.*"
281
- else
282
- sql << @selects.join(", ")
283
- end
284
-
285
- sql << " FROM `#{@model.table_name}`"
286
-
287
- unless @joins.empty?
288
- @joins.each do |join|
289
- sql << " #{join}"
290
- end
291
- end
292
-
293
- unless @wheres.empty?
294
- sql << " WHERE "
295
-
296
- first = true
297
- @wheres.each do |where|
298
- if first == true
299
- first = false
300
- else
301
- sql << " AND "
302
- end
303
-
304
- sql << where
305
- end
306
- end
307
-
308
- unless @groups.empty?
309
- sql << " GROUP BY "
310
-
311
- first = true
312
- @groups.each do |group|
313
- if first
314
- first = false
315
- else
316
- sql << ", "
317
- end
318
-
319
- sql << group
320
- end
321
- end
322
-
323
- unless @orders.empty?
324
- sql << " ORDER BY "
325
-
326
- first = true
327
- @orders.each do |order|
328
- if first
329
- first = false
330
- else
331
- sql << ", "
332
- end
333
-
334
- if @reverse_order
335
- if order.match(/\s+desc/i)
336
- order = order.gsub(/\s+desc/i, " ASC")
337
- elsif order.match(/\s+asc/i)
338
- order = order.gsub(/\s+asc/i, " DESC")
339
- else
340
- order = "#{order} DESC"
341
- end
342
- end
343
-
344
- sql << order
345
- end
346
- end
347
-
348
- if @limit && @offset
349
- sql << " LIMIT #{@offset.to_i}, #{@limit.to_i}"
350
- elsif @limit
351
- sql << " LIMIT #{@limit.to_i}"
352
- end
353
-
354
- sql.strip
292
+ BazaModels::Query::SqlGenerator.new(query: self).to_sql
355
293
  end
356
294
 
357
295
  def destroy_all
@@ -412,6 +350,10 @@ class BazaModels::Query
412
350
  pages_count
413
351
  end
414
352
 
353
+ def ransack(params)
354
+ BazaModels::Ransacker.new(class: @model, params: params, query: self)
355
+ end
356
+
415
357
  private
416
358
 
417
359
  def should_use_autoload?
@@ -471,4 +413,26 @@ private
471
413
  return value.id if value.is_a?(BazaModels::Model)
472
414
  value
473
415
  end
416
+
417
+ def value_with_mode(value)
418
+ if value.is_a?(Array)
419
+ sql = "IN ("
420
+
421
+ first = true
422
+ value.each do |val_i|
423
+ if first
424
+ first = false
425
+ else
426
+ sql << ", " unless first
427
+ end
428
+
429
+ sql << @db.sqlval(val_i)
430
+ end
431
+
432
+ sql << ")"
433
+ sql
434
+ else
435
+ "= #{@db.sqlval(value)}"
436
+ end
437
+ end
474
438
  end
@@ -18,14 +18,12 @@ class BazaModels::Query::Not
18
18
  @wheres << "`#{key}`.`#{hash_key}` != '#{@db.esc(hash_value)}'"
19
19
  end
20
20
  end
21
- else
22
- if value.is_a?(Array)
23
- values = value.map { |value_i| "'#{@db.esc(value_i)}'" }.join(",")
21
+ elsif value.is_a?(Array)
22
+ values = value.map { |value_i| "'#{@db.esc(value_i)}'" }.join(",")
24
23
 
25
- @wheres << "`#{@model.table_name}`.`#{key}` NOT IN (#{values})"
26
- else
27
- @wheres << "`#{@model.table_name}`.`#{key}` != '#{@db.esc(value)}'"
28
- end
24
+ @wheres << "`#{@model.table_name}`.`#{key}` NOT IN (#{values})"
25
+ else
26
+ @wheres << "`#{@model.table_name}`.`#{key}` != '#{@db.esc(value)}'"
29
27
  end
30
28
  end
31
29
 
@@ -0,0 +1,95 @@
1
+ class BazaModels::Query::SqlGenerator
2
+ def initialize(args)
3
+ @query = args.fetch(:query)
4
+
5
+ instance_variables = [
6
+ :selects, :joins, :wheres, :groups, :orders, :limit, :offset,
7
+ :model, :table_name, :reverse_order
8
+ ]
9
+ instance_variables.each do |instance_variable|
10
+ value = @query.instance_variable_get(:"@#{instance_variable}")
11
+ instance_variable_set(:"@#{instance_variable}", value)
12
+ end
13
+ end
14
+
15
+ def to_sql
16
+ sql = "SELECT "
17
+
18
+ if @selects.empty?
19
+ sql << "`#{@model.table_name}`.*"
20
+ else
21
+ sql << @selects.join(", ")
22
+ end
23
+
24
+ sql << " FROM `#{@model.table_name}`"
25
+
26
+ unless @joins.empty?
27
+ @joins.each do |join|
28
+ sql << " #{join}"
29
+ end
30
+ end
31
+
32
+ unless @wheres.empty?
33
+ sql << " WHERE "
34
+
35
+ first = true
36
+ @wheres.each do |where|
37
+ if first == true
38
+ first = false
39
+ else
40
+ sql << " AND "
41
+ end
42
+
43
+ sql << where
44
+ end
45
+ end
46
+
47
+ unless @groups.empty?
48
+ sql << " GROUP BY "
49
+
50
+ first = true
51
+ @groups.each do |group|
52
+ if first
53
+ first = false
54
+ else
55
+ sql << ", "
56
+ end
57
+
58
+ sql << group
59
+ end
60
+ end
61
+
62
+ unless @orders.empty?
63
+ sql << " ORDER BY "
64
+
65
+ first = true
66
+ @orders.each do |order|
67
+ if first
68
+ first = false
69
+ else
70
+ sql << ", "
71
+ end
72
+
73
+ if @reverse_order
74
+ if order =~ /\s+desc/i
75
+ order = order.gsub(/\s+desc/i, " ASC")
76
+ elsif order =~ /\s+asc/i
77
+ order = order.gsub(/\s+asc/i, " DESC")
78
+ else
79
+ order = "#{order} DESC"
80
+ end
81
+ end
82
+
83
+ sql << order
84
+ end
85
+ end
86
+
87
+ if @limit && @offset
88
+ sql << " LIMIT #{@offset.to_i}, #{@limit.to_i}"
89
+ elsif @limit
90
+ sql << " LIMIT #{@limit.to_i}"
91
+ end
92
+
93
+ sql.strip
94
+ end
95
+ end
@@ -1,30 +1,66 @@
1
1
  class BazaModels::Ransacker
2
+ AutoAutoloader.autoload_sub_classes(self, __FILE__)
3
+
4
+ attr_accessor :query
5
+ attr_reader :db, :klass
6
+
2
7
  def initialize(args)
3
8
  @klass = args.fetch(:class)
9
+ @db = @klass.db
4
10
  @params = args.fetch(:params)
5
- @query = @klass
11
+ @query = args.fetch(:query)
6
12
  end
7
13
 
8
14
  def result
9
- add_filters_to_query
15
+ add_filters_to_query unless @add_filters_to_query_executed
10
16
  @query
11
17
  end
12
18
 
13
19
  private
14
20
 
15
21
  def add_filters_to_query
22
+ @add_filters_to_query_executed = true
16
23
  return unless @params
17
24
 
18
25
  @params.each do |key, value|
19
26
  if (match = key.to_s.match(/\A(.+?)_eq\Z/))
20
- column_name = match[1]
21
- @query = @query.where("`#{@klass.table_name}`.`#{@klass.db.escape_column(column_name)}` = '#{@klass.db.esc(value)}'")
27
+ filter_eq(match[1], value)
22
28
  elsif (match = key.to_s.match(/\A(.+?)_cont\Z/))
23
- column_name = match[1]
24
- @query = @query.where("`#{@klass.table_name}`.`#{@klass.db.escape_column(column_name)}` LIKE '%#{@klass.db.esc(value)}%'")
29
+ filter_cont(match[1], value)
30
+ elsif key.to_s == "s"
31
+ match = value.to_s.match(/\A([A-z_\d]+)\s+(asc|desc)\Z/)
32
+ raise "Couldn't sort-match: #{value}" unless match
33
+ sort_by(column_name: match[1], sort_mode: match[2])
25
34
  else
26
35
  raise "Unknown modifier: #{key}"
27
36
  end
28
37
  end
29
38
  end
39
+
40
+ def filter_eq(column_name, value)
41
+ BazaModels::Ransacker::RelationshipScanner.new(
42
+ column_name: column_name,
43
+ mode: :eq,
44
+ ransacker: self,
45
+ value: value
46
+ )
47
+ end
48
+
49
+ def filter_cont(column_name, value)
50
+ BazaModels::Ransacker::RelationshipScanner.new(
51
+ column_name: column_name,
52
+ mode: :cont,
53
+ ransacker: self,
54
+ value: value
55
+ )
56
+ end
57
+
58
+ def sort_by(args)
59
+ BazaModels::Ransacker::RelationshipScanner.new(
60
+ column_name: args.fetch(:column_name),
61
+ mode: :sort,
62
+ ransacker: self,
63
+ value: args.fetch(:sort_mode)
64
+ )
65
+ end
30
66
  end
@@ -0,0 +1,110 @@
1
+ class BazaModels::Ransacker::RelationshipScanner
2
+ def initialize(args)
3
+ @join_parts = args[:join_parts] || []
4
+ @mode = args.fetch(:mode)
5
+ @ransacker = args.fetch(:ransacker)
6
+ @db = @ransacker.db
7
+ @value = args.fetch(:value)
8
+
9
+ if args[:column_name]
10
+ @name_parts = args.fetch(:column_name).split("_")
11
+ else
12
+ @name_parts = args.fetch(:name_parts)
13
+ end
14
+
15
+ if args[:klass]
16
+ @klass = args.fetch(:klass)
17
+ else
18
+ @klass = @ransacker.klass
19
+ end
20
+
21
+ parse_relation
22
+ end
23
+
24
+ private
25
+
26
+ def parse_relation
27
+ current_name = []
28
+ relationships = @klass.relationships
29
+
30
+ loop do
31
+ break if @name_parts.empty?
32
+ name_part = @name_parts.shift
33
+ current_name << name_part
34
+
35
+ relationships.each do |relationship_name, relationship|
36
+ next unless relationship_name.to_s == current_name.join("_")
37
+
38
+ @join_parts << relationship_name
39
+
40
+ BazaModels::Ransacker::RelationshipScanner.new(
41
+ join_parts: @join_parts,
42
+ klass: StringCases.constantize(relationship.fetch(:class_name)),
43
+ name_parts: @name_parts,
44
+ mode: @mode,
45
+ ransacker: @ransacker,
46
+ value: @value
47
+ )
48
+ return nil
49
+ end
50
+
51
+ name = current_name.join("_")
52
+ @klass.column_names.each do |column_name|
53
+ next unless name == column_name
54
+
55
+ add_filter_to_query(
56
+ column_name: column_name
57
+ )
58
+ return nil
59
+ end
60
+ end
61
+
62
+ raise "Could not figure out relationships based on name: #{current_name.join("_")}"
63
+ end
64
+
65
+ def join_parts_as_hash
66
+ return @join_parts.first if @join_parts.length == 1
67
+
68
+ hash = {}
69
+ current_hash = hash
70
+ join_parts = @join_parts.clone
71
+
72
+ loop do
73
+ break if join_parts.empty?
74
+ join_part = join_parts.shift
75
+
76
+ if join_parts.length == 1
77
+ current_hash[join_part] = join_parts.shift
78
+ break
79
+ else
80
+ current_hash[join_part] = {}
81
+ current_hash = current_hash.fetch(join_part)
82
+ end
83
+ end
84
+
85
+ hash
86
+ end
87
+
88
+ def add_filter_to_query(args)
89
+ @ransacker.query = @ransacker.query.joins(join_parts_as_hash) if @join_parts.any?
90
+
91
+ column_query = "#{@db.sep_col}#{@db.escape_column(args.fetch(:column_name))}#{@db.sep_col}"
92
+ table_query = "#{@db.sep_table}#{@db.escape_table(@klass.table_name)}#{@db.sep_table}"
93
+
94
+ if @mode == :cont
95
+ @ransacker.query = @ransacker
96
+ .query
97
+ .where("#{table_query}.#{column_query} LIKE #{@db.sep_val}%#{@klass.db.esc(@value)}%#{@db.sep_val}")
98
+ elsif @mode == :eq
99
+ @ransacker.query = @ransacker
100
+ .query
101
+ .where("#{table_query}.#{column_query} = #{@db.sep_val}#{@klass.db.esc(@value)}#{@db.sep_val}")
102
+ elsif @mode == :sort
103
+ @ransacker.query = @ransacker
104
+ .query
105
+ .order("#{table_query}.#{column_query} #{@value}")
106
+ else
107
+ raise "Unknown mode: #{@mode}"
108
+ end
109
+ end
110
+ end
@@ -140,6 +140,17 @@ describe "BazaModels::Model" do
140
140
  expect(user.changed?).to eq false
141
141
  end
142
142
 
143
+ it "#each" do
144
+ user.save!
145
+ count = 0
146
+ User.each do |user|
147
+ expect(user).to eq user
148
+ count += 1
149
+ end
150
+
151
+ expect(count).to eq 1
152
+ end
153
+
143
154
  it "doesnt care if initialized data has keys as strings" do
144
155
  user = User.new("email" => "test@example.com")
145
156
  expect(user.email).to eq "test@example.com"
@@ -29,9 +29,16 @@ describe BazaModels::Query do
29
29
  expect(query.to_a).to eq [user]
30
30
  expect(query.to_sql).to eq "SELECT `users`.* FROM `users` WHERE (`users`.`email`='test@example.com')"
31
31
  end
32
+
33
+ it "supports arrays as values" do
34
+ query = User.where(email: [user.email])
35
+
36
+ expect(query.to_a).to eq [user]
37
+ expect(query.to_sql).to eq "SELECT `users`.* FROM `users` WHERE `users`.`email` IN ('test@example.com')"
38
+ end
32
39
  end
33
40
 
34
- context '#joins' do
41
+ context "#joins" do
35
42
  before do
36
43
  user.save!
37
44
  role_admin.save!
@@ -152,4 +159,21 @@ describe BazaModels::Query do
152
159
  expect(sql).to end_with " DESC"
153
160
  end
154
161
  end
162
+
163
+ it "#new" do
164
+ user.save!
165
+ expect(user.roles.length).to eq 0
166
+ expect(user.roles.count).to eq 0
167
+
168
+ role = user.roles.new(role: "admin")
169
+ expect(role.new_record?).to eq true
170
+ expect(user.roles.length).to eq 1
171
+ expect(user.roles.count).to eq 0
172
+
173
+ role.save!
174
+
175
+ expect(user.roles.length).to eq 1
176
+ expect(user.roles.count).to eq 1
177
+ expect(user.roles.to_a).to eq [role]
178
+ end
155
179
  end
@@ -3,7 +3,11 @@ require "spec_helper"
3
3
  describe BazaModels::Query do
4
4
  include DatabaseHelper
5
5
 
6
- let!(:user) { User.create!(id: 1, email: "test@example.com") }
6
+ let!(:organization) { Organization.create!(id: 1, name: "Test organization") }
7
+ let!(:person) { Person.create!(id: 1, user: user) }
8
+ let!(:user) { User.create!(id: 1, organization: organization, email: "test@example.com") }
9
+ let!(:another_user) { User.create!(id: 2, organization: nil, email: "another_user@example.com") }
10
+ let!(:another_person) { Person.create!(id: 2, user: another_user) }
7
11
 
8
12
  it "eq" do
9
13
  expect(User.ransack(id_eq: 1).result.to_a).to eq [user]
@@ -12,4 +16,28 @@ describe BazaModels::Query do
12
16
  it "cont" do
13
17
  expect(User.ransack(email_cont: "test").result.to_a).to eq [user]
14
18
  end
19
+
20
+ it "s" do
21
+ query = User.ransack(s: "email asc")
22
+
23
+ expect(query.result.to_a).to eq [another_user, user]
24
+ expect(query.result.to_sql).to eq "SELECT `users`.* FROM `users` ORDER BY `users`.`email` asc"
25
+ end
26
+
27
+ it "sorts by sub column" do
28
+ query = Person.ransack(s: "user_email asc")
29
+
30
+ expect(query.result.to_a).to eq [another_person, person]
31
+ expect(query.result.to_sql).to include "`users`.`email` asc"
32
+ end
33
+
34
+ it "works with sub models" do
35
+ query = User.ransack(organization_name_cont: "Test")
36
+ expect(query.result.to_a).to eq [user]
37
+ end
38
+
39
+ it "works recursively with sub models" do
40
+ query = Person.ransack(user_organization_name_cont: "Test")
41
+ expect(query.result.to_a).to eq [person]
42
+ end
15
43
  end
@@ -67,10 +67,13 @@ module DatabaseHelper
67
67
  indexes: [:user_id]
68
68
  )
69
69
 
70
- @db.tables.create(:organizations, columns: [
71
- {name: :id, type: :int, primarykey: true, autoincr: true},
72
- {name: :name, type: :varchar}
73
- ])
70
+ @db.tables.create(
71
+ :organizations,
72
+ columns: [
73
+ {name: :id, type: :int, primarykey: true, autoincr: true},
74
+ {name: :name, type: :varchar}
75
+ ]
76
+ )
74
77
  end
75
78
 
76
79
  after do
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: baza_models
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.3
4
+ version: 0.0.4
5
5
  platform: ruby
6
6
  authors:
7
7
  - kaspernj
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2016-01-07 00:00:00.000000000 Z
11
+ date: 2016-04-07 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: array_enumerator
@@ -66,6 +66,20 @@ dependencies:
66
66
  - - ">="
67
67
  - !ruby/object:Gem::Version
68
68
  version: 0.0.1
69
+ - !ruby/object:Gem::Dependency
70
+ name: html_gen
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - ">="
74
+ - !ruby/object:Gem::Version
75
+ version: 0.0.12
76
+ type: :runtime
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - ">="
81
+ - !ruby/object:Gem::Version
82
+ version: 0.0.12
69
83
  - !ruby/object:Gem::Dependency
70
84
  name: rspec
71
85
  requirement: !ruby/object:Gem::Requirement
@@ -182,16 +196,16 @@ dependencies:
182
196
  name: rubocop
183
197
  requirement: !ruby/object:Gem::Requirement
184
198
  requirements:
185
- - - ">="
199
+ - - '='
186
200
  - !ruby/object:Gem::Version
187
- version: '0'
201
+ version: 0.37.0
188
202
  type: :development
189
203
  prerelease: false
190
204
  version_requirements: !ruby/object:Gem::Requirement
191
205
  requirements:
192
- - - ">="
206
+ - - '='
193
207
  - !ruby/object:Gem::Version
194
- version: '0'
208
+ version: 0.37.0
195
209
  - !ruby/object:Gem::Dependency
196
210
  name: orm_adapter
197
211
  requirement: !ruby/object:Gem::Requirement
@@ -216,6 +230,7 @@ extra_rdoc_files:
216
230
  files:
217
231
  - ".document"
218
232
  - ".rspec"
233
+ - ".rubocop.yml"
219
234
  - ".rubocop_todo.yml"
220
235
  - Gemfile
221
236
  - Gemfile.lock
@@ -224,14 +239,14 @@ files:
224
239
  - Rakefile
225
240
  - VERSION
226
241
  - baza_models.gemspec
227
- - config/best_project_practice_rubocop.yml
228
- - config/best_project_practice_rubocop_todo.yml
229
242
  - lib/baza_models.rb
230
243
  - lib/baza_models/autoloader.rb
231
244
  - lib/baza_models/baza_orm_adapter.rb
232
245
  - lib/baza_models/can_can_adapter.rb
233
246
  - lib/baza_models/class_translation.rb
234
247
  - lib/baza_models/errors.rb
248
+ - lib/baza_models/helpers.rb
249
+ - lib/baza_models/helpers/ransacker_helper.rb
235
250
  - lib/baza_models/model.rb
236
251
  - lib/baza_models/model/belongs_to_relations.rb
237
252
  - lib/baza_models/model/custom_validations.rb
@@ -246,7 +261,9 @@ files:
246
261
  - lib/baza_models/query.rb
247
262
  - lib/baza_models/query/inspector.rb
248
263
  - lib/baza_models/query/not.rb
264
+ - lib/baza_models/query/sql_generator.rb
249
265
  - lib/baza_models/ransacker.rb
266
+ - lib/baza_models/ransacker/relationship_scanner.rb
250
267
  - lib/baza_models/test_database_cleaner.rb
251
268
  - lib/baza_models/validators.rb
252
269
  - lib/baza_models/validators/base_validator.rb
@@ -308,7 +325,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
308
325
  version: '0'
309
326
  requirements: []
310
327
  rubyforge_project:
311
- rubygems_version: 2.4.0
328
+ rubygems_version: 2.2.2
312
329
  signing_key:
313
330
  specification_version: 4
314
331
  summary: ActiveRecord like models for the Baza database framework
@@ -1,2 +0,0 @@
1
- ---
2
- inherit_from: best_project_practice_rubocop_todo.yml
@@ -1,35 +0,0 @@
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