marty 3.1.0 → 4.0.0.rc2

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 (58) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +0 -7
  3. data/.rubocop.yml +0 -1
  4. data/.rubocop_todo.yml +15 -2
  5. data/Dockerfile.dummy +0 -3
  6. data/Gemfile +15 -21
  7. data/Gemfile.lock +289 -0
  8. data/app/components/marty/data_grid_view.rb +18 -68
  9. data/app/components/marty/extras/layout.rb +1 -1
  10. data/app/components/marty/grid.rb +1 -1
  11. data/app/components/marty/import_view.rb +3 -3
  12. data/app/components/marty/main_auth_app.rb +1 -11
  13. data/app/components/marty/report_form.rb +6 -6
  14. data/app/components/marty/script_form.rb +5 -5
  15. data/app/components/marty/script_tester.rb +2 -2
  16. data/app/components/marty/user_view.rb +9 -3
  17. data/app/models/marty/data_grid.rb +11 -16
  18. data/app/models/marty/event.rb +2 -2
  19. data/app/models/marty/promise.rb +4 -4
  20. data/app/models/marty/role_type.rb +1 -14
  21. data/app/services/marty/data_grid_view/save_grid.rb +2 -2
  22. data/app/services/marty/promises/delorean/create.rb +2 -2
  23. data/app/services/marty/promises/ruby/create.rb +2 -2
  24. data/config/locales/en.yml +2 -11
  25. data/docker-compose.dummy.yml +0 -1
  26. data/lib/marty/content_handler.rb +2 -2
  27. data/lib/marty/data_change.rb +1 -1
  28. data/lib/marty/data_conversion.rb +4 -3
  29. data/lib/marty/data_importer.rb +4 -4
  30. data/lib/marty/mcfly_model.rb +10 -7
  31. data/lib/marty/migrations.rb +1 -1
  32. data/lib/marty/monkey.rb +2 -2
  33. data/lib/marty/promise_job.rb +5 -5
  34. data/lib/marty/promise_proxy.rb +2 -2
  35. data/lib/marty/promise_ruby_job.rb +4 -4
  36. data/lib/marty/version.rb +1 -1
  37. data/marty.gemspec +18 -13
  38. data/other/marty/diagnostic/aws/ec2_instance.rb +2 -17
  39. data/other/marty/diagnostic/database.rb +2 -2
  40. data/other/marty/diagnostic/delayed_job_version.rb +1 -0
  41. data/spec/dummy/app/models/gemini/fannie_bup.rb +20 -13
  42. data/spec/dummy/config/application.rb +0 -1
  43. data/spec/dummy/config/initializers/secret_token.rb +1 -1
  44. data/spec/features/data_grid_spec.rb +46 -109
  45. data/spec/features/reporting_spec.rb +4 -4
  46. data/spec/features/rule_spec.rb +1 -1
  47. data/spec/features/scripting_spec.rb +3 -3
  48. data/spec/features/user_view_spec.rb +8 -17
  49. data/spec/lib/data_importer_spec.rb +8 -8
  50. data/spec/lib/mcfly_model_spec.rb +6 -6
  51. data/spec/models/data_grid_spec.rb +4 -19
  52. data/spec/spec_helper.rb +2 -2
  53. data/spec/support/netzke.rb +3 -4
  54. metadata +53 -50
  55. data/.ssh-docker/.keep +0 -0
  56. data/app/components/marty/data_grid_user_view.rb +0 -39
  57. data/db/migrate/108_add_data_grid_perms.rb +0 -16
  58. data/other/marty/diagnostic/aws/error.rb +0 -8
@@ -115,7 +115,7 @@ module Layout
115
115
  end
116
116
 
117
117
  def get_sorter(col)
118
- lambda { |rel, dir| rel.order(Arel.sql("#{col}::text #{dir}")) }
118
+ lambda { |rel, dir| rel.order("#{col}::text #{dir.to_s}") }
119
119
  end
120
120
 
121
121
  ######################################################################
@@ -52,7 +52,7 @@ class Marty::Grid < ::Netzke::Grid::Base
52
52
 
53
53
  def get_json_sorter(json_col, field)
54
54
  lambda do |r, dir|
55
- r.order(Arel.sql("#{json_col} ->> '#{field}' " + dir.to_s))
55
+ r.order("#{json_col} ->> '#{field}' " + dir.to_s)
56
56
  end
