yiffspace 0.1.7 → 0.2.0

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 (127) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +4 -10
  3. data/README.md +18 -1
  4. data/Rakefile +6 -7
  5. data/lib/yiffspace/version.rb +1 -1
  6. data/lib/yiffspace.rb +26 -27
  7. metadata +104 -139
  8. data/app/assets/config/yiffspace_manifest.js +0 -1
  9. data/app/assets/stylesheets/yiffspace/application.css +0 -30
  10. data/app/controllers/yiff_space/application_controller.rb +0 -6
  11. data/app/helpers/yiff_space/application_helper.rb +0 -6
  12. data/app/models/yiff_space/application_record.rb +0 -7
  13. data/app/views/layouts/yiff_space/application.html.erb +0 -17
  14. data/app/views/yiff_space/error.html.erb +0 -3
  15. data/lib/yiffspace/concerns/active_record_extensions.rb +0 -45
  16. data/lib/yiffspace/concerns/api_methods.rb +0 -101
  17. data/lib/yiffspace/concerns/attribute_matchers.rb +0 -100
  18. data/lib/yiffspace/concerns/attribute_methods.rb +0 -39
  19. data/lib/yiffspace/concerns/concurrency_methods.rb +0 -20
  20. data/lib/yiffspace/concerns/conditional_includes.rb +0 -43
  21. data/lib/yiffspace/concerns/current_methods.rb +0 -60
  22. data/lib/yiffspace/concerns/has_bit_flags.rb +0 -59
  23. data/lib/yiffspace/concerns/user_class_methods.rb +0 -32
  24. data/lib/yiffspace/concerns/user_methods.rb +0 -77
  25. data/lib/yiffspace/concerns/user_name_methods.rb +0 -53
  26. data/lib/yiffspace/concerns/user_resolvable_methods.rb +0 -38
  27. data/lib/yiffspace/config_builder.rb +0 -192
  28. data/lib/yiffspace/configuration/images.rb +0 -22
  29. data/lib/yiffspace/configuration.rb +0 -116
  30. data/lib/yiffspace/core_ext/active_record/all.rb +0 -8
  31. data/lib/yiffspace/core_ext/active_record/cross_join_lateral.rb +0 -7
  32. data/lib/yiffspace/core_ext/active_record/cross_unnest.rb +0 -7
  33. data/lib/yiffspace/core_ext/active_record/left_join_lateral.rb +0 -7
  34. data/lib/yiffspace/core_ext/active_record/left_unnest.rb +0 -7
  35. data/lib/yiffspace/core_ext/active_record/unnest.rb +0 -8
  36. data/lib/yiffspace/core_ext/active_record/where_chain.rb +0 -6
  37. data/lib/yiffspace/core_ext/all.rb +0 -8
  38. data/lib/yiffspace/core_ext/arel/all.rb +0 -4
  39. data/lib/yiffspace/core_ext/arel/cross_join_lateral.rb +0 -21
  40. data/lib/yiffspace/core_ext/arel/left_join_lateral.rb +0 -21
  41. data/lib/yiffspace/core_ext/enumerable/all.rb +0 -3
  42. data/lib/yiffspace/core_ext/enumerable/parallel.rb +0 -7
  43. data/lib/yiffspace/core_ext/hash/all.rb +0 -3
  44. data/lib/yiffspace/core_ext/hash/to_open_hash.rb +0 -7
  45. data/lib/yiffspace/core_ext/object/all.rb +0 -4
  46. data/lib/yiffspace/core_ext/object/to_b.rb +0 -7
  47. data/lib/yiffspace/core_ext/object/truthy_falsy.rb +0 -7
  48. data/lib/yiffspace/core_ext/string/all.rb +0 -3
  49. data/lib/yiffspace/core_ext/string/sql.rb +0 -7
  50. data/lib/yiffspace/engine.rb +0 -23
  51. data/lib/yiffspace/extensions/active_record/cross_join_lateral.rb +0 -23
  52. data/lib/yiffspace/extensions/active_record/cross_unnest.rb +0 -15
  53. data/lib/yiffspace/extensions/active_record/left_join_lateral.rb +0 -24
  54. data/lib/yiffspace/extensions/active_record/left_unnest.rb +0 -15
  55. data/lib/yiffspace/extensions/active_record/unnest.rb +0 -20
  56. data/lib/yiffspace/extensions/active_record/where_chain.rb +0 -107
  57. data/lib/yiffspace/extensions/arel/nodes/cross_join_lateral.rb +0 -17
  58. data/lib/yiffspace/extensions/arel/nodes/left_join_lateral.rb +0 -17
  59. data/lib/yiffspace/extensions/arel/table/cross_join_lateral.rb +0 -15
  60. data/lib/yiffspace/extensions/arel/table/left_join_lateral.rb +0 -15
  61. data/lib/yiffspace/extensions/arel/visitors/postgresql/cross_join_lateral.rb +0 -19
  62. data/lib/yiffspace/extensions/arel/visitors/postgresql/left_join_lateral.rb +0 -23
  63. data/lib/yiffspace/extensions/enumerable/parallel.rb +0 -39
  64. data/lib/yiffspace/extensions/hash/to_open_hash.rb +0 -15
  65. data/lib/yiffspace/extensions/object/to_b.rb +0 -22
  66. data/lib/yiffspace/extensions/object/truthy_falsy.rb +0 -35
  67. data/lib/yiffspace/extensions/string/sql.rb +0 -21
  68. data/lib/yiffspace/images/avatar/base.rb +0 -41
  69. data/lib/yiffspace/images/avatar/discord.rb +0 -37
  70. data/lib/yiffspace/images/avatar/gravatar.rb +0 -21
  71. data/lib/yiffspace/images/avatar.rb +0 -33
  72. data/lib/yiffspace/images/banner/base.rb +0 -41
  73. data/lib/yiffspace/images/banner/discord.rb +0 -37
  74. data/lib/yiffspace/images/banner.rb +0 -33
  75. data/lib/yiffspace/images.rb +0 -6
  76. data/lib/yiffspace/include/active_record_extensions.rb +0 -5
  77. data/lib/yiffspace/include/all.rb +0 -31
  78. data/lib/yiffspace/include/api_methods.rb +0 -5
  79. data/lib/yiffspace/include/attribute_matchers.rb +0 -5
  80. data/lib/yiffspace/include/attribute_methods.rb +0 -5
  81. data/lib/yiffspace/include/cache.rb +0 -5
  82. data/lib/yiffspace/include/concurrency_methods.rb +0 -5
  83. data/lib/yiffspace/include/conditional_includes.rb +0 -5
  84. data/lib/yiffspace/include/current.rb +0 -5
  85. data/lib/yiffspace/include/current_methods.rb +0 -5
  86. data/lib/yiffspace/include/duration_parser.rb +0 -5
  87. data/lib/yiffspace/include/has_bit_flags.rb +0 -5
  88. data/lib/yiffspace/include/helpers.rb +0 -5
  89. data/lib/yiffspace/include/open_hash.rb +0 -5
  90. data/lib/yiffspace/include/parameter_builder.rb +0 -5
  91. data/lib/yiffspace/include/parse_value.rb +0 -5
  92. data/lib/yiffspace/include/query_builder.rb +0 -5
  93. data/lib/yiffspace/include/query_dsl.rb +0 -5
  94. data/lib/yiffspace/include/query_helper.rb +0 -5
  95. data/lib/yiffspace/include/routes.rb +0 -5
  96. data/lib/yiffspace/include/table_builder.rb +0 -5
  97. data/lib/yiffspace/include/trace_logger.rb +0 -5
  98. data/lib/yiffspace/include/u2id.rb +0 -5
  99. data/lib/yiffspace/include/user_attribute.rb +0 -5
  100. data/lib/yiffspace/include/user_class_methods.rb +0 -5
  101. data/lib/yiffspace/include/user_like.rb +0 -5
  102. data/lib/yiffspace/include/user_methods.rb +0 -5
  103. data/lib/yiffspace/include/user_name_methods.rb +0 -5
  104. data/lib/yiffspace/include/user_resolvable.rb +0 -5
  105. data/lib/yiffspace/include/user_resolvable_methods.rb +0 -5
  106. data/lib/yiffspace/search/query_builder.rb +0 -83
  107. data/lib/yiffspace/search/query_dsl.rb +0 -119
  108. data/lib/yiffspace/search/query_helper.rb +0 -49
  109. data/lib/yiffspace/serializers/avatar_serializer.rb +0 -21
  110. data/lib/yiffspace/serializers/banner_serializer.rb +0 -21
  111. data/lib/yiffspace/serializers/user_resolvable_serializer.rb +0 -21
  112. data/lib/yiffspace/utils/cache.rb +0 -40
  113. data/lib/yiffspace/utils/current.rb +0 -43
  114. data/lib/yiffspace/utils/duration_parser.rb +0 -24
  115. data/lib/yiffspace/utils/helpers.rb +0 -25
  116. data/lib/yiffspace/utils/open_hash.rb +0 -63
  117. data/lib/yiffspace/utils/parameter_builder.rb +0 -121
  118. data/lib/yiffspace/utils/parse_value.rb +0 -174
  119. data/lib/yiffspace/utils/routes.rb +0 -28
  120. data/lib/yiffspace/utils/set_env_constraint.rb +0 -18
  121. data/lib/yiffspace/utils/table_builder.rb +0 -169
  122. data/lib/yiffspace/utils/trace_logger.rb +0 -91
  123. data/lib/yiffspace/utils/user_attribute.rb +0 -272
  124. data/lib/yiffspace/utils/user_like.rb +0 -8
  125. data/lib/yiffspace/utils/user_resolvable.rb +0 -61
  126. data/lib/yiffspace/utils/user_to_id.rb +0 -11
  127. data/lib/yiffspace/utils.rb +0 -6
