fustrate-rails 0.4.1 → 0.10.1

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 (61) hide show
  1. checksums.yaml +5 -5
  2. data/config/initializers/jbuilder.rb +13 -0
  3. data/config/initializers/renderers.rb +40 -0
  4. data/config/initializers/sanitize.rb +112 -0
  5. data/config/rubocop/default.yml +96 -0
  6. data/config/rubocop/rails.yml +22 -0
  7. data/lib/fustrate/rails/concerns/clean_attributes.rb +49 -0
  8. data/lib/fustrate/rails/concerns/model.rb +48 -0
  9. data/lib/fustrate/rails/concerns/sanitize_html.rb +34 -0
  10. data/lib/fustrate/rails/engine.rb +14 -7
  11. data/lib/fustrate/rails/services/base.rb +46 -0
  12. data/lib/fustrate/rails/services/generate_csv.rb +35 -0
  13. data/lib/fustrate/rails/services/generate_excel.rb +32 -0
  14. data/lib/fustrate/rails/services/log_edit.rb +132 -0
  15. data/lib/fustrate/rails/spec_helper.rb +62 -0
  16. data/lib/fustrate/rails/version.rb +5 -1
  17. data/lib/fustrate-rails.rb +5 -2
  18. metadata +44 -140
  19. data/vendor/assets/javascripts/awesomplete.js +0 -402
  20. data/vendor/assets/javascripts/fustrate/_module.coffee +0 -140
  21. data/vendor/assets/javascripts/fustrate/components/_module.coffee +0 -3
  22. data/vendor/assets/javascripts/fustrate/components/alert_box.coffee +0 -10
  23. data/vendor/assets/javascripts/fustrate/components/autocomplete.coffee +0 -161
  24. data/vendor/assets/javascripts/fustrate/components/disclosure.coffee +0 -12
  25. data/vendor/assets/javascripts/fustrate/components/drop_zone.coffee +0 -9
  26. data/vendor/assets/javascripts/fustrate/components/dropdown.coffee +0 -48
  27. data/vendor/assets/javascripts/fustrate/components/file_picker.coffee +0 -11
  28. data/vendor/assets/javascripts/fustrate/components/flash.coffee +0 -31
  29. data/vendor/assets/javascripts/fustrate/components/modal.coffee +0 -273
  30. data/vendor/assets/javascripts/fustrate/components/pagination.coffee +0 -84
  31. data/vendor/assets/javascripts/fustrate/components/tabs.coffee +0 -28
  32. data/vendor/assets/javascripts/fustrate/components/tooltip.coffee +0 -72
  33. data/vendor/assets/javascripts/fustrate/generic_form.coffee +0 -30
  34. data/vendor/assets/javascripts/fustrate/generic_page.coffee +0 -40
  35. data/vendor/assets/javascripts/fustrate/generic_table.coffee +0 -57
  36. data/vendor/assets/javascripts/fustrate/listenable.coffee +0 -25
  37. data/vendor/assets/javascripts/fustrate/object.coffee +0 -21
  38. data/vendor/assets/javascripts/fustrate/record.coffee +0 -23
  39. data/vendor/assets/javascripts/fustrate.coffee +0 -6
  40. data/vendor/assets/stylesheets/_fustrate.sass +0 -7
  41. data/vendor/assets/stylesheets/awesomplete.sass +0 -76
  42. data/vendor/assets/stylesheets/fustrate/_colors.sass +0 -12
  43. data/vendor/assets/stylesheets/fustrate/_settings.sass +0 -20
  44. data/vendor/assets/stylesheets/fustrate/components/_components.sass +0 -36
  45. data/vendor/assets/stylesheets/fustrate/components/_functions.sass +0 -41
  46. data/vendor/assets/stylesheets/fustrate/components/alerts.sass +0 -86
  47. data/vendor/assets/stylesheets/fustrate/components/buttons.sass +0 -99
  48. data/vendor/assets/stylesheets/fustrate/components/disclosures.sass +0 -23
  49. data/vendor/assets/stylesheets/fustrate/components/dropdowns.sass +0 -36
  50. data/vendor/assets/stylesheets/fustrate/components/flash.sass +0 -38
  51. data/vendor/assets/stylesheets/fustrate/components/forms.sass +0 -195
  52. data/vendor/assets/stylesheets/fustrate/components/grid.sass +0 -196
  53. data/vendor/assets/stylesheets/fustrate/components/labels.sass +0 -64
  54. data/vendor/assets/stylesheets/fustrate/components/modals.sass +0 -167
  55. data/vendor/assets/stylesheets/fustrate/components/pagination.sass +0 -69
  56. data/vendor/assets/stylesheets/fustrate/components/panels.sass +0 -67
  57. data/vendor/assets/stylesheets/fustrate/components/popovers.sass +0 -19
  58. data/vendor/assets/stylesheets/fustrate/components/tables.sass +0 -62
  59. data/vendor/assets/stylesheets/fustrate/components/tabs.sass +0 -44
  60. data/vendor/assets/stylesheets/fustrate/components/tooltips.sass +0 -28
  61. data/vendor/assets/stylesheets/fustrate/components/typography.sass +0 -391