57
57
  end
58
58
 
@@ -84,10 +84,10 @@ class Marty::ImportView < Marty::Form
84
84
  result << messages if messages
85
85
 
86
86
  client.set_result result.join('<br/>')
87
- rescue Marty::DataImporter::Error => e
87
+ rescue Marty::DataImporter::Error => exc
88
88
  result = [
89
- "Import failed on line(s): #{e.lines.join(', ')}",
90
- "Error: #{e.to_s}",
89
+ "Import failed on line(s): #{exc.lines.join(', ')}",
90
+ "Error: #{exc.to_s}",
91
91
  ]
92
92
 
93
93
  client.set_result '<font color="red">' + result.join('<br/>') + '</font>'
@@ -4,7 +4,6 @@ require 'marty/api_log_view'
4
4
  require 'marty/config_view'
5
5
  require 'marty/data_grid_view'
6
6
  require 'marty/schedule_jobs_dashboard'
7
- require 'marty/data_grid_user_view'
8
7
  require 'marty/event_view'
9
8
  require 'marty/import_type_view'
10
9
  require 'marty/new_posting_window'
@@ -97,7 +96,6 @@ class Marty::MainAuthApp < Marty::AuthApp
97
96
  icon_cls: 'fa fa-window-restore glyph',
98
97
  menu: [
99
98
  :data_grid_view,
100
- :data_grid_user_view,
101
99
  :reporting,
102
100
  :scripting,
103
101
  :promise_view,
@@ -239,14 +237,7 @@ class Marty::MainAuthApp < Marty::AuthApp
239
237
  end
240
238
 
241
239
  action :data_grid_view do |a|
242
- a.text = I18n.t('data_grid_view')
243
- a.handler = :netzke_load_component_by_action
244
- a.icon_cls = 'fa fa-table glyph'
245
- a.disabled = !self.class.has_any_perm?
246
- end
247
-
248
- action :data_grid_user_view do |a|
249
- a.text = I18n.t('data_grid_user_view')
240
+ a.text = I18n.t('data_grid_view', default: 'Data Grids')
250
241
  a.handler = :netzke_load_component_by_action
251
242
  a.icon_cls = 'fa fa-table glyph'
252
243
  a.disabled = !self.class.has_any_perm?
@@ -397,7 +388,6 @@ class Marty::MainAuthApp < Marty::AuthApp
397
388
  component :config_view
398
389
 
399
390
  component :data_grid_view
400
- component :data_grid_user_view
401
391
 
402
392
  component :event_view
403
393
 
@@ -61,10 +61,10 @@ class Marty::ReportForm < Marty::Form
61
61
 
62
62
  begin
63
63
  engine.evaluate(node, 'result', d_params)
64
- rescue StandardError => e
65
- Marty::Util.logger.error "run_eval failed: #{e.backtrace}"
64
+ rescue StandardError => exc
65
+ Marty::Util.logger.error "run_eval failed: #{exc.backtrace}"
66
66
 
67
- res = Delorean::Engine.grok_runtime_exception(e)
67
+ res = Delorean::Engine.grok_runtime_exception(exc)
68
68
  res['backtrace'] =
69
69
  res['backtrace'].map { |m, line, fn| "#{m}:#{line} #{fn}" }.join('\n')
70
70
  res
@@ -156,15 +156,15 @@ class Marty::ReportForm < Marty::Form
156
156
  raise 'bad form items' unless items.is_a?(Array)
157
157
  raise 'bad format' unless
158
158
  Marty::ContentHandler::GEN_FORMATS.member?(format)
159
- rescue StandardError => e
159
+ rescue StandardError => exc
160
160
  c.title = 'ERROR'
161
161
  c.items =
162
162
  [
163
163
  {
164
- field_label: 'exception',
164
+ field_label: 'Exception',
165
165
  xtype: :displayfield,
166
166
  name: 'displayfield1',
167
- value: "<span style=\"color:red;\">#{e}</span>"
167
+ value: "<span style=\"color:red;\">#{exc}</span>"
168
168
  },
169
169
  ]
170
170
  return
@@ -83,10 +83,10 @@ class Marty::ScriptForm < Marty::Form
83
83
  begin
84
84
  dev = Marty::Tag.find_by_name('DEV')
85
85
  Marty::ScriptSet.new(dev).parse_check(script.name, data['body'])
86
- rescue Delorean::ParseError => e
87
- client.netzke_notify e.message
86
+ rescue Delorean::ParseError => exc
87
+ client.netzke_notify exc.message
88
88
  client.netzke_apply_form_errors({})
89
- client.set_line_error(e.line)
89
+ client.set_line_error(exc.line)
90
90
  return
91
91
  end
92
92
 
@@ -120,8 +120,8 @@ class Marty::ScriptForm < Marty::Form
120
120
  'PrettyScript',
121
121
  rep_params)