@@ -1,63 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require("active_support/hash_with_indifferent_access")
4
-
5
- module YiffSpace
6
- module Utils
7
- class OpenHash < ActiveSupport::HashWithIndifferentAccess
8
- def initialize(constructor = nil, respond_to_missing: true)
9
- super(constructor)
10
- @respond_to_missing = respond_to_missing
11
- end
12
-
13
- def respond_to_missing?(name, include_private = false)
14
- return true if @respond_to_missing
15
-
16
- name = name.to_s
17
- key?(name) || name.end_with?("=") || super
18
- end
19
-
20
- def method_missing(name, *args)
21
- if name.end_with?("=")
22
- public_send(:[]=, name.to_s.chomp("=").to_sym, args.first)
23
- elsif key?(name)
24
- public_send(:[], name)
25
- elsif @respond_to_missing
26
- nil
27
- else
28
- super
29
- end
30
- end
31
-
32
- def self.from(hash = nil, recursive: true, respond_to_missing: true, **kwargs)
33
- hash = kwargs if hash.nil? && kwargs.any?
34
- raise(ArgumentError, "no hash provided") if hash.nil?
35
-
36
- oh = OpenHash.new(respond_to_missing: respond_to_missing)
37
- hash.each do |key, value|
38
- if recursive && value.is_a?(Hash)
39
- oh[key] = OpenHash.from(value, recursive: recursive)
40
- elsif recursive && value.is_a?(Array)
41
- oh[key] = value.map { |v| v.is_a?(Hash) ? OpenHash.from(v, recursive: recursive, respond_to_missing: respond_to_missing) : v }
42
- else
43
- oh[key] = value
44
- end
45
- end
46
- oh
47
- end
48
-
49
- def marshal_dump
50
- [to_h, @respond_to_missing]
51
- end
52
-
53
- def marshal_load(data)
54
- hash, @respond_to_missing = data
55
- replace(hash)
56
- end
57
-
58
- def self.from_array(items, **)
59
- items.map { |item| from(item, **) }
60
- end
61
- end
62
- end
63
- end
@@ -1,121 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module YiffSpace
4
- module Utils
5
- class ParameterBuilder
6
- def self.serial_parameters(only_string, object, options = {})
7
- only_array = split_only_string(only_string)
8
- get_only_hash(only_array, object, options)
9
- end
10
-
11
- def self.get_only_hash(only_array, object, options = {}, seen_objects = [])
12
- return {} if object.nil?
13
-
14
- is_root = seen_objects.empty?
15
- only_hash = { only: [], include: [], methods: [] }
16
- available_includes = object.available_includes
17
- attributes, methods = object.api_attributes(options[:user]).partition { |attr| object.has_attribute?(attr) }
18
- methods -= available_includes
19
- # Attributes and/or methods may be included in the final pass, but not includes
20
- seen_objects << object.class.name
21
- underscore = false
22
- only_array.each do |item|
23
- if item == "_"
24
- underscore = true
25
- next
26
- end
27
- match = item.match(/(\w+)\[(.+?)\]$/)
28
- item = (match || [])[1] || item
29
- item_sym = item.to_sym
30
- was_seen = inclusion_seen?(item, object.class, seen_objects)
31
- if match && available_includes.include?(item_sym) && (!was_seen || is_root)
32
- item_object = object.send(item_sym)
33
- next if item_object.nil?
34
-
35
- item_object = item_object[0] if item_object.is_a?(ActiveRecord::Relation)
36
- item_array = split_only_string(match[2])
37
- item_hash = get_only_hash(item_array, item_object, options, seen_objects.clone)
38
- only_hash[:include] << { item_sym => item_hash }
39
- elsif available_includes.include?(item_sym) && (!was_seen || is_root)
40
- only_hash[:include] << item_sym
41
- elsif attributes.include?(item_sym)
42
- only_hash[:only] << item_sym
43
- elsif methods.include?(item_sym)
44
- only_hash[:methods] << item_sym
45
- only_hash[:only] << item_sym
46
- end
47
- end
48
- only_hash.delete(:include) if only_hash[:include].empty?
49
- only_hash.delete(:methods) if only_hash[:methods].empty?
50
- only_hash[:only].unshift("_") if underscore
51
- only_hash
52
- end
53
-
54
- def self.includes_parameters(only_string, model_name)
55
- return [] if only_string.blank?
56
-
57
- only_array = split_only_string(only_string)
58
- get_includes_array(only_array, model_name)
59
- end
60
-
61
- def self.get_includes_array(only_array, model_name, seen_objects = [])
62
- is_root = seen_objects.empty?
63
- include_array = []
64
- model = Kernel.const_get(model_name)
65
- available_includes = model.available_includes
66
- # Attributes and/or methods may be included in the final pass, but not includes
67
- seen_objects << model_name
68
- only_array.each do |item|
69
- match = item.match(/(\w+)\[(.+?)\]$/)
70
- item = (match || [])[1] || item
71
- item_sym = item.to_sym
72
- was_seen = inclusion_seen?(item, model, seen_objects)
73
- if match && available_includes.include?(item_sym) && (!was_seen || is_root)
74
- item_array = split_only_string(match[2])
75
- model.associated_models(item).each do |m|
76
- item_array = get_includes_array(item_array, m, seen_objects.clone)
77
- include_array << (item_array.empty? ? item_sym : { item_sym => item_array })
78
- end
79
- elsif available_includes.include?(item_sym) && (!was_seen || is_root)
80
- include_array << item_sym
81
- end
82
- end
83
- include_array
84
- end
85
-
86
- def self.inclusion_seen?(inclusion, class_object, seen_objects)
87
- if class_object.reflections[inclusion]
88
- inclusion_class = class_object.reflections[inclusion].class_name
89
- max_seen = (class_object.multiple_includes.include?(inclusion.to_sym) ? 1 : 0)
90
- seen_objects.count(inclusion_class) > max_seen
91
- else
92
- false
93
- end
94
- end
95
-
96
- def self.split_only_string(only_string)
97
- only_array = []
98
- offset = 0
99
- position = 0
100
- level = 0
101
- loop do
102
- str = only_string[Range.new(position, -1)]
103
- match = str.match(/[,\[\]]/)
104
- break unless match
105
-
106
- start_pos, end_pos = match.offset(0)
107
- if match[0] == "," && level.zero?
108
- only_array << only_string[Range.new(offset, position + start_pos - 1)]
109
- offset = position + end_pos
110
- elsif match[0] == "["
111
- level += 1
112
- elsif match[0] == "]"
113
- level -= 1
114
- end
115
- position += end_pos
116
- end
117
- only_array << only_string[Range.new(offset, -1)]
118
- end
119
- end
120
- end
121
- end
@@ -1,174 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module YiffSpace
4
- module Utils
5
- module ParseValue
6
- MAX_INT = 2_147_483_647
7
- MIN_INT = -2_147_483_648
8
- extend(self)
9
-
10
- def date_range(target)
11
- case target
12
- # 10_yesterweeks_ago, 10yesterweekago
13
- when /\A(\d{1,2})_?yester(week|month|year)s?_?ago\z/
14
- yester_range($1.to_i, $2)
15
- when /\Ayester(week|month|year)\z/
16
- yester_range(1, $1)
17
- when /\A(day|week|month|year)\z/
18
- [:gte, Time.zone.now - 1.send($1)]
19
- # 10_weeks_ago, 10w
20
- when /\A(\d+)_?(s(econds?)?|mi(nutes?)?|h(ours?)?|d(ays?)?|w(eeks?)?|mo(nths?)?|y(ears?)?)_?(ago)?\z/i
21
- [:gte, time_string(target)]
22
- else
23
- range(target, :date)
24
- end
25
- end
26
-
27
- def range_fudged(range, type)
28
- result = range(range, type)
29
- if result[0] == :eq
30
- new_min = [(result[1] * 0.95).to_i, MIN_INT].max
31
- new_max = [(result[1] * 1.05).to_i, MAX_INT].min
32
- [:between, new_min, new_max]
33
- else
34
- result
35
- end
36
- end
37
-
38
- def range(range, type = :integer)
39
- if range.start_with?("<=")
40
- [:lte, cast(range.delete_prefix("<="), type)]
41
-
42
- elsif range.start_with?("..")
43
- [:lte, cast(range.delete_prefix(".."), type)]
44
-
45
- elsif range.start_with?("<")
46
- [:lt, cast(range.delete_prefix("<"), type)]
47
-
48
- elsif range.start_with?(">=")
49
- [:gte, cast(range.delete_prefix(">="), type)]
50
-
51
- elsif range.end_with?("..")
52
- [:gte, cast(range.delete_suffix(".."), type)]
53
-
54
- elsif range.start_with?(">")
55
- [:gt, cast(range.delete_prefix(">"), type)]
56
-
57
- elsif range.include?("..")
58
- left, right = range.split("..", 2)
59
- [:between, cast(left, type), cast(right, type)]
60
-
61
- elsif range.include?(",")
62
- [:in, range.split(",").first(YiffSpace.config.max_multi_count.call).map { |x| cast(x, type) }]
63
-
64
- else
65
- [:eq, cast(range, type)]
66
-
67
- end
68
- end
69
-
70
- RANGE_INVERSIONS = {
71
- lte: :gte,
72
- lt: :gt,
73
- gte: :lte,
74
- gt: :lt,
75
- }.freeze
76
-
77
- def invert_range(range)
78
- # >10 <=> <10
79
- range[0] = RANGE_INVERSIONS[range[0]] || range[0]
80
- # 10..20 <=> 20..10
81
- range[1], range[2] = range[2], range[1] if range[0] == :between
82
- range
83
- end
84
-
85
- private
86
-
87
- def cast(object, type)
88
- case type
89
- when :integer
90
- object.to_i.clamp(MIN_INT, MAX_INT)
91
-
92
- when :float
93
- # Floats obviously have a different range but this is good enough
94
- object.to_f.clamp(MIN_INT, MAX_INT)
95
-
96
- when :date, :datetime
97
- case object
98
- when "today"
99
- return Date.current
100
- when "yesterday"
101
- return Date.yesterday
102
- when "decade"
103
- return Date.current - 10.years
104
- when /\A(day|week|month|year)\z/
105
- return Date.current - 1.send($1.to_sym)
106
- end
107
-
108
- ago = time_string(object)
109
- return ago if ago.present?
110
-
111
- begin
112
- Time.zone.parse(object)
113
- rescue ArgumentError
114
- nil
115
- end
116
-
117
- when :age
118
- time_string(object)
119
-
120
- when :ratio
121
- left, right = object.split(":", 10)
122
-
123
- if right && right.to_f != 0.0
124
- (left.to_f / right.to_f).round(10)
125
- elsif right
126
- 0.0
127
- else
128
- object.to_f.round(2)
129
- end
130
-
131
- when :filesize
132
- size = object.downcase
133
- if size.end_with?("kb")
134
- size.to_f.kilobytes
135
- elsif size.end_with?("mb")
136
- size.to_f.megabytes
137
- else
138
- size.to_f
139
- end.to_i
140
- end
141
- end
142
-
143
- def yester_range(count, unit)
144
- origin = Date.current - count.send(unit)
145
- start = origin.send("beginning_of_#{unit}")
146
- stop = origin.send("end_of_#{unit}")
147
- [:between, start, stop]
148
- end
149
-
150
- def time_string(target)
151
- target =~ /\A(\d+)_?(s(econds?)?|mi(nutes?)?|h(ours?)?|d(ays?)?|w(eeks?)?|mo(nths?)?|y(ears?)?)_?(ago)?\z/i
152
-
153
- size = $1.to_i
154
- unit = $2&.downcase || ""
155
-
156
- if unit.start_with?("s")
157
- size.seconds.ago
158
- elsif unit.start_with?("mi")
159
- size.minutes.ago
160
- elsif unit.start_with?("h")
161
- size.hours.ago
162
- elsif unit.start_with?("d")
163
- size.days.ago
164
- elsif unit.start_with?("w")
165
- size.weeks.ago
166
- elsif unit.start_with?("mo")
167
- size.months.ago
168
- elsif unit.start_with?("y")
169
- size.years.ago
170
- end
171
- end
172
- end
173
- end
174
- end
@@ -1,28 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module YiffSpace
4
- module Utils
5
- # Allow Rails URL helpers to be used outside of views.
6
- #
7
- # @example
8
- # Routes.posts_path(tags: "male")
9
- # => "/posts?tags=male"
10
- #
11
- # @see config/routes.rb
12
- # @see https://guides.rubyonrails.org/routing.html
13
- module Routes
14
- module_function
15
-
16
- def method_missing(name, *, &)
17
- url_helpers = Rails.application.routes.url_helpers
18
- return url_helpers.public_send(name, *, &) if url_helpers.respond_to?(name)
19
-
20
- super
21
- end
22
-
23
- def respond_to_missing?(name, include_private = false)
24
- Rails.application.routes.url_helpers.respond_to?(name, include_private) || super
25
- end
26
- end
27
- end
28
- end
@@ -1,18 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module YiffSpace
4
- module Utils
5
- class SetEnvConstraint
6
- attr_reader(:key, :value)
7
-
8
- def initialize(key, value)
9
- @key = key.to_s
10
- @value = value
11
- end
12
-
13
- def matches?(request)
14
- request.env[key.to_s] = value
15
- end
16
- end
17
- end
18
- end
@@ -1,169 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module YiffSpace
4
- module Utils
5
- # A helper class for building HTML tables. Used in views.
6
- #
7
- # @example
8
- # <%= table_for @tags do |table| %>
9
- # <% table.column :name do |tag| %>
10
- # <%= link_to_wiki "?", tag.name %>
11
- # <%= link_to tag.name, posts_path(tags: tag.name) %>
12
- # <% end %>
13
- # <% table.column :post_count %>
14
- # <% end %>
15
- #
16
- # @see app/views/table_builder/_table.html.erb
17
- class TableBuilder
18
- # Represents a single column in the table.
19
- class Column
20
- attr_reader(:attribute, :name, :block, :header_attributes, :body_attributes, :caption)
21
-
22
- # Define a table column.
23
- #
24
- # @example
25
- # <% table.column :post_count %>
26
- #
27
- # @example
28
- # <% table.column :name do |tag| %>
29
- # <%= tag.pretty_name %>
30
- # <% end %>
31
- #
32
- # @param attribute [Symbol] The attribute in the model the column is for.
33
- # The column's name and value will come from this attribute by default.
34
- # @param name [String] the column's name, if different from the attribute name.
35
- # @param column [String] the column name
36
- # @param th [Hash] the HTML attributes for the column's <th> tag.
37
- # @param td [Hash] the HTML attributes for the column's <td> tag.
38
- # @param width [String] the HTML width value for the <th> tag.
39
- # @yieldparam item a block that returns the column value based on the item.
40
- def initialize(attribute = nil, column: nil, th: {}, td: {}, width: nil, name: nil, &block)
41
- @attribute = attribute
42
- @column = column
43
- @header_attributes = { width: width, **th }
44
- @body_attributes = td
45
- @block = block
46
-
47
- @name = name || attribute
48
- @name = @name.to_s.titleize unless @name.is_a?(String)
49
-
50
- return unless @name.present? || @column.present?
51
-
52
- if @column.present?
53
- column_class = "#{@column}-column"
54
- else
55
- column_class = "#{@name.parameterize.dasherize}-column"
56
- end
57
- @header_attributes[:class] = "#{column_class} #{@header_attributes[:class]}".strip
58
- @body_attributes[:class] = "#{column_class} #{@body_attributes[:class]}".strip
59
- end
60
-
61
- # Returns the value of the table cell.
62
- # @param item [ApplicationRecord] the table cell item
63
- # @param row [Integer] the table row number
64
- # @param column [Integer] the table column number
65
- # @return [#to_s] the value of the table cell
66
- def value(item, row, column)
67
- if block.present?
68
- view = block.binding.receiver
69
- if view.respond_to?(:capture)
70
- view.capture { block.call(item, row, column, self) }
71
- else
72
- block.call(item, row, column, self)
73
- end
74
- elsif attribute.is_a?(Symbol)
75
- item.send(attribute)
76
- else
77
- ""
78
- end
79
- end
80
- end
81
-
82
- # Represents a custom row in the table body.
83
- class Row
84
- attr_reader(:block, :row_attributes)
85
-
86
- def initialize(row_attributes = {}, &block)
87
- @row_attributes = row_attributes
88
- @block = block
89
- end
90
-
91
- def custom?
92
- true
93
- end
94
-
95
- def value(index)
96
- view = block.binding.receiver
97
- if view.respond_to?(:capture)
98
- view.capture { block.call(index, self) }
99
- else
100
- block.call(index, self)
101
- end
102
- end
103
- end
104
-
105
- attr_reader(:columns, :table_attributes, :row_attributes, :items)
106
-
107
- # Build a table for an array of objects, one object per row.
108
- #
109
- # The <table> tag is automatically given an HTML id of the form `{name}-table`.
110
- # For example, `posts-table`, `tags-table`.
111
- #
112
- # The <tr> tag is automatically given an HTML id of the form `{name}-{id}`.
113
- # For example, `post-1234`, `tag-4567`, etc. Each <tr> tag also gets a set of
114
- # data attributes for each model; see #html_data_attributes in app/policies.
115
- #
116
- # @param items [Array<ApplicationRecord>] The list of ActiveRecord objects to
117
- # build the table for. One item per table row.
118
- # @param tr [Hash] optional HTML attributes for the <tr> tag for each row
119
- # @param table_attributes [Hash] optional HTML attributes for the <table> tag
120
- # @yieldparam table [self] the table being built
121
- def initialize(items, tr: {}, **table_attributes)
122
- @items = items
123
- @columns = []
124
- @table_attributes = { class: "striped", **table_attributes }
125
- @row_attributes = tr
126
-
127
- @table_attributes[:id] ||= "#{items.model_name.plural.dasherize}-table" if items.respond_to?(:model_name)
128
-
129
- yield(self) if block_given?
130
- end
131
-
132
- # Set the table caption
133
- def caption
134
- @caption = yield if block_given?
135
- @caption
136
- end
137
-
138
- # Add a column to the table.
139
- # @example
140
- # table.column(:name)
141
- def column(*, **options, &)
142
- opt = options.extract!(:if, :unless)
143
- return if (opt.key?(:if) && !opt[:if]) || (opt.key?(:unless) && opt[:unless])
144
-
145
- @columns << Column.new(*, **options, &)
146
- end
147
-
148
- def row(row_attributes = {}, &)
149
- @items = @items.to_a unless @items.is_a?(Array)
150
- @items << Row.new(row_attributes, &)
151
- end
152
-
153
- # Return the HTML attributes for each <tr> tag.
154
- # @param item [ApplicationRecord] the item for this row
155
- # @param _row [Integer] the row number (unused)
156
- # @return [Hash] the <tr> attributes
157
- def all_row_attributes(item, _row)
158
- return item.row_attributes if item.is_a?(Row)
159
- return {} unless item.is_a?(YiffSpace.config.application_record_class)
160
-
161
- {
162
- id: "#{item.model_name.singular.dasherize}-#{item.id}",
163
- **row_attributes,
164
- **YiffSpace.config.application_controller_class.helpers.data_attributes_for(item),
165
- }
166
- end
167
- end
168
- end
169
- end
@@ -1,91 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module YiffSpace
4
- module Utils
5
- module TraceLogger
6
- module_function
7
-
8
- COLORS = {
9
- black: "\e[30m",
10
- red: "\e[31m",
11
- green: "\e[32m",
12
- yellow: "\e[33m",
13
- blue: "\e[34m",
14
- magenta: "\e[35m",
15
- cyan: "\e[36m",
16
- white: "\e[37m",
17
- reset: "\e[0m",
18
- }.freeze
19
-
20
- # noinspection RubyLiteralArrayInspection
21
- LEVELS = {
22
- debug: ["%<cyan>s", "%<blue>s"],
23
- error: ["%<red>s", "%<red>s"],
24
- info: ["%<cyan>s", "%<blue>s"],
25
- warn: ["%<yellow>s", "%<yellow>s"],
26
- default: ["%<white>s", "%<white>s"],
27
- }.freeze
28
-
29
- def format_level(level)
30
- level = level.to_sym
31
- primary, alternate = LEVELS.fetch(level, LEVELS[:default])
32
- colorize("#{alternate}[%<reset>s#{primary}#{level.to_s.upcase}%<reset>s#{alternate}]%<reset>s")
33
- end
34
-
35
- def colorize(text, **)
36
- format(text, **COLORS, **)
37
- end
38
-
39
- def debug(*, **)
40
- _log(*, level: :debug, **)
41
- end
42
-
43
- def error(*, **)
44
- _log(*, level: :error, **)
45
- end
46
-
47
- def info(*, **)
48
- _log(*, level: :info, **)
49
- end
50
-
51
- def warn(*, **)
52
- _log(*, level: :warn, **)
53
- end
54
-
55
- def _log(*arg, ignore: nil, level: :log, lines: 3, format: nil)
56
- return unless Rails.logger.public_send("#{level}?")
57
-
58
- if arg.one?
59
- name = nil
60
- message = arg.first
61
- else
62
- name = arg.shift
63
- message = arg.join
64
- end
65
- primary, alternate = LEVELS.fetch(level, LEVELS[:default])
66
- args = { level: format_level(level), name: name, message: message }
67
- fmt = "%<level>s"
68
- if format.nil?
69
- if name.present?
70
- fmt += " #{alternate}[%<reset>s%<magenta>s%<name>s%<reset>s#{alternate}]%<reset>s " \
71
- "#{primary}%<message>s%<reset>s"
72
- else
73
- fmt += " #{primary}%<message>s%<reset>s"
74
- end
75
- else
76
- fmt += " #{format}%<reset>s"
77
- end
78
- ignore = Array(ignore).unshift(%r{/yiffspace/utils/trace_logger\.rb})
79
- callers = caller_locations.reject do |loc|
80
- path = loc.absolute_path || loc.path
81
- !Rails.backtrace_cleaner.clean_frame("#{path}:#{loc.lineno}") || ignore.any? { |i| path.match?(i) }
82
- end
83
- callers = callers.take(lines) if lines.present?
84
- Rails.logger.public_send(level, colorize(fmt, **args))
85
- callers.each { |c| Rails.logger.public_send(level, "↳ #{c.path.gsub(%r{^/app/}, '')}:#{c.lineno} in `#{c.label}`") }
86
- end
87
-
88
- private_class_method(:_log)
89
- end
90
- end
91
- end