source_route 0.5.0 → 0.6.0

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: a04414f0a3fc78965a7b84b519771817b01aaf41
4
- data.tar.gz: 7ace385216b4e224e7f551b00b4626a35e93b8cd
3
+ metadata.gz: 744e671ef5af028f1bc8432482de55af9ab6c0a2
4
+ data.tar.gz: 32c60f705394c3a93d78a0bb27add38648ef36b5
5
5
  SHA512:
6
- metadata.gz: b146be3ce3eea65dfd2e80a16d45ad2a0a25fad09a53cf05adecb66c4eed30199ff3197367a4380f3faf42bc44177d84bbcf31a9cb0fa709cad81f1f28c20795
7
- data.tar.gz: f8877f910f84a3ace2bcded0cc5ebadcc91cb95375aef2c41f514f24faadc27ddb5ffb9c1dcfed592f3965947555c9a954a93cae825403047a7a3b3347a7569f
6
+ metadata.gz: 7656687526f1f1c241a9a868d5337457466757ab02117fc1a2f5c936c8138eca4760e0693d0c6648c38dd0046b7dcecccabb0bc1421234ffa1303c17e644fbf4
7
+ data.tar.gz: b9c93cc92da3800396820350d41cf0a1caa8b36f78444899eae3e572d6689ff8393d63d93edd0971dbc8e995137d91470ddb1efccb62328066571e5d7269b32b
data/.gitignore CHANGED
@@ -21,5 +21,6 @@ tmp
21
21
  *.a
22
22
  mkmf.log
23
23
  .ruby-version
24
+ .projectile
24
25
 
25
- call_and_return_in_sample_app.html
26
+ *html
data/README.md CHANGED
@@ -26,9 +26,9 @@ Or install it yourself as:
26
26
 
27
27
  SourceRoute.trace(output_format: :console, event: :c_call) { 'abc'.upcase }
28
28
 
29
- #### In rails console
29
+ #### In rails console or test code
30
30
 
31
- SourceRoute.trace(defined_class: :ActiveRecord, output_format: :html) { User.new }
31
+ SourceRoute.trace(defined_class: 'ActiveRecord::Attribute', output_format: :html) { User.new }
32
32
 
33
33
  It will generate a html file, open it and you can get the trace of User.new
34
34
 
@@ -42,10 +42,11 @@ you will get a different trace file.
42
42
  full_feature
43
43
  filename 'tmp/capture_wanted.html'
44
44
  end
45
- .... # here is your code
45
+ # Following is your code
46
+ ....
46
47
  ....
47
48
  ....
48
- # add it after your tracked code, it will output the trace into a html file
49
+ # add it after your tracked code, it output the trace into a html file
49
50
  SourceRoute.output_html
50
51
 
51
52
  Same as the previous example, you will get a html file showing the code trace.
@@ -67,16 +68,7 @@ see full usage in examples/study_callback.rb
67
68
 
68
69
  ## Why
69
70
 
70
- I always wanna upgrade my ruby(rails) skills. But everytime when I looking for workaround from stack overflow I feel frustration.
71
-
72
- To get solution or workaround from google or stack overflow is suitable when I'm a ruby starter or task is urgent. But it's not really helpful to levelup my skills.
73
-
74
- The way how I solve problem define my skills' border and depth. So if I slove problems by search google and stack overflow with workarounds, I mostly just increase my experiences on ruby(rails). But if I solve problems directly, in most case, I can say my skill border extends.
75
-
76
- That's why I create this gem. To solve problems directly, I need to know what happened in call or return traces.
77
- Fortunately ruby 2.0 introduce a new feature TracePoint to easily trace inner event. But it's not easily to be used as daily tool. This gem tries to make tracing more readable and easily in our daily work.
78
-
79
- Finally, I expect my working style can changes from searching workaround from internet to reading code trace(then more easily check source) directly. I hope it can help you too.
71
+ Help me read source code and solve problem directly.
80
72
 
81
73
  ## Test
82
74
 
@@ -93,14 +85,17 @@ Finally, I expect my working style can changes from searching workaround from in
93
85
 
94
86
  ### TODO
95
87
 
96
- call and return event combined together is no useful. So traces data structure need changed.
88
+ add syntax to monitor when obj was passed into method
97
89
 
98
- global disable some class from monitor
90
+ animation when node hide
99
91
 