122
122
  client.get_report(path)
123
- rescue StandardError => e
124
- return client.netzke_notify "ERROR: #{e}"
123
+ rescue StandardError => exc
124
+ return client.netzke_notify "ERROR: #{exc}"
125
125
  end
126
126
  end
127
127
 
@@ -75,8 +75,8 @@ class Marty::ScriptTester < Marty::Form
75
75
  client.set_result result.join('<br/>')
76
76
  rescue SystemStackError
77
77
  return client.netzke_notify 'System Stack Error'
78
- rescue StandardError => e
79
- res = Delorean::Engine.grok_runtime_exception(e)
78
+ rescue StandardError => exc
79
+ res = Delorean::Engine.grok_runtime_exception(exc)
80
80
 
81
81
  result = ["Error: #{res['error']}", 'Backtrace:'] +
82
82
  res['backtrace'].map { |m, line, fn| "#{m}:#{line} #{fn}" }
@@ -33,7 +33,9 @@ module Marty; class UserView < Marty::Grid
33
33
  def self.set_roles(roles, user)
34
34
  roles = [] unless roles.present?
35
35
 
36
- roles = ::Marty::RoleType.from_nice_names(roles)
36
+ roles = Marty::RoleType.get_all.select do |role|
37
+ roles.include?(I18n.t("roles.#{role}", default: role))
38
+ end
37
39
 
38
40
  roles_in_user = user.user_roles.map(&:role)
39
41
  roles_to_delete = roles_in_user - roles
@@ -150,10 +152,14 @@ module Marty; class UserView < Marty::Grid
150
152
  c.type = :string
151
153
 
152
154
  c.getter = lambda do |r|
153
- Marty::RoleType.to_nice_names(r.user_roles.map(&:role))
155
+ r.user_roles.map do |ur|
156
+ I18n.t("roles.#{ur.role}", default: ur.role)
157
+ end
154
158
  end
155
159
 
156
- store = ::Marty::RoleType.to_nice_names(::Marty::RoleType::VALUES.sort)
160
+ store = ::Marty::RoleType.get_all.sort.map do |role|
161
+ I18n.t("roles.#{role}", default: role)
162
+ end
157
163
 
158
164
  c.editor_config = {
159
165
  multi_select: true,
@@ -253,7 +253,8 @@ class Marty::DataGrid < Marty::Base
253
253
 
254
254
  # private method used to cache lookup_grid_distinct_entry_h result
255
255
  delorean_fn :lookup_grid_h_priv,
256
- private: true, cache: true, sig: 4 do |pt, dgh, h, distinct|
256
+ to_hash: false, private: true, cache: true, sig: 4 do |pt, dgh, h, distinct|
257
+
257
258
  lookup_grid_distinct_entry_h(
258
259
  pt, h, dgh, nil, true, false, distinct)['result']
259
260
  end
@@ -270,9 +271,9 @@ class Marty::DataGrid < Marty::Base
270
271
  end
271
272
 
272
273
  def self.lookup_grid_distinct_entry_h(
273
- pt, h, dgh, visited = nil, follow = true,
274
- return_grid_data = false, distinct = true
275
- )
274
+ pt, h, dgh, visited = nil, follow = true,
275
+ return_grid_data = false, distinct = true
276
+ )
276
277
 
277
278
  # Perform grid lookup, if result is another data_grid, and follow is true,
278
279
  # then perform lookup on the resulting grid. Allows grids to be nested
@@ -359,19 +360,13 @@ class Marty::DataGrid < Marty::Base
359
360
  def export_array
360
361
  # add data type metadata row if not default
361
362
  lenstr = 'lenient' if lenient
363
+ typestr = data_type unless [nil, DEFAULT_DATA_TYPE].member?(data_type) &&
364
+ !constraint.present?
365
+
366
+ len_dt = [lenstr, typestr].compact.join(' ')
362
367
 
