large_text_field 1.2.0 → 1.3.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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: fff0ae6fef43accd89e4d85adc223752579dc4202cd79eff6ad52bd322f4d7c5
4
- data.tar.gz: 5a0b69d8d87f8bb86f5ca83b1926e17298e0a7ac2cdba20e502df92c3e22fd0b
3
+ metadata.gz: f2e280facc3621c0a56580099e140094ddd0a02c3d8679b1fd62f7f8e85c23c5
4
+ data.tar.gz: 2a312b3f22593f142ddce7526b7fa388d41297ab61cf0fb59f603495300c5f94
5
5
  SHA512:
6
- metadata.gz: 14f76e0df0369ef995cecda988176032d20dde40b6fba59bd3c97aa0250bd87b5ac1f40c89dcdc8064d5de4735eaa31e4a06a366a1f83173caa43820ea547457
7
- data.tar.gz: 6491b14da859550bd9277f22ac4fbc9d89042e06f3798c105b5f47761ff3167b0d65b3168231d542d10b7ccd51181f4eb2b0745357f52e1f820ee2ead50b8090
6
+ metadata.gz: 8f748d3c267b4cd971db249bfd2b647166eda4e6b25da091caa0a71f08318b049a23acdafdde592e037a9932491ff0cf4983e9d21f61e7f73611bbe0f452b7dd
7
+ data.tar.gz: 118a78c39fa5d35bc49dd92a0785d0beb510e0d5479f132408e0bc3723cbcc1781321b89a7790126996c2bc8cd2cc5c28773c30d3f83eaa0cb48042f7d3490e8
data/README.md CHANGED
@@ -5,6 +5,7 @@ characters. Defining new fields on models does not require database migrations.
5
5
  central table that is polymorphically associated with the model, but they act like a column on the same model.
6
6
 
7
7
  ## How do I use it?
8
+
8
9
  In you Gemfile add:
9
10
 
10
11
  ```
@@ -13,8 +14,8 @@ In you Gemfile add:
13
14
 
14
15
  There will be database migration you need to run to define the table, so go ahead and run that...
15
16
 
16
- Any class that wants to define a large text field should include **::LargeTextField::Owner**,
17
- and then define text fields by calling the **large_text_field** macro.
17
+ Any class that wants to define a large text field should include **::LargeTextField::Owner**,
18
+ and then define text fields by calling the **large_text_field** macro.
18
19
 
19
20
  For example the following is a `Library` class that has large text fields for `notes` and `description`.
20
21
 
@@ -27,25 +28,35 @@ class Library < ApplicationRecord
27
28
  end
28
29
  ```
29
30
 
30
- That's it! You can then access `notes` and `description` as if they were columns on your class.
31
+ That's it! You can then access `notes` and `description` as if they were columns on your class.
31
32
 
32
33
  The `large_text_field` macro takes the following options...
33
34
 
34
- * **maximum: number** - The maximum length of a large text field. By default this is 5,000,000 characters,
35
- but it can be set to less using this option.
36
- * **singularize_errors: boolean** - should validation messages be singularized.
35
+ - **maximum: number** - The maximum length of a large text field. By default this is 5,000,000 characters,
36
+ but it can be set to less using this option.
37
+ - **singularize_errors: boolean** - should validation messages be singularized.
37
38
 
38
- Large text fields defaults to an empty string. You cannot store `nil` in a large text field.
39
+ Large text fields defaults to an empty string. You cannot store `nil` in a large text field.
39
40
 
40
- **Please note:** Large text field uses the *before_save* callback on the class that is the owner for book-keeping.
41
- Callbacks are great, but if there are multiple handlers for the same callback the order in which they are called is
42
- not predictable. If you want to make changes to large_text_field values in the before_save callback, use the
43
- **large_text_field_save** callback instead. This will be called before the large text field book-keeping so your
44
- changes will be saved. For example, this will call the `save_preprocess` method on your class before the large text
41
+ **Please note:** Large text field uses the _before_save_ callback on the class that is the owner for book-keeping.
42
+ Callbacks are great, but if there are multiple handlers for the same callback the order in which they are called is
43
+ not predictable. If you want to make changes to large_text_field values in the before_save callback, use the
44
+ **large_text_field_save** callback instead. This will be called before the large text field book-keeping so your
45
+ changes will be saved. For example, this will call the `save_preprocess` method on your class before the large text
45
46
  fields are saved...