@@ -0,0 +1,132 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Copyright (c) Steven Hoffman
4
+ # All rights reserved.
5
+
6
+ module Fustrate
7
+ module Rails
8
+ module Services
9
+ module LogEdit
10
+ IGNORE_COLUMNS = %w[id created_at updated_at].freeze
11
+ RENAME_COLUMNS = {}.freeze
12
+
13
+ attr_reader :subject, :force, :note, :user
14
+
15
+ def call(subject, force: false, note: nil, user: nil)
16
+ # Make sure any before_validation callbacks are run
17
+ subject.validate
18
+
19
+ @subject = subject
20
+ @force = force
21
+ @note = note
22
+ @user = user || ::Current.user
23
+
24
+ process_changes
25
+
26
+ self.class::RENAME_COLUMNS.each do |from, to|
27
+ changes[to] = changes.delete(from) if changes[from]
28
+ end
29
+
30
+ record_edit
31
+ end
32
+
33
+ protected
34
+
35
+ def changes
36
+ @changes ||= subject.changes.except(*self.class::IGNORE_COLUMNS)
37
+ end
38
+
39
+ def record_edit
40
+ clean_changes!
41
+
42
+ return if changes.empty? && !force
43
+
44
+ subject.log_edits_on.edits.new(
45
+ user:,
46
+ note:,
47
+ reason: ::Current.params[:reason],
48
+ pretty_changes: changes,
49
+ raw_changes:
50
+ )
51
+ end
52
+
53
+ # Get rid of changes from nil to '' and whatnot
54
+ def clean_changes! = changes.delete_if { |_, values| values.all?(&:blank?) || values.first == values.last }
55
+
56
+ def raw_changes = subject.changes
57
+
58
+ def process_changes
59
+ process_timestamps(:datetime, '%-m/%-d/%y %-I:%M %p')
60
+ process_timestamps(:date, '%-m/%-d/%y')
61
+ process_timestamps(:time, '%-I:%M %p')
62
+
63
+ process_boolean_columns
64
+ process_relations
65
+ end
66
+
67
+ def process_timestamps(type, time_format)
68
+ columns_of_type(type).each do |column_name|
69
+ changes[column_name].map! { _1&.strftime(time_format) }
70
+ end
71
+ end
72
+
73
+ def process_boolean_columns
74
+ columns_of_type(:boolean).each do |column_name|
75
+ changes[column_name] = changes[column_name][1] ? %w[No Yes] : %w[Yes No]
76
+ end
77
+ end
78
+
79
+ def columns_of_type(type) = Array(columns[type]).select { changes[_1] }
80
+
81
+ def process_relations
82
+ subject.class.reflect_on_all_associations.each do |relation|
83
+ if relation.options[:polymorphic]
84
+ process_polymorphic_relation(relation.name)
85
+ elsif relation.is_a?(::ActiveRecord::Reflection::BelongsToReflection)
86
+ process_belongs_to_relation(relation.name)
87
+ end
88
+ end
89
+ end
90
+
91
+ def process_polymorphic_relation(name)
92
+ return unless changes["#{name}_id"] || changes["#{name}_type"]
93
+
94
+ changes.delete("#{name}_id")
95
+ changes.delete("#{name}_type")
96
+
97
+ changes[name] = [find_old_polymorphic_record(name), subject.__send__(name)&.to_s]
98
+ end
99
+
100
+ def find_old_polymorphic_record(name)
101
+ # The type, and in rare cases the ID, may not have actually changed
102
+ old_id = subject.__send__(:"#{name}_id_in_database")
103
+ old_type = subject.__send__(:"#{name}_type_in_database").presence
104
+
105
+ ::Object.const_get(old_type).find(old_id)&.to_s if old_type
106
+ end
107
+
108
+ def columns
109
+ # .reject { _1.name.match?(/_(?:type|id)\z/) }
110
+ @columns ||= subject.class.columns
111
+ .reject { self.class::IGNORE_COLUMNS.include? _1.name }
112
+ .group_by { _1.sql_type_metadata.type }
113
+ .transform_values { |cols| cols.map { _1.name.to_sym } }
114
+ end
115
+
116
+ def process_belongs_to_relation(name)
117
+ return unless changes["#{name}_id"]
118
+
119
+ new_value = subject.__send__(name)
120
+
121
+ old_value_id = changes.delete("#{name}_id").first
122
+
123
+ # If we're removing the value, new_value.class will be nil, so we need to use reflection.
124
+ changes[name] = [
125
+ (subject.class.reflect_on_association(name).klass.find(old_value_id)&.to_s if old_value_id),
126
+ new_value&.to_s
127
+ ]
128
+ end
129
+ end
130
+ end
131
+ end
132
+ end
@@ -0,0 +1,62 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Copyright (c) Steven Hoffman
4
+ # All rights reserved.
5
+
6
+ module Fustrate
7
+ module Rails
8
+ module SpecHelper
9
+ include ::ActiveSupport::Testing::TimeHelpers
10
+
11
+ def accept(mime)
12
+ request.accept = mime['/'] ? mime : ::Mime::Type.lookup_by_extension(mime)
13
+ end
14
+
15
+ # Just helps to shorten some absurdly long error message keys
16
+ def error_t(model, attribute, key)
17
+ key = "attributes.#{attribute}.#{key}" if attribute
18
+
19
+ ::I18n.t "activerecord.errors.models.#{model.model_name.i18n_key}.#{key}"
20
+ end
21
+
22
+ def double_list(name, count, **stubs) = ::Array.new(count) { instance_double(name, stubs) }
23
+
24
+ def data_from_file(name, **interpolations)
25
+ ::Dir.glob(::Rails.root.join('spec', 'data', "#{name}.*")) do |filename|
26
+ case ::File.extname filename
27
+ when '.yml', '.yaml'
28
+ return yaml_data_from_file(filename, **interpolations)
29
+ else
30
+ raise ::ArgumentError, "Could not parse unknown file type #{::File.extname filename}"
31
+ end
32
+ end
33
+ end
34
+
35
+ def image_file(filename, type = 'image/jpeg')
36
+ ::Rack::Test::UploadedFile.new ::Rails.root.join('spec', 'files', filename), type
37
+ end
38
+
39
+ def pdf_file(filename)
40
+ ::Rack::Test::UploadedFile.new ::Rails.root.join('spec', 'files', filename), 'application/pdf'
41
+ end
42
+
43
+ # A few cron scripts use `puts` and clog up STDOUT.
44
+ def stfu
45
+ orig_stdout = $stdout.clone
46
+ $stdout.reopen ::File.new('/dev/null', 'w')
47
+ yield
48
+ rescue ::StandardError => e
49
+ $stdout.reopen orig_stdout
50
+ raise e
51
+ ensure
52
+ $stdout.reopen orig_stdout
53
+ end
54
+
55
+ protected
56
+
57
+ def yaml_data_from_file(filename, **) = ::YAML.safe_load read_with_interpolations(filename, **), aliases: true
58
+
59
+ def read_with_interpolations(filename, **interpolations) = ::File.read(filename) % interpolations
60
+ end
61
+ end
62
+ end
@@ -1,6 +1,10 @@
1
1
  # frozen_string_literal: true