363
- typestr = data_type unless [nil, DEFAULT_DATA_TYPE].member?(data_type)
364
- len_type = [lenstr, typestr].compact.join(' ')
365
-
366
- meta_rows = if (lenient || typestr) && constraint
367
- [[len_type, constraint]]
368
- elsif lenient || typestr
369
- [[len_type]]
370
- elsif constraint
371
- [['', constraint]]
372
- else
373
- []
374
- end
368
+ meta_rows = len_dt.present? || constraint.present? ?
369
+ [[len_dt, constraint]] : []
375
370
 
376
371
  meta_rows += metadata.map do |inf|
377
372
  [inf['attr'], inf['type'], inf['dir'], inf['rs_keep'] || '']
@@ -311,7 +311,7 @@ SQL
311
311
 
312
312
  def self.cleanup
313
313
  where('start_dt < ?', Time.zone.now - 48.hours).delete_all
314
- rescue StandardError => e
315
- Marty::Util.logger.error("event GC error: #{e}")
314
+ rescue StandardError => exc
315
+ Marty::Util.logger.error("event GC error: #{exc}")
316
316
  end
317
317
  end
@@ -132,9 +132,9 @@ class Marty::Promise < Marty::Base
132
132
  # log "OFF0 #{Process.pid} #{last}"
133
133
  begin
134
134
  work_off_job(job)
135
- rescue StandardError => e
135
+ rescue StandardError => exc
136
136
  # log "OFFERR #{exc}"
137
- error = exception_to_result(e)
137
+ error = exception_to_result(exc)
138
138
  last.set_result(error)
139
139
  end
140
140
  # log "OFF1 #{Process.pid} #{last}"
@@ -215,8 +215,8 @@ class Marty::Promise < Marty::Base
215
215
  'start_dt < ? AND parent_id IS NULL',
216
216
  DateTime.now - (all ? 0.hours : 4.hours)
217
217
  ).destroy_all
218
- rescue StandardError => e
219
- Marty::Util.logger.error("promise GC error: #{e}")
218
+ rescue StandardError => exc
219
+ Marty::Util.logger.error("promise GC error: #{exc}")
220
220
  end
221
221
 
222
222
  def exception_to_result(promise:, exception:)
@@ -5,19 +5,6 @@ class Marty::RoleType < Marty::Base
5
5
  'admin',
6
6
  'user_manager',
7
7
  'dev',
8
- 'viewer',
9
- 'data_grid_editor'
8
+ 'viewer'
10
9
  ]
11
-
12
- def self.from_nice_names(roles)
13
- Marty::RoleType.get_all.select do |role|
14
- roles.include?(I18n.t("roles.#{role}", default: role))
15
- end
16
- end
17
-
18
- def self.to_nice_names(roles)
19
- roles.map do |role|
20
- I18n.t("roles.#{role}", default: role)
21
- end
22
- end
23
10
  end
@@ -15,9 +15,8 @@ module Marty
15
15
  end
16
16
 
17
17
  def self.call(params)
18
+ user_perm = Marty::DataGridView.get_edit_save_permission
18
19
  rec_id = params['record_id']
19
- dg = Marty::DataGrid.mcfly_pt('infinity').find_by(group_id: rec_id)
20
- user_perm = Marty::DataGridView.get_edit_permission(dg.permissions)
21
20
  data = params['data']
22
21
  raise GridError.new('entered with view permissions', data, rec_id) if
23
22
  user_perm == 'view'
@@ -25,6 +24,7 @@ module Marty
25
24
  data_as_array = data.map do |row|
26
25
  row.keys.map { |key| row[key] }
27
26
  end
27
+ dg = Marty::DataGrid.mcfly_pt('infinity').find_by(group_id: rec_id)
28
28
  vcnt = dg.metadata.select { |md| md['dir'] == 'v' }.count
29
29
  hcnt = dg.metadata.select { |md| md['dir'] == 'h' }.count
30
30
  cur_data_dim = [dg.data.length, dg.data[0].length]
@@ -31,9 +31,9 @@ module Marty
31
31
  )
32
32
 
33
33
  job = Delayed::Job.enqueue(promise_job)
34
- rescue StandardError => e
34
+ rescue StandardError => exc
35
35
  # log "CALLERR #{exc}"
