baza_models 0.0.3 → 0.0.4

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