100
- Cleanup Code and remove useless comments.
92
+ use concurrent-ruby to speed up
101
93
 
94
+ call and return event combined together is no useful. So traces data structure need changed.
102
95
  Dynamic indent when new child level comes.
103
96
 
97
+ global disable some class from monitor
98
+
104
99
  Add debug option to provide more verbose messages of what has happened
105
100
 
106
101
  if instance val contains symbol as value, the json output will be string. It could be confused others.
@@ -8,15 +8,15 @@ require "source_route/core_ext"
8
8
  require "source_route/version"
9
9
  require "source_route/config"
10
10
  require "source_route/proxy"
11
- require "source_route/jsonify"
12
11
  require "source_route/generate_result"
13
12
  require "source_route/tp_result"
14
- require "source_route/tp_result_chain"
15
- require "source_route/tp_filter"
13
+ require "source_route/trace_chain"
14
+ require "source_route/trace_filter"
16
15
  require 'source_route/json_overrides/activerecord_associations_association'
17
16
 
18
17
  begin
19
18
  if Rails
19
+ require 'source_route/rails_plugins/source_track_middleware'
20
20
  ActiveSupport.on_load(:after_initialize, yield: true) do
21
21
  # make it respond to to_s. In rails source, almost all of its methods are removed, including to_s.
22
22
  module ActiveSupport
@@ -44,7 +44,11 @@ module SourceRoute
44
44
  end
45
45
 
46
46
  def disable
47
- proxy.tp.disable
47
+ if proxy.tp.nil?
48
+ puts 'Error: You try to call disable on nil object, do you define SourceRoute ?'
49
+ else
50
+ proxy.tp.disable
51
+ end
48
52
  end
49
53
 
50
54
  def enable(match = nil, &block)
@@ -1,13 +1,15 @@
1
1
  module SourceRoute
2
- TP_FILTER = [:defined_class, :method_id, :path, :lineno].freeze
3
- TP_FILTER_METHODS = (TP_FILTER + TP_FILTER.map { |tpf| "#{tpf}_not".to_sym }).freeze
2
+ TRACE_FILTER = [:defined_class, :method_id, :path, :lineno].freeze
3
+ TRACE_FILTER_METHODS = (TRACE_FILTER + TRACE_FILTER.map { |tpf| "#{tpf}_not".to_sym }).freeze
4
4
 
5
+ # todo: Here is not good. Tried to compatible with different options
6
+ # but code becomes hard to maintenance
5
7
  class Config
6
8
 
7
9
  DIRECT_ATTRS = [:event, :full_feature, :debug,
8
10
  :output_format, :show_additional_attrs,
9
11
  :filename, :include_local_var, :include_instance_var,
10
- :import_return_to_call
12
+ :import_return_to_call, :track_params
11
13
  ]
12
14
 
13
15
  attr_accessor *DIRECT_ATTRS
@@ -38,6 +40,7 @@ module SourceRoute
38
40
  def has_call_and_return_event
39
41
  event.include? :return and event.include? :call
40
42
  end
43
+
41
44
  end # END Config
42
45
 
43
46
  class BlockConfigParser
@@ -69,12 +72,20 @@ module SourceRoute
69
72
  end
70
73
  end
71
74
 
75
+ # Track when the value was passed into method
76
+ def track_params(value)
77
+ ret_params[:track_params] = value.object_id
78
+ ret_params[:show_additional_attrs] = :path
79
+ ret_params[:include_local_var] = true
80
+ ret_params[:event] = :call
81
+ end
82
+
72
83
  # override
73
84
  def output_format(data = nil, &block)
74
85
  ret_params[:output_format] = block_given? ? block : data
75
86
  end
76
87
 
77
- TP_FILTER_METHODS.each do |m|
88
+ TRACE_FILTER_METHODS.each do |m|
78
89
  define_method m do |*v|
79
90
  ret_params[m] = v
80
91
  end
@@ -85,7 +96,7 @@ module SourceRoute
85
96
  module ParamsConfigParser
86
97
  extend self
87
98
 
88
- TP_FILTER.each do |m|
99
+ TRACE_FILTER.each do |m|
89
100
  define_method m do |v|
90
101
  @config.positives[m] = Array(v).flatten.map(&:to_s).join('|')
91
102
  end
@@ -99,7 +110,7 @@ module SourceRoute
99
110
  @config = Config.new