36
- res = ::Delorean::Engine.grok_runtime_exception(e)
36
+ res = ::Delorean::Engine.grok_runtime_exception(exc)
37
37
  promise.set_start
38
38
  promise.set_result(res)
39
39
  # log "CALLERRSET #{res}"
@@ -29,8 +29,8 @@ module Marty
29
29
  )
30
30
 
31
31
  job = Delayed::Job.enqueue(promise_job)
32
- rescue StandardError => e
33
- res = { 'error' => e.message }
32
+ rescue StandardError => exc
33
+ res = { 'error' => exc.message }
34
34
  promise.set_start
35
35
  promise.set_result(res)
36
36
  raise
@@ -18,10 +18,8 @@ en:
18
18
  create_posting: Create
19
19
  api_auth: API Authorization
20
20
  event_view: Event View
21
- data_grid_view: Data Grids Admin
22
- data_grid: Data Grids Admin
23
- data_grid_user: Data Grids
24
- data_grid_user_view: Data Grids
21
+ data_grid_view: Data Grids
22
+ data_grid: Data Grids
25
23
 
26
24
  data_import_view:
27
25
  import: Import
@@ -32,7 +30,6 @@ en:
32
30
  admin: Admin
33
31
  dev: Developer
34
32
  user_manager: User Manager
35
- data_grid_editor: Data Grid Editor
36
33
 
37
34
  posting_types:
38
35
  BASE: BASE
@@ -179,9 +176,3 @@ en:
179
176
  grid:
180
177
  base:
181
178
  view_record: "%{model} (Read-only)"
182
-
183
- data_grid_view_perms:
184
- perm_view: Can View
185
- perm_edit_data: Can Edit Data
186
- perm_edit_all: Can Edit All
187
-
@@ -24,7 +24,6 @@ services:
24
24
  - .:/opt/app:delegated
25
25
  - '.bash_history.docker:/root/.bash_history'
26
26
  - '.pry_history.docker:/root/.pry_history'
27
- - '.ssh-docker:/root/.ssh'
28
27
  - bundle_box:/bundle_box
29
28
  tty: true
30
29
  stdin_open: true
@@ -34,9 +34,9 @@ module Marty::ContentHandler
34
34
  else
35
35
  res, format = { error: "Unknown format: #{format}" }.to_json, 'json'
36
36
  end
37
- rescue StandardError => e
37
+ rescue StandardError => exc
38
38
  res, format =
39
- { error: "Failed conversion #{format}: #{e}" }.to_json, 'json'
39
+ { error: "Failed conversion #{format}: #{exc}" }.to_json, 'json'
40
40
  end
41
41
 
42
42
  type, disposition = GEN_FORMATS[format]
@@ -219,7 +219,7 @@ class Marty::DataChange
219
219
  # "different".
220
220
  conv =
221
221
  Marty::DataConversion.convert_row(klass, input, ts)
222
- rescue StandardError => e
222
+ rescue StandardError => exc
223
223
  only_input << input
224
224
  next
225
225
  end
@@ -1,7 +1,7 @@
1
1
  class Marty::DataConversion
2
2
  EXCEL_START_DATE = Date.parse('1/1/1900') - 2
3
3
 
4
- FLOAT_PAT = /\A-?\d+(\.?\d+)?([eE][-+]?[0-9]+)?\z/
4
+ FLOAT_PAT = /^-?\d+(\.\d+)?$/
5
5
 