2
+
3
+ # Copyright (c) Steven Hoffman
4
+ # All rights reserved.
5
+
2
6
  module Fustrate
3
7
  module Rails
4
- VERSION = '0.4.1'.freeze
8
+ VERSION = '0.10.1'
5
9
  end
6
10
  end
@@ -1,4 +1,7 @@
1
- require 'coffee-script'
2
- require 'sass'
1
+ # frozen_string_literal: true
2
+
3
+ # Copyright (c) Steven Hoffman
4
+ # All rights reserved.
5
+
3
6
  require 'fustrate/rails/engine'
4
7
  require 'fustrate/rails/version'
metadata CHANGED
@@ -1,193 +1,99 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: fustrate-rails
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.4.1
4
+ version: 0.10.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Steven Hoffman
8
- autorequire:
8
+ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2017-02-25 00:00:00.000000000 Z
11
+ date: 2024-02-04 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
- name: coffee-script
14
+ name: activesupport
15
15
  requirement: !ruby/object:Gem::Requirement
16
16
  requirements:
17
- - - ">="
17
+ - - "~>"
18
18
  - !ruby/object:Gem::Version
19
- version: '2.4'
19
+ version: '7.1'
20
20
  type: :runtime
21
21
  prerelease: false
22
22
  version_requirements: !ruby/object:Gem::Requirement