100
111
  params.each do |k, v|
101
112
  @config.send("#{k}=", v) if Config::DIRECT_ATTRS.include? k.to_sym
102
- send(k, v) if (TP_FILTER_METHODS + [:full_feature]).include? k.to_sym
113
+ send(k, v) if (TRACE_FILTER_METHODS + [:full_feature]).include? k.to_sym
103
114
  end
104
115
  @config.formulize
105
116
  end
@@ -18,9 +18,7 @@ module SourceRoute
18
18
  end
19
19
  # TODO: any exception triggered in render method will be absorb totally, how to fix it?
20
20
  html_output_str = slim_template.render(proxy.result_builder)
21
- File.open(filename, 'w') do |f|
22
- f << html_output_str
23
- end
21
+ File.write(filename, html_output_str)
24
22
  end
25
23
 
26
24
  end # END Html
@@ -3,13 +3,13 @@ html
3
3
  head
4
4
  title Source Route Result
5
5
  link rel="stylesheet" href="https://cdn.rawgit.com/Urigo/angular-spinkit/master/build/angular-spinkit.min.css"
6
- link rel="stylesheet" href="https://cdn.rawgit.com/raykin/json-formatter/dist/dist/json-formatter.css"
7
- link rel="stylesheet" href="http://oss.maxcdn.com/semantic-ui/2.1.8/semantic.min.css"
6
+ link rel="stylesheet" href="https://cdn.rawgit.com/raykin/json-formatter/master/dist/json-formatter.min.css"
7
+ link rel="stylesheet" href="https://cdn.jsdelivr.net/semantic-ui/2.2.6/semantic.min.css"
8
8
 
9
- script async=true src="http://cdnjs.cloudflare.com/ajax/libs/lodash.js/3.10.0/lodash.js"
9
+ script src="http://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.2/lodash.js"
10
10
  script src="http://cdnjs.cloudflare.com/ajax/libs/jquery/2.1.4/jquery.min.js"
11
- script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.4.6/angular.min.js"
12
- script async=true src="http://oss.maxcdn.com/semantic-ui/2.1.8/semantic.min.js"
11
+ script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.6.0/angular.min.js"
12
+ script async=true src="https://cdn.jsdelivr.net/semantic-ui/2.2.6/semantic.min.js"
13
13
 
14
14
  css:
15
15
  .call-level-0 {}
@@ -57,7 +57,7 @@ html
57
57
  a.ui.top.right.attached.label.mini(ng-show="::containsDetail(trace)" ng-click="showMoreDetail = !showMoreDetail")
58
58
  i.sidebar.icon
59
59
  .header
60
- span.bold>(ng-bind="::trace.order_id")
60
+ span.bold.ui.label>(ng-bind="::(trace.order_id || '>')")
61
61
  span(ng-bind="::tpSelfList[trace.tp_self_refer]")
62
62
  i.circle.icon.grey(style="font-size: 0.3em")
63
63
  span.method-value(ng-bind="::trace.method_id")
@@ -68,7 +68,7 @@ html
68
68
  / workaround for return_value is 'false' and return_value always to be string when existed
69
69
  .meta(ng-if="trace.hasOwnProperty('return_value')")
70
70
  i.icon.pointing.right.small
71
- json-formatter(json="::trace.return_value" title="{{::trace.return_value_class}}" style="display: inline-block")
71
+ json-formatter(json="::trimString(trace.return_value, 30)" title="{{::trace.return_value_class}}" style="display: inline-block")
72
72
  .description(style="margin-left: 20px")
73
73
  .details.right.floated(ng-if="showMoreDetail")
74
74
  .ui.segments(style="border-color: blue")
@@ -89,7 +89,7 @@ html
89
89
  json-formatter(open="1" json="::plusTraceAttrs[trace.order_id]" title="TracePoint")
90
90
 
91
91
  script src="https://cdn.rawgit.com/Urigo/angular-spinkit/master/build/angular-spinkit.min.js"
92
- script src="https://cdn.rawgit.com/raykin/json-formatter/dist/dist/json-formatter.js"
92
+ script src="https://cdn.rawgit.com/raykin/json-formatter/master/dist/json-formatter.js"
93
93
  // script async src="https://ajax.googleapis.com/ajax/libs/angularjs/1.4.3/angular-sanitize.js"
94
94
 
95
95
  javascript:
@@ -179,10 +179,11 @@ html
179
179
 
180
180
  combinedAttrs = function(trace) {
181
181
  var attrs = {}
182
+
182
183
  if (trace.hasOwnProperty('lineno') && trace.hasOwnProperty('path')) {
183
- attrs.method_defined_on = trace.path + ":" + trace.lineno;
184
+ attrs.method_defined_on = _.replace(trace.path, /.*gems\//, '') + ":" + trace.lineno;
184
185
  } else if (trace.hasOwnProperty('path')) {
185
- attrs.method_defined_on = trace.path;
186
+ attrs.method_defined_on = _.replace(trace.path, /.*gems\//, '');
186
187
  }
187
188
  if (trace.hasOwnProperty('defined_class')) {
188
189
  attrs.method_defined_in = trace.defined_class;
@@ -231,13 +232,13 @@ html
231
232
 
232
233
  $scope.hasChild = function() {
233
234
  return _.find($scope.traces, function(trace) {
234
- return _.contains(trace.parent_ids, $scope.trace.order_id)
235
+ return _.includes(trace.parent_ids, $scope.trace.order_id)
235
236
  });
236
237
  }
237
238
  })
238
239
 
239
240
  .data-collect
240
241
  / dont use local_trace_data.to_json, because ActiveSupport override it and can introduce unexpected crash for some data
241
- #trace-data(data-trace="#{jsonify_tp_result_chain}"
242
+ #trace-data(data-trace="#{jsonify_trace_chain}"
242
243
  data-tp-events="#{jsonify_events}"
243
244
  data-tp-self-caches="#{jsonify_tp_self_caches}")
@@ -0,0 +1,105 @@
1
+ doctype html
2
+ html
3
+ head
4
+ title Source Route Result
5
+ link rel="stylesheet" href="https://cdn.jsdelivr.net/semantic-ui/2.2.10/semantic.min.css"
6
+
7
+ script src="http://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.2/lodash.js"
8
+ script src="https://unpkg.com/vue"
9
+ script src="https://code.jquery.com/jquery-3.2.1.min.js"
10
+ script async=true src="https://cdn.jsdelivr.net/semantic-ui/2.2.10/semantic.min.js"
11
+
12
+ css:
13
+ .call-level-0 {}
14
+ .item.trace.call-level-1 { padding-left: 50px }
15
+ .item.trace.call-level-2 { padding-left: 100px }
16
+ .item.trace.call-level-3 { padding-left: 150px }
17
+ .item.trace.call-level-4 { padding-left: 200px }
18
+ .item.trace.call-level-5 { padding-left: 250px }
19
+ .item.trace.call-level-6 { padding-left: 300px }
20
+ .item.trace.call-level-7 { padding-left: 300px }
21
+ .trace .main .ui.label .icon {
22
+ margin-right: 0;
23
+ }
24
+ // level more than 7 seems not reasonable
25
+
26
+ body
27
+
28
+ .ui.menu.pointing.stackable.attached#top-menu
29
+ .ui.container
30
+ // .item
31
+ // a.navbar-brand(href="#" @click="resetTraceFilter()") ALL
32
+ .item(v-for="event in tpEvents" :class="{active: event == traceFilter.event}")
33
+ a(href="#" @click="traceFilter.event = event" v-text="event")
34
+ .item
35
+ .ui.buttons
36
+ button.ui.labeled.icon.button.olive(@click="outlineTrace()" :class="{loading: outlineTraceLoading}")
37
+ i.angle.double.right.icon
38
+ span OutLine
39
+ .or
40
+ button.ui.right.labeled.icon.button.green(@click="expandAllTrace()" :class="{loading: expandAllTraceLoading}")
41
+ i.angle.double.down.icon
42
+ span Expand
43
+ .right.menu
44
+ .item
45
+ span Trace Count
46
+ .ui.teal.left.pointing.label(v-text="currentCounter()")
47
+
48
+ .ui.container#traces
49
+ .row
50
+ .ui.relaxed.items(:class="{{traceFilter.event}}")
51
+ // track by trace.order_id doesn't always work. because order_id doesn't always exists
52
+ .item.trace(v-for="trace in traces | filter:traceFilter:true | filter:childParentFilterFn" :class="callLevelClass(trace)" ng-controller="TpTraceCtrl")
53
+ .content(ng-init="showMoreDetail = false" style="display: flex; justify-content: space-between; align-items: center;")
54
+ .ui.segment.padded.main
55
+ a.ui.top.right.attached.label.mini(v-show="containsDetail(trace)" @click="showMoreDetail = !showMoreDetail")
56
+ i.sidebar.icon
57
+ .header
58
+ span.bold.ui.label>(v-text="(trace.order_id || '>')")
59
+ span(v-text="tpSelfList[trace.tp_self_refer]")
60
+ i.circle.icon.grey(style="font-size: 0.3em")
61
+ span.method-value(v-text="trace.method_id")
62
+ a.ui.bottom.right.attached.label.mini(v-if="hasChild()" @click="toggleChild()" :class="{loading: togglingChild}")
63
+ i.icon.angle.down(v-show="trace.childOpened" style="font-size: 10px")
64
+ i.icon.angle.right(ng-hide="trace.childOpened" style="font-size: 14px")
65
+ / pulse-spinner(v-show="togglingChild")
66
+ / workaround for return_value is 'false' and return_value always to be string when existed
67
+ .meta(v-if="trace.hasOwnProperty('return_value')")
68
+ i.icon.pointing.right.small
69
+ json-formatter(json="trimString(trace.return_value, 30)" title="{{trace.return_value_class}}" style="display: inline-block")
70
+ .description(style="margin-left: 20px")
71
+ .details.right.floated(v-if="showMoreDetail")
72
+ .ui.segments(style="border-color: blue")
73
+ .ui.segment(v-if="trace.params_var")
74
+ .ui.teal.left.ribbon.label Parameters
75
+ json-formatter(open="1" json="trace.params_var" title="{{trace.params_var_class}}")
76
+ .ui.segment(v-if="trace.hasOwnProperty('return_value')")
77
+ .ui.grey.left.ribbon.label Return Value
78
+ json-formatter(open="1" json="trace.return_value" title="{{trace.return_value_class}}")
79
+ .ui.segment(v-if="trace.local_var")
80
+ .ui.teal.left.ribbon.label Local Variables
81
+ json-formatter(open="1" json="trace.local_var" title="{{trace.local_var_class}}")
82
+ .ui.segment(v-if="trace.instance_var")
83
+ .ui.blue.left.ribbon.label Instance Variables
84
+ json-formatter(open="1" json="trace.instance_var" title="{{trace.instance_var_class}}")
85
+ .ui.segment(v-if="containsOtherAttrs(trace)")
86
+ .ui.orange.left.ribbon.label Trace Attributes
87
+ json-formatter(open="1" json="plusTraceAttrs[trace.order_id]" title="TracePoint")
88
+
89
+ javascript:
90
+ var top_menu = new Vue({
91
+ el: '#top-menu',
92
+ data: $("#trace-data").data('tp-events')
93
+ });
94
+
95
+ // var traces = new Vue({
96
+ // el: '#traces',
97
+ // data: $("#trace-data").data('trace')
98
+
99
+ // });
100
+
101
+ .data-collect
102
+ // dont use local_trace_data.to_json, because ActiveSupport override it and can introduce unexpected crash for some data
103
+ #trace-data(data-trace="#{jsonify_trace_chain}"
104
+ data-tp-events="#{jsonify_events}"
105
+ data-tp-self-caches="#{jsonify_tp_self_caches}")
@@ -8,10 +8,10 @@ module SourceRoute
8
8
  # 5. Output data with correct format