6
6
  PATS = {
7
7
  integer: /^-?\d+(\.0+)?$/,
@@ -58,13 +58,13 @@ class Marty::DataConversion
58
58
  begin
59
59
  v =~ FLOAT_PAT ? EXCEL_START_DATE + v.to_f :
60
60
  Mcfly.is_infinity(v) ? 'infinity' : v.to_date
61
- rescue StandardError => e
61
+ rescue StandardError => exc
62
62
  raise "date conversion failed for #{v.inspect}}"
63
63
  end
64
64
  when :datetime
65
65
  begin
66
66
  Mcfly.is_infinity(v) ? 'infinity' : v.to_datetime
67
- rescue StandardError => e
67
+ rescue StandardError => exc
68
68
  raise "datetime conversion failed for #{v.inspect}}"
69
69
  end
70
70
  when :numrange, :int4range, :int8range
@@ -98,6 +98,7 @@ class Marty::DataConversion
98
98
 
99
99
  @@associations[klass] ||= klass.reflect_on_all_associations.
100
100
  each_with_object({}) do |assoc, h|
101
+
101
102
  h[assoc.name.to_s] = {
102
103
  assoc_keys: assoc_keys(assoc.klass),
103
104
  assoc_class: assoc.klass,
@@ -77,9 +77,9 @@ module Marty
77
77
 
78
78
  Marty::DataConversion.create_or_update(klass, row, dt)
79
79
  end
80
- rescue StandardError => e
80
+ rescue StandardError => exc
81
81
  # to find problems with the importer, comment out the rescue block
82
- raise Error.new(e.to_s, [eline])
82
+ raise Error.new(exc.to_s, [eline])
83
83
  end
84
84
 
85
85
  ids = {}
@@ -96,8 +96,8 @@ module Marty
96
96
  # Validate affected rows if necessary
97
97
  klass.send(validation_function.to_sym, ids.keys) if
98
98
  validation_function
99
- rescue StandardError => e
100
- raise Error.new(e.to_s, [])
99
+ rescue StandardError => exc
100
+ raise Error.new(exc.to_s, [])
101
101
  end
102
102
 
103
103
  remainder_ids = cleaner_ids - ids.keys
@@ -6,8 +6,10 @@ module Mcfly::Model
6
6
  end
7
7
 
8
8
  module ClassMethods
9
- def hash_if_necessary(q, private)
10
- !private && q.is_a?(ActiveRecord::Base) ? make_openstruct(q) : q
9
+ def hash_if_necessary(q, to_hash)
10
+ return make_hash(q) if to_hash && q.is_a?(ActiveRecord::Base)
11
+
12
+ q
11
13
  end
12
14
 
13
15
  def base_mcfly_lookup(name, options = {}, &block)
@@ -41,7 +43,7 @@ module Mcfly::Model
41
43
 
42
44
  q = q.first if q.respond_to?(:first) && options[:mode] == :first
43
45
 
44
- hash_if_necessary(q, options[:private])
46
+ hash_if_necessary(q, options.fetch(:to_hash, false))
45
47
  end
46
48
  end
47
49
 
@@ -55,7 +57,7 @@ module Mcfly::Model
55
57
 
56
58
  def gen_mcfly_lookup(name, attrs, options = {})
57
59
  raise "bad options #{options.keys}" unless
58
- (options.keys - [:mode, :cache, :private]).empty?
60
+ (options.keys - [:mode, :cache, :private, :to_hash]).empty?
59
61
 
60
62
  mode = options.fetch(:mode, :first)
61
63
 
@@ -86,6 +88,7 @@ module Mcfly::Model
86
88
 
87
89
  base_mcfly_lookup(name, options + { sig: attrs.length + 1,
88
90
  mode: mode }) do |_t, *attr_list|
91
+
89
92
  attr_list_ids = attr_list.each_with_index.map do |_x, i|
90
93
  assoc.member?(attrs[i]) ?
91
94
  (attr_list[i] && attr_list[i].id) : attr_list[i]
@@ -134,7 +137,7 @@ module Mcfly::Model
134
137
 
135
138
  pc_name = "pc_#{name}".to_sym
136
139
 
137
- gen_mcfly_lookup(pc_name, pc_attrs, options + { private: true })
140
+ gen_mcfly_lookup(pc_name, pc_attrs, options + { private: true, to_hash: false })
138
141
 
139
142
  lpi = attrs.keys.index rel_attr
140
143
 
@@ -142,7 +145,7 @@ module Mcfly::Model
142
145
  raise "need #{rel_attr} argument" unless lpi
143
146
 
144
147
  # cache if mode is not nil
145
- priv = options[:private]
148
+ to_hash = options.fetch(:to_hash, false)
146
149
 
147
150
  # cache if mode is not explicitly set to nil or cache is true
148
151
  cache = options.fetch(:cache) { options.fetch(:mode, :first) }
@@ -165,7 +168,7 @@ module Mcfly::Model
165
168
  send(cat_attr_id)
166
169
 
167
170
  q = send(pc_name, ts, *args)
168
- hash_if_necessary(q, priv)
171
+ hash_if_necessary(q, to_hash)
169
172
  end
170
173
  end
171
174
  end