23
23
  requirements:
24
- - - ">="
24
+ - - "~>"
25
25
  - !ruby/object:Gem::Version
26
- version: '2.4'
26
+ version: '7.1'
27
27
  - !ruby/object:Gem::Dependency
28
- name: sass
28
+ name: jbuilder
29
29
  requirement: !ruby/object:Gem::Requirement
30
30
  requirements:
31
- - - ">="
31
+ - - "~>"
32
32
  - !ruby/object:Gem::Version
33
- version: '3.4'
33
+ version: '2.11'
34
34
  type: :runtime
35
35
  prerelease: false
36
36
  version_requirements: !ruby/object:Gem::Requirement
37
37
  requirements:
38
- - - ">="
38
+ - - "~>"
39
39
  - !ruby/object:Gem::Version
40
- version: '3.4'
40
+ version: '2.11'
41
41
  - !ruby/object:Gem::Dependency
42
42
  name: railties
43
43
  requirement: !ruby/object:Gem::Requirement
44
44
  requirements:
45
- - - ">="
45
+ - - "~>"
46
46
  - !ruby/object:Gem::Version
47
- version: '4'
48
- - - "<"
49
- - !ruby/object:Gem::Version
50
- version: '5.2'
51
- type: :runtime
52
- prerelease: false
53
- version_requirements: !ruby/object:Gem::Requirement
54
- requirements:
55
- - - ">="
56
- - !ruby/object:Gem::Version
57
- version: '4'
58
- - - "<"
59
- - !ruby/object:Gem::Version
60
- version: '5.2'
61
- - !ruby/object:Gem::Dependency
62
- name: bourbon
63
- requirement: !ruby/object:Gem::Requirement
64
- requirements:
65
- - - ">="
66
- - !ruby/object:Gem::Version
67
- version: '0'
68
- type: :runtime
69
- prerelease: false
70
- version_requirements: !ruby/object:Gem::Requirement
71
- requirements:
72
- - - ">="
73
- - !ruby/object:Gem::Version
74
- version: '0'
75
- - !ruby/object:Gem::Dependency
76
- name: font-awesome-rails
77
- requirement: !ruby/object:Gem::Requirement
78
- requirements:
79
- - - ">="
80
- - !ruby/object:Gem::Version
81
- version: '0'
47
+ version: '7.1'
82
48
  type: :runtime