46
47
 
47
48
  ```ruby
48
49
  set_callback(:large_text_field_save, :before, :save_preprocess)
49
50
  ```
50
51
 
51
- This project rocks and uses MIT-LICENSE. You should too.
52
+ Added class methods:
53
+
54
+ ```ruby
55
+ large_text_field_deprecated_class_name_override "LargeTextField::NamedTextValue"
56
+ large_text_field_class_name_override "MyCustomLargeTextField"
57
+ ```
58
+
59
+ You will not generally need this support; however, it can be helpful when trying to separate a model into a
60
+ different database.
61
+
62
+ This project rocks and uses MIT-LICENSE. You should too.
@@ -5,7 +5,8 @@ require_relative 'application_record'
5
5
  module LargeTextField
6
6
  class NamedTextValue < ApplicationRecord
7
7
  # Schema
8
- # field_name :string, :limit => 255
8
+ # field_name :string, :limit => 255
9
+ # foo :string
9
10
  # value :text, :null=>true, :limit => MYSQL_MEDIUM_TEXT_UTF8_LIMIT
10
11
  #
11
12
  # index [ :owner_type, :owner_id, :field_name ], :name => 'large_text_field_by_owner_field', :unique=>true
@@ -8,20 +8,25 @@ module LargeTextField
8
8
  include ActiveSupport::Callbacks
9
9
 
10
10
  included do
11
- has_many(
12
- :large_text_fields,
13
- class_name: "LargeTextField::NamedTextValue",
14
- as: :owner,
15
- autosave: true,
16
- dependent: :destroy,
17
- inverse_of: :owner
18
- )
19
11
  validate :validate_large_text_fields
20
12
  before_save :write_large_text_field_changes
21
13
  define_callbacks :large_text_field_save
22
14
 
23
15
  class_attribute :large_text_field_options
24
16
  self.large_text_field_options = {}
17
+
18
+ class_attribute :initialized
19
+ self.initialized = false
20
+
21
+ class_attribute :large_text_field_class_name
22
+ self.large_text_field_class_name = "LargeTextField::NamedTextValue"
23
+ class_attribute :large_text_field_class
24
+ self.large_text_field_class = LargeTextField::NamedTextValue
25
+
26
+ class_attribute :large_text_field_deprecated_class_name
27
+ self.large_text_field_deprecated_class_name = nil
28
+ class_attribute :large_text_field_deprecated_class
29
+ self.large_text_field_deprecated_class = nil
25
30
  end
26
31
 
27
32
  def dup
@@ -42,7 +47,13 @@ module LargeTextField
42
47
  end
43
48
 
44
49
  def text_field_hash
45
- @text_field_hash ||= large_text_fields.build_hash { |text_field| [text_field.field_name, text_field] }
50
+ unless @text_field_hash
51
+ @text_field_hash = large_text_fields.build_hash { |text_field| [text_field.field_name, text_field] }
52
+ if large_text_field_deprecated_class_name
53
+ deprecated_large_text_fields.each { |text_field| @text_field_hash[text_field.field_name] ||= text_field }
54
+ end
55
+ end
56
+ @text_field_hash
46
57
  end
47
58
 
48
59
  def text_field_hash_loaded?
@@ -61,7 +72,7 @@ module LargeTextField
61
72
  if (field = text_field_hash[field_name])
62
73
  field.value = value
63
74
  else
64
- text_field_hash[field_name] = LargeTextField::NamedTextValue.new(owner: self, field_name: field_name, value: value)
75
+ text_field_hash[field_name] = large_text_field_class.new(owner: self, field_name:, value:)
65
76
  end
66
77
  end
67
78
 