9
9
  class GenerateResult
10
10
 
11
- attr_reader :tp_result_chain, :tp_self_caches, :collected_data
11
+ attr_reader :trace_chain, :tp_self_caches, :collected_data
12
12
 
13
13
  extend Forwardable
14
- def_delegators :@tp_result_chain, :import_return_value_to_call_chain, :treeize_call_chain
14
+ def_delegators :@trace_chain, :import_return_value_to_call_chain, :treeize_call_chain
15
15
 
16
16
  # see event description in TracePoint API Doc
17
17
  DEFAULT_ATTRS = {
@@ -32,7 +32,7 @@ module SourceRoute
32
32
 
33
33
  def initialize(proxy)
34
34
  @proxy = proxy
35
- @tp_result_chain = TpResultChain.new
35
+ @trace_chain = TraceChain.new
36
36
  @tp_self_caches = []
37
37
  end
38
38
 
@@ -64,11 +64,11 @@ module SourceRoute
64
64
  when :html
65
65
  # we cant generate html right now becase the tp callback is still in process
66
66
  # so we gather data into array
67
- @tp_result_chain.push(TpResult.new(tp_ins))
67
+ @trace_chain.push(TpResult.new(tp_ins))
68
68
  when :silence, :none
69
69
  # do nothing at now
70
70
  when :test
71
- @tp_result_chain.push(TpResult.new(tp_ins))
71
+ @trace_chain.push(TpResult.new(tp_ins))
72
72
  when :stack_overflow
73
73
  console_stack_overflow
74
74
  when Proc
@@ -88,21 +88,22 @@ module SourceRoute
88
88
  end
89
89
 
90
90
  def jsonify_events
91
- Oj.dump(@proxy.config.event.map(&:to_s))
91
+ JSON.dump(@proxy.config.event.map(&:to_s))
92
92
  end
93
93
 
94
- def jsonify_tp_result_chain
95
- value = tp_result_chain.chain.map(&:to_hash)
96
- Oj.dump(value, mode: :compat)
94
+ def jsonify_trace_chain
95
+ value = trace_chain.chain.map(&:to_hash)
96
+ JSON.dump(value)
97
97
 
98
- # tp_result_chain.to_json
99
- # json_array = tp_result_chain.map { |result| Jsonify.dump(result) }
98
+ # not worked
99
+ # trace_chain.to_json
100
+ # json_array = trace_chain.map { |result| JSON.dump(result) }
100
101
  # '[ ' + json_array.join(',') + ' ]'
101
102
  end
102
103
 
103
104
  def jsonify_tp_self_caches
104
- Oj.dump(tp_self_caches.clone
105
- .map(&:to_s))
105
+ JSON.dump(tp_self_caches.clone
106
+ .map(&:to_s))
106
107
  end
107
108
 
108
109
  private
@@ -1,33 +1,39 @@
1
1
  if defined? ActiveRecord
2
- class ActiveRecord::Associations::Association
3
-
4
- # dump association can trigger ActiveSupport::JSON::Encoding::CircularReferenceError when use rails ~> 4.0.1
5
- # I try other json gems to fix it, but all failed. That's why I override it here.
6
- def to_json(options = nil)
7
- Oj.dump(to_s)
2
+ module ActiveRecord
3
+ module Associations
4
+ class Association
5
+ # dump association can trigger ActiveSupport::JSON::Encoding::CircularReferenceError when use rails ~> 4.0.1
6
+ # I try other json gems to fix it, but all failed. That's why I override it here.
7
+ def to_json(options = nil)
8
+ Oj.dump(to_s)
9
+ end
10
+ end
8
11
  end
9
- end
10
12
 
11
- class ActiveRecord::Relation
13
+ class Relation
12
14
 
13
- # Override original method.
14
- # becasue it trigger SystemStackError: stack level too deep when use rails ~> 4.1.0
15
- # def as_json(options = nil) #:nodoc:
16
- # binding.pry
17
- # Json.dump(inspect)
18
- # end
15
+ # Override original method.
16
+ # becasue it trigger SystemStackError: stack level too deep when use rails ~> 4.1.0
17
+ # def as_json(options = nil) #:nodoc:
18
+ # binding.pry
19
+ # Json.dump(inspect)
20
+ # end
19
21
 
20
- end
22
+ end
21
23
 
22
- class ActiveRecord::Base
24
+ class Base
25
+ def source_route_display
26
+ to_s
27
+ end
23
28
 
24
- # dump association can trigger ActiveSupport::JSON::Encoding::CircularReferenceError when use rails ~> 4.0.1
25
- # I try other json gems to fix it, but all failed. That's why I override it here.
26
- #
27
- # it can affect the json output of rails AR. Not good solution
28
- # def to_json(options = nil)
29
- # JSON.dump(to_s)
30
- # end
31
- end
29
+ # dump association can trigger ActiveSupport::JSON::Encoding::CircularReferenceError when use rails ~> 4.0.1
30
+ # I try other json gems to fix it, but all failed. That's why I override it here.
31
+ #
32
+ # it can affect the json output of rails AR. Not good solution
33
+ # def to_json(options = nil)
34
+ # JSON.dump(to_s)
35
+ # end
36
+ end # END Base
32
37
 
38
+ end # END ActiveRecord
33
39
  end