83
49
  prerelease: false
84
50
  version_requirements: !ruby/object:Gem::Requirement
85
51
  requirements:
86
- - - ">="
52
+ - - "~>"
87
53
  - !ruby/object:Gem::Version
88
- version: '0'
54
+ version: '7.1'
89
55
  - !ruby/object:Gem::Dependency
90
- name: js-routes
56
+ name: sanitize
91
57
  requirement: !ruby/object:Gem::Requirement
92
58
  requirements:
93
- - - ">="
59
+ - - "~>"
94
60
  - !ruby/object:Gem::Version
95
- version: '0'
61
+ version: '6.1'
96
62
  type: :runtime
97
63
  prerelease: false
98
64
  version_requirements: !ruby/object:Gem::Requirement
99
65
  requirements:
100
- - - ">="
66
+ - - "~>"
101
67
  - !ruby/object:Gem::Version
102
- version: '0'
103
- - !ruby/object:Gem::Dependency
104
- name: modernizr-rails
105
- requirement: !ruby/object:Gem::Requirement
106
- requirements:
107
- - - ">="
108
- - !ruby/object:Gem::Version
109
- version: '0'
110
- type: :runtime
111
- prerelease: false
112
- version_requirements: !ruby/object:Gem::Requirement
113
- requirements:
114
- - - ">="
115
- - !ruby/object:Gem::Version
116
- version: '0'
117
- - !ruby/object:Gem::Dependency
118
- name: momentjs-rails
119
- requirement: !ruby/object:Gem::Requirement
120
- requirements:
121
- - - ">="
122
- - !ruby/object:Gem::Version
123
- version: '0'
124
- type: :runtime
125
- prerelease: false
126
- version_requirements: !ruby/object:Gem::Requirement
127
- requirements:
128
- - - ">="
129
- - !ruby/object:Gem::Version
130
- version: '0'
131
- description: |2
132
- A coffeescript/sass library that encapsulates common code that I use on
133
- multiple projects. It was originally based on Foundation 5, but nearly
134
- everything has been changed.
135
- email:
68
+ version: '6.1'
69
+ description:
70
+ email:
136
71
  executables: []
137
72
  extensions: []
138
73
  extra_rdoc_files: []
139
74
  files:
75
+ - config/initializers/jbuilder.rb
76
+ - config/initializers/renderers.rb
77
+ - config/initializers/sanitize.rb
78
+ - config/rubocop/default.yml
79
+ - config/rubocop/rails.yml
140
80
  - lib/fustrate-rails.rb
81
+ - lib/fustrate/rails/concerns/clean_attributes.rb
82
+ - lib/fustrate/rails/concerns/model.rb
83
+ - lib/fustrate/rails/concerns/sanitize_html.rb
141
84
  - lib/fustrate/rails/engine.rb
85
+ - lib/fustrate/rails/services/base.rb
86
+ - lib/fustrate/rails/services/generate_csv.rb
87
+ - lib/fustrate/rails/services/generate_excel.rb
88
+ - lib/fustrate/rails/services/log_edit.rb
89
+ - lib/fustrate/rails/spec_helper.rb
142
90
  - lib/fustrate/rails/version.rb