@@ -91,7 +102,10 @@ module LargeTextField
91
102
  def write_large_text_field_changes
92
103
  run_callbacks(:large_text_field_save)
93
104
 
94
- @text_field_hash = text_field_hash.compact.select { |_key, value| value.value.presence }
105
+ @text_field_hash = text_field_hash
106
+ .compact
107
+ .select { |_key, value| value.value.presence }
108
+ .transform_values { |value| value.is_a?(large_text_field_class) ? value : large_text_field_class.new(owner: self, field_name: value.field_name, value: value.value) }
95
109
  self.large_text_fields = text_field_hash.values.compact
96
110
  true
97
111
  end
@@ -103,7 +117,43 @@ module LargeTextField
103
117
  end
104
118
 
105
119
  module ClassMethods
120
+ def large_text_field_class_name_override(value)
121
+ self.large_text_field_class_name = value
122
+ self.large_text_field_class = Object.const_get(value)
123
+ end
124
+
125
+ def large_text_field_deprecated_class_name_override(value)
126
+ self.large_text_field_deprecated_class_name = value
127
+ self.large_text_field_deprecated_class = Object.const_get(value)
128
+ end
129
+
130
+ def initialize_large_text_field
131
+ return if initialized # skip if already initialized
132
+
133
+ has_many(
134
+ :large_text_fields,
135
+ class_name: large_text_field_class_name,
136
+ as: :owner,
137
+ autosave: true,
138
+ dependent: :destroy,
139
+ inverse_of: :owner
140
+ )
141
+ if large_text_field_deprecated_class_name
142
+ has_many(
143
+ :deprecated_large_text_fields,
144
+ class_name: large_text_field_deprecated_class_name,
145
+ as: :owner,
146
+ autosave: true,
147
+ dependent: :destroy,
148
+ inverse_of: :owner
149
+ )
150
+ end
151
+ self.initialized = true
152
+ end
153
+
106
154
  def large_text_field(field_name, maximum: nil, singularize_errors: false)
155
+ initialize_large_text_field # ensure the association is initialized
156
+
107
157
  field_name = field_name.to_s
108
158
 
109
159
  # validate custom maximum
@@ -117,7 +167,7 @@ module LargeTextField
117
167
  end
118
168
  end
119
169
 
120
- large_text_field_options[field_name] = { maximum: maximum, singularize_errors: singularize_errors }
170
+ large_text_field_options[field_name] = { maximum:, singularize_errors: }
121
171
  define_method(field_name) { get_text_field(field_name) }
122
172
  define_method("#{field_name}=") { |value| set_text_field(field_name, value) }
123
173
  define_method("#{field_name}_changed?") { text_field_changed(field_name) }
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module LargeTextField
4
- VERSION = "1.2.0"
4
+ VERSION = "1.3.0"
5
5
  end
metadata CHANGED
@@ -1,14 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: large_text_field
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.2.0
4
+ version: 1.3.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Invoca
8
- autorequire:
9
8
  bindir: bin
10
9
  cert_chain: []
11
- date: 2024-07-11 00:00:00.000000000 Z
10
+ date: 2025-06-09 00:00:00.000000000 Z
12
11
  dependencies:
13
12
  - !ruby/object:Gem::Dependency
14
13
  name: invoca-utils
@@ -68,7 +67,6 @@ metadata:
68
67
  documentation_uri: https://github.com/invoca/large_text_field
69
68
  changelog_uri: https://github.com/invoca/large_text_field/blob/master/CHANGELOG.md
70
69
  bug_tracker_uri: https://github.com/invoca/large_text_field/issues
71
- post_install_message:
72
70
  rdoc_options: []
73
71
  require_paths:
74
72
  - lib
@@ -83,8 +81,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
83
81
  - !ruby/object:Gem::Version
84
82
  version: '0'
85
83
  requirements: []
86
- rubygems_version: 3.3.27
87
- signing_key:
84
+ rubygems_version: 3.6.3
88
85
  specification_version: 4
89
86
  summary: Add large text fields to models without database migrations
90
87
  test_files: []