143
- - vendor/assets/javascripts/awesomplete.js
144
- - vendor/assets/javascripts/fustrate.coffee
145
- - vendor/assets/javascripts/fustrate/_module.coffee
146
- - vendor/assets/javascripts/fustrate/components/_module.coffee
147
- - vendor/assets/javascripts/fustrate/components/alert_box.coffee
148
- - vendor/assets/javascripts/fustrate/components/autocomplete.coffee
149
- - vendor/assets/javascripts/fustrate/components/disclosure.coffee
150
- - vendor/assets/javascripts/fustrate/components/drop_zone.coffee
151
- - vendor/assets/javascripts/fustrate/components/dropdown.coffee
152
- - vendor/assets/javascripts/fustrate/components/file_picker.coffee
153
- - vendor/assets/javascripts/fustrate/components/flash.coffee
154
- - vendor/assets/javascripts/fustrate/components/modal.coffee
155
- - vendor/assets/javascripts/fustrate/components/pagination.coffee
156
- - vendor/assets/javascripts/fustrate/components/tabs.coffee
157
- - vendor/assets/javascripts/fustrate/components/tooltip.coffee
158
- - vendor/assets/javascripts/fustrate/generic_form.coffee
159
- - vendor/assets/javascripts/fustrate/generic_page.coffee
160
- - vendor/assets/javascripts/fustrate/generic_table.coffee
161
- - vendor/assets/javascripts/fustrate/listenable.coffee
162
- - vendor/assets/javascripts/fustrate/object.coffee
163
- - vendor/assets/javascripts/fustrate/record.coffee
164
- - vendor/assets/stylesheets/_fustrate.sass
165
- - vendor/assets/stylesheets/awesomplete.sass
166
- - vendor/assets/stylesheets/fustrate/_colors.sass
167
- - vendor/assets/stylesheets/fustrate/_settings.sass
168
- - vendor/assets/stylesheets/fustrate/components/_components.sass
169
- - vendor/assets/stylesheets/fustrate/components/_functions.sass
170
- - vendor/assets/stylesheets/fustrate/components/alerts.sass
171
- - vendor/assets/stylesheets/fustrate/components/buttons.sass
172
- - vendor/assets/stylesheets/fustrate/components/disclosures.sass
173
- - vendor/assets/stylesheets/fustrate/components/dropdowns.sass
174
- - vendor/assets/stylesheets/fustrate/components/flash.sass
175
- - vendor/assets/stylesheets/fustrate/components/forms.sass
176
- - vendor/assets/stylesheets/fustrate/components/grid.sass
177
- - vendor/assets/stylesheets/fustrate/components/labels.sass
178
- - vendor/assets/stylesheets/fustrate/components/modals.sass
179
- - vendor/assets/stylesheets/fustrate/components/pagination.sass
180
- - vendor/assets/stylesheets/fustrate/components/panels.sass
181
- - vendor/assets/stylesheets/fustrate/components/popovers.sass
182
- - vendor/assets/stylesheets/fustrate/components/tables.sass
183
- - vendor/assets/stylesheets/fustrate/components/tabs.sass
184
- - vendor/assets/stylesheets/fustrate/components/tooltips.sass
185
- - vendor/assets/stylesheets/fustrate/components/typography.sass
186
91
  homepage: https://github.com/fustrate/fustrate-rails
187
92
  licenses:
188
93
  - MIT
189
- metadata: {}
190
- post_install_message:
94
+ metadata:
95
+ rubygems_mfa_required: 'true'
96
+ post_install_message:
191
97
  rdoc_options: []
192
98
  require_paths:
193
99
  - lib
@@ -195,17 +101,15 @@ required_ruby_version: !ruby/object:Gem::Requirement
195
101
  requirements:
196
102
  - - ">="
197
103
  - !ruby/object:Gem::Version
198
- version: '0'
104
+ version: 3.3.0
199
105
  required_rubygems_version: !ruby/object:Gem::Requirement
200
106
  requirements:
201
107
  - - ">="
202
108
  - !ruby/object:Gem::Version
203
109
  version: '0'
204
110
  requirements: []
205
- rubyforge_project:
206
- rubygems_version: 2.6.8
207
- signing_key:
111
+ rubygems_version: 3.5.5
112
+ signing_key:
208
113
  specification_version: 4
209
- summary: JS/CSS framework customized to my preferences, long ago based on Foundation
210
- 5. Needs an actual name.
114
+ summary: A few useful services and initializers.
211
115
  test_files: []