active_hash 3.3.1 → 4.1.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 +4 -4
- data/CHANGELOG.md +39 -1
- data/README.md +23 -5
- data/active_hash.gemspec +2 -2
- data/lib/active_file/base.rb +1 -1
- data/lib/active_hash/base.rb +30 -7
- data/lib/active_hash/relation.rb +19 -0
- data/lib/active_hash/version.rb +1 -1
- data/lib/associations/associations.rb +6 -14
- data/lib/enum/enum.rb +14 -0
- metadata +6 -9
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 87c94fe12c3633dc4d691ff9c67c818ec68495f89e5529130b2e4d49504cefd3
|
|
4
|
+
data.tar.gz: dab8cc2c530de82a9020a68d128ca1d6c815aa68ab977ea242a3f2d8470d8c22
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 1cb506c09e918622c2581d2f7727076db0fbc43a4940cd90dad2ff96857b16d19b2b77bb1b808e7c160ab4109ad7b97369b167a7c057730cd9806e6fbef72988
|
|
7
|
+
data.tar.gz: 8588f0311f2b680147bec5606cfdbc5ec0b0a224672c28dbd33c67bd88d85351050baf726eaaaa8c908c4c5d5e3200314f4939a29368244da81b5c8bcf9e88db
|
data/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,41 @@
|
|
|
1
1
|
# active_hash Changelog
|
|
2
2
|
|
|
3
|
+
## Version [4.1.0] - <sub><sup>2026-04-01</sup></sub>
|
|
4
|
+
|
|
5
|
+
### Added
|
|
6
|
+
|
|
7
|
+
- Add `Relation#or` support [#343](https://github.com/active-hash/active_hash/pull/343) @opsys-saito
|
|
8
|
+
- Alias `Relation#find_each` and `Base#find_each` to `#each` [#333](https://github.com/active-hash/active_hash/pull/333) @DmitryBarskov
|
|
9
|
+
|
|
10
|
+
### Fixed
|
|
11
|
+
|
|
12
|
+
- Fix `exists?` to support ids which are strings [#339](https://github.com/active-hash/active_hash/pull/339) @mtmail
|
|
13
|
+
- Fix `model_name` availability when using `ActiveModel::Serialization` [#335](https://github.com/active-hash/active_hash/pull/335) @moznion
|
|
14
|
+
|
|
15
|
+
## Version [4.0.0] - <sub><sup>2025-07-30</sup></sub>
|
|
16
|
+
|
|
17
|
+
### Added
|
|
18
|
+
|
|
19
|
+
- Add i18n support [#230](https://github.com/active-hash/active_hash/pull/230) @ryu-sato @Yuki-Inoue
|
|
20
|
+
- Add `column_names` method [#311](https://github.com/active-hash/active_hash/pull/311) @hatsu38
|
|
21
|
+
- Add block support to `count` [#317](https://github.com/active-hash/active_hash/pull/317) @ashleyHutton
|
|
22
|
+
- Support ruby 3.4 [#328](https://github.com/active-hash/active_hash/pull/328) @flavorjones
|
|
23
|
+
- Add `:alias` to `has_many :through` [#329](https://github.com/active-hash/active_hash/pull/329) @alexgriff
|
|
24
|
+
- Add Active Record 8.0 [#324](https://github.com/active-hash/active_hash/pull/324) @flavorjones
|
|
25
|
+
|
|
26
|
+
### Fixed
|
|
27
|
+
|
|
28
|
+
- Fix Do not suppress load errors[#309](https://github.com/active-hash/active_hash/pull/309) @andreynering
|
|
29
|
+
- Ensure `field_names` are all strings [#312](https://github.com/active-hash/active_hash/pull/312) @flavorjones
|
|
30
|
+
- Hide private `add_default_value` [#314](https://github.com/active-hash/active_hash/pull/314) @kbrock
|
|
31
|
+
- Fix `exists?(nil)` [#320](https://github.com/active-hash/active_hash/pull/320) @y-yagi
|
|
32
|
+
- Enance Enum support [#321](https://github.com/active-hash/active_hash/pull/321) @hatsu38
|
|
33
|
+
- Updated docs [#326](https://github.com/active-hash/active_hash/pull/326) @y-yagi
|
|
34
|
+
|
|
35
|
+
### Removed
|
|
36
|
+
|
|
37
|
+
- Drop Active Record < 6.1. Ruby < 3.0 [#324](https://github.com/active-hash/active_hash/pull/324) @flavorjones
|
|
38
|
+
|
|
3
39
|
## Version [3.3.1] - <sub><sup>2024-05-03</sup></sub>
|
|
4
40
|
|
|
5
41
|
### Fixed
|
|
@@ -329,7 +365,9 @@
|
|
|
329
365
|
- Setting data to nil correctly causes .all to return an empty array
|
|
330
366
|
- Added reload(force) method, so that you can force a reload from files in ActiveFile, useful for tests
|
|
331
367
|
|
|
332
|
-
[HEAD]: https://github.com/active-hash/active_hash/compare/
|
|
368
|
+
[HEAD]: https://github.com/active-hash/active_hash/compare/v4.1.0...HEAD
|
|
369
|
+
[4.1.0]: https://github.com/active-hash/active_hash/compare/v4.0.0...v4.1.0
|
|
370
|
+
[3.3.1]: https://github.com/active-hash/active_hash/compare/v3.3.0...v3.3.1
|
|
333
371
|
[3.3.0]: https://github.com/active-hash/active_hash/compare/v3.2.1...v3.3.0
|
|
334
372
|
[3.2.1]: https://github.com/active-hash/active_hash/compare/v3.2.0...v3.2.1
|
|
335
373
|
[3.2.0]: https://github.com/active-hash/active_hash/compare/v3.1.1...v3.2.0
|
data/README.md
CHANGED
|
@@ -34,7 +34,11 @@ Other:
|
|
|
34
34
|
gem install active_hash
|
|
35
35
|
```
|
|
36
36
|
|
|
37
|
-
|
|
37
|
+
Requirements:
|
|
38
|
+
|
|
39
|
+
- v1.x: Ruby >= 1.9.3, Rails >= 2.2.2
|
|
40
|
+
- v2.x, v3.x: Ruby >= 2.4, Rails >= 5
|
|
41
|
+
- upcoming: Ruby >= 3.0, Rails >= 6.1
|
|
38
42
|
|
|
39
43
|
```ruby
|
|
40
44
|
gem 'active_hash', '~> 1.5.3'
|
|
@@ -558,7 +562,7 @@ Call `Model.reload(true)` to force reload the data from disk.
|
|
|
558
562
|
In Rails, you can use this snippet. Please just note it resets the state every request, which may not always be desired.
|
|
559
563
|
|
|
560
564
|
```ruby
|
|
561
|
-
|
|
565
|
+
before_action do
|
|
562
566
|
[Model1, Model2, Model3].each { |m| m.reload(true) }
|
|
563
567
|
end
|
|
564
568
|
```
|
|
@@ -606,6 +610,20 @@ Constants are formed by first stripping all non-word characters and then upcasin
|
|
|
606
610
|
|
|
607
611
|
The field specified as the _enum_accessor_ must contain unique data values.
|
|
608
612
|
|
|
613
|
+
## I18n
|
|
614
|
+
|
|
615
|
+
ActiveHash supports i18n as ActiveModel.
|
|
616
|
+
Put following code in one of your locale file (e.g. `config/locales/LANGUAGE_CODE.yml`)
|
|
617
|
+
|
|
618
|
+
```yaml
|
|
619
|
+
# for example, inside config/locales/ja.yml
|
|
620
|
+
ja:
|
|
621
|
+
activemodel:
|
|
622
|
+
models:
|
|
623
|
+
# `Country.model_name.human` will evaluates to "国"
|
|
624
|
+
country: "国"
|
|
625
|
+
```
|
|
626
|
+
|
|
609
627
|
## Contributing
|
|
610
628
|
|
|
611
629
|
If you'd like to become an ActiveHash contributor, the easiest way it to fork this repo, make your changes, run the specs and submit a pull request once they pass.
|
|
@@ -619,10 +637,10 @@ If your changes seem reasonable and the specs pass I'll give you commit rights t
|
|
|
619
637
|
|
|
620
638
|
## Releasing a new version
|
|
621
639
|
|
|
622
|
-
To make users' lives easier,
|
|
640
|
+
To make users' lives easier, CI will exercise tests for:
|
|
623
641
|
|
|
624
|
-
* Ruby
|
|
625
|
-
* ActiveRecord/ActiveSupport from
|
|
642
|
+
* Ruby 3.0 through current
|
|
643
|
+
* ActiveRecord/ActiveSupport from 6.1 through edge
|
|
626
644
|
|
|
627
645
|
Once appraisal passes in all supported rubies, follow these steps to release a new version of active_hash:
|
|
628
646
|
|
data/active_hash.gemspec
CHANGED
|
@@ -51,7 +51,7 @@ Gem::Specification.new do |s|
|
|
|
51
51
|
Dir.glob("lib/**/*")
|
|
52
52
|
].flatten
|
|
53
53
|
s.test_files = s.files.grep(%r{^(test|spec|features)/})
|
|
54
|
-
s.add_runtime_dependency('activesupport', '>=
|
|
54
|
+
s.add_runtime_dependency('activesupport', '>= 6.1.0')
|
|
55
55
|
s.add_development_dependency "pry"
|
|
56
|
-
s.required_ruby_version = '>=
|
|
56
|
+
s.required_ruby_version = '>= 3.0.0'
|
|
57
57
|
end
|
data/lib/active_file/base.rb
CHANGED
|
@@ -49,7 +49,7 @@ module ActiveFile
|
|
|
49
49
|
end
|
|
50
50
|
protected :actual_root_path
|
|
51
51
|
|
|
52
|
-
[:find, :find_by_id, :all, :where, :method_missing].each do |method|
|
|
52
|
+
[:find, :find_by_id, :all, :where, :method_missing, :find_each].each do |method|
|
|
53
53
|
define_method(method) do |*args, &block|
|
|
54
54
|
reload unless data_loaded
|
|
55
55
|
return super(*args, &block)
|
data/lib/active_hash/base.rb
CHANGED
|
@@ -25,6 +25,7 @@ module ActiveHash
|
|
|
25
25
|
|
|
26
26
|
if Object.const_defined?(:ActiveModel)
|
|
27
27
|
extend ActiveModel::Naming
|
|
28
|
+
extend ActiveModel::Translation
|
|
28
29
|
include ActiveModel::Conversion
|
|
29
30
|
else
|
|
30
31
|
def to_param
|
|
@@ -50,6 +51,23 @@ module ActiveHash
|
|
|
50
51
|
@field_names ||= []
|
|
51
52
|
end
|
|
52
53
|
|
|
54
|
+
#
|
|
55
|
+
# Useful for CSV integration needing column names as strings.
|
|
56
|
+
#
|
|
57
|
+
# @return [Array<String>] An array of column names as strings.
|
|
58
|
+
#
|
|
59
|
+
# @example Usage
|
|
60
|
+
# class Country < ActiveHash::Base
|
|
61
|
+
# fields :name, :code
|
|
62
|
+
# end
|
|
63
|
+
#
|
|
64
|
+
# Country.column_names
|
|
65
|
+
# # => ["id", "name", "code"]
|
|
66
|
+
#
|
|
67
|
+
def column_names
|
|
68
|
+
field_names.map(&:name)
|
|
69
|
+
end
|
|
70
|
+
|
|
53
71
|
def the_meta_class
|
|
54
72
|
class << self
|
|
55
73
|
self
|
|
@@ -85,17 +103,17 @@ module ActiveHash
|
|
|
85
103
|
end
|
|
86
104
|
end
|
|
87
105
|
|
|
88
|
-
def exists?(args =
|
|
106
|
+
def exists?(args = :none)
|
|
89
107
|
if args.respond_to?(:id)
|
|
90
108
|
record_index[args.id.to_s].present?
|
|
91
|
-
elsif args
|
|
109
|
+
elsif !args
|
|
92
110
|
false
|
|
93
|
-
elsif args
|
|
111
|
+
elsif args == :none
|
|
94
112
|
all.present?
|
|
95
113
|
elsif args.is_a?(Hash)
|
|
96
114
|
all.where(args).present?
|
|
97
115
|
else
|
|
98
|
-
all.where(id: args.
|
|
116
|
+
all.where(id: args.to_s).present?
|
|
99
117
|
end
|
|
100
118
|
end
|
|
101
119
|
|
|
@@ -172,7 +190,7 @@ module ActiveHash
|
|
|
172
190
|
relation
|
|
173
191
|
end
|
|
174
192
|
|
|
175
|
-
delegate :where, :find, :find_by, :find_by!, :find_by_id, :count, :pluck, :ids, :pick, :first, :last, :order, to: :all
|
|
193
|
+
delegate :where, :find_each, :find, :find_by, :find_by!, :find_by_id, :count, :pluck, :ids, :pick, :first, :last, :order, to: :all
|
|
176
194
|
|
|
177
195
|
def transaction
|
|
178
196
|
yield
|
|
@@ -198,7 +216,9 @@ module ActiveHash
|
|
|
198
216
|
end
|
|
199
217
|
|
|
200
218
|
def field(field_name, options = {})
|
|
219
|
+
field_name = field_name.to_sym
|
|
201
220
|
validate_field(field_name)
|
|
221
|
+
|
|
202
222
|
field_names << field_name
|
|
203
223
|
|
|
204
224
|
add_default_value(field_name, options[:default]) if options.key?(:default)
|
|
@@ -210,7 +230,8 @@ module ActiveHash
|
|
|
210
230
|
end
|
|
211
231
|
|
|
212
232
|
def validate_field(field_name)
|
|
213
|
-
|
|
233
|
+
field_name = field_name.to_sym
|
|
234
|
+
if [:attributes].include?(field_name)
|
|
214
235
|
raise ReservedFieldError.new("#{field_name} is a reserved field in ActiveHash. Please use another name.")
|
|
215
236
|
end
|
|
216
237
|
end
|
|
@@ -263,8 +284,10 @@ module ActiveHash
|
|
|
263
284
|
self.default_attributes[field_name] = default_value
|
|
264
285
|
end
|
|
265
286
|
|
|
287
|
+
private :add_default_value
|
|
288
|
+
|
|
266
289
|
def define_getter_method(field, default_value)
|
|
267
|
-
unless instance_methods.include?(field
|
|
290
|
+
unless instance_methods.include?(field)
|
|
268
291
|
define_method(field) do
|
|
269
292
|
attributes[field].nil? ? default_value : attributes[field]
|
|
270
293
|
end
|
data/lib/active_hash/relation.rb
CHANGED
|
@@ -7,6 +7,8 @@ module ActiveHash
|
|
|
7
7
|
delegate :empty?, :length, :first, :second, :third, :last, to: :records
|
|
8
8
|
delegate :sample, to: :records
|
|
9
9
|
|
|
10
|
+
alias find_each each
|
|
11
|
+
|
|
10
12
|
attr_reader :conditions, :order_values, :klass, :all_records
|
|
11
13
|
|
|
12
14
|
def initialize(klass, all_records, conditions = nil, order_values = nil)
|
|
@@ -22,6 +24,22 @@ module ActiveHash
|
|
|
22
24
|
spawn.where!(conditions_hash)
|
|
23
25
|
end
|
|
24
26
|
|
|
27
|
+
def or(other)
|
|
28
|
+
unless other.is_a?(self.class)
|
|
29
|
+
raise ArgumentError, "or() expects an ActiveHash::Relation"
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
unless other.klass == klass
|
|
33
|
+
raise ArgumentError, "or() expects relations for the same model"
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
merged = (records + other.records).uniq do |record|
|
|
37
|
+
record.respond_to?(:id) ? record.id : record.object_id
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
self.class.new(klass, merged, [], order_values)
|
|
41
|
+
end
|
|
42
|
+
|
|
25
43
|
def pretty_print(pp)
|
|
26
44
|
pp.pp(entries.to_ary)
|
|
27
45
|
end
|
|
@@ -135,6 +153,7 @@ module ActiveHash
|
|
|
135
153
|
end
|
|
136
154
|
|
|
137
155
|
def count
|
|
156
|
+
return super if block_given?
|
|
138
157
|
length
|
|
139
158
|
end
|
|
140
159
|
|
data/lib/active_hash/version.rb
CHANGED
|
@@ -8,19 +8,16 @@ module ActiveHash
|
|
|
8
8
|
|
|
9
9
|
def has_many(association_id, scope = nil, **options, &extension)
|
|
10
10
|
if options[:through]
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
rescue StandardError, LoadError
|
|
16
|
-
nil
|
|
17
|
-
end
|
|
11
|
+
source_association_name = options[:source]&.to_s || association_id.to_s.singularize
|
|
12
|
+
|
|
13
|
+
through_klass = reflect_on_association(options[:through])&.klass
|
|
14
|
+
klass = through_klass&.reflect_on_association(source_association_name)&.klass
|
|
18
15
|
|
|
19
16
|
if klass && klass < ActiveHash::Base
|
|
20
17
|
define_method(association_id) do
|
|
21
18
|
join_models = send(options[:through])
|
|
22
19
|
join_models.flat_map do |join_model|
|
|
23
|
-
join_model.send(
|
|
20
|
+
join_model.send(source_association_name)
|
|
24
21
|
end.uniq
|
|
25
22
|
end
|
|
26
23
|
|
|
@@ -33,12 +30,7 @@ module ActiveHash
|
|
|
33
30
|
|
|
34
31
|
def belongs_to(name, scope = nil, **options)
|
|
35
32
|
klass_name = options.key?(:class_name) ? options[:class_name] : name.to_s.camelize
|
|
36
|
-
klass =
|
|
37
|
-
begin
|
|
38
|
-
klass_name.safe_constantize
|
|
39
|
-
rescue StandardError, LoadError
|
|
40
|
-
nil
|
|
41
|
-
end
|
|
33
|
+
klass = klass_name.safe_constantize
|
|
42
34
|
|
|
43
35
|
if klass && klass < ActiveHash::Base
|
|
44
36
|
options = { class_name: klass_name }.merge(options)
|
data/lib/enum/enum.rb
CHANGED
|
@@ -14,6 +14,20 @@ module ActiveHash
|
|
|
14
14
|
reload
|
|
15
15
|
end
|
|
16
16
|
|
|
17
|
+
def enum(columns)
|
|
18
|
+
columns.each do |column, values|
|
|
19
|
+
values = values.zip(values.map(&:to_s)).to_h if values.is_a?(Array)
|
|
20
|
+
values.each do |method, value|
|
|
21
|
+
class_eval <<~METHOD, __FILE__, __LINE__ + 1
|
|
22
|
+
# frozen_string_literal: true
|
|
23
|
+
def #{method}?
|
|
24
|
+
#{column} == #{value.inspect}
|
|
25
|
+
end
|
|
26
|
+
METHOD
|
|
27
|
+
end
|
|
28
|
+
end
|
|
29
|
+
end
|
|
30
|
+
|
|
17
31
|
def insert(record)
|
|
18
32
|
super
|
|
19
33
|
set_constant(record) if defined?(@enum_accessors)
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: active_hash
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version:
|
|
4
|
+
version: 4.1.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Jeff Dean
|
|
@@ -26,10 +26,9 @@ authors:
|
|
|
26
26
|
- Brett Richardson
|
|
27
27
|
- Rachel Heaton
|
|
28
28
|
- Keisuke Izumiya
|
|
29
|
-
autorequire:
|
|
30
29
|
bindir: bin
|
|
31
30
|
cert_chain: []
|
|
32
|
-
date:
|
|
31
|
+
date: 1980-01-02 00:00:00.000000000 Z
|
|
33
32
|
dependencies:
|
|
34
33
|
- !ruby/object:Gem::Dependency
|
|
35
34
|
name: activesupport
|
|
@@ -37,14 +36,14 @@ dependencies:
|
|
|
37
36
|
requirements:
|
|
38
37
|
- - ">="
|
|
39
38
|
- !ruby/object:Gem::Version
|
|
40
|
-
version:
|
|
39
|
+
version: 6.1.0
|
|
41
40
|
type: :runtime
|
|
42
41
|
prerelease: false
|
|
43
42
|
version_requirements: !ruby/object:Gem::Requirement
|
|
44
43
|
requirements:
|
|
45
44
|
- - ">="
|
|
46
45
|
- !ruby/object:Gem::Version
|
|
47
|
-
version:
|
|
46
|
+
version: 6.1.0
|
|
48
47
|
- !ruby/object:Gem::Dependency
|
|
49
48
|
name: pry
|
|
50
49
|
requirement: !ruby/object:Gem::Requirement
|
|
@@ -93,7 +92,6 @@ metadata:
|
|
|
93
92
|
changelog_uri: https://github.com/active-hash/active_hash/blob/master/CHANGELOG.md
|
|
94
93
|
source_code_uri: http://github.com/active-hash/active_hash
|
|
95
94
|
bug_tracker_uri: https://github.com/active-hash/active_hash/issues
|
|
96
|
-
post_install_message:
|
|
97
95
|
rdoc_options: []
|
|
98
96
|
require_paths:
|
|
99
97
|
- lib
|
|
@@ -101,15 +99,14 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
|
101
99
|
requirements:
|
|
102
100
|
- - ">="
|
|
103
101
|
- !ruby/object:Gem::Version
|
|
104
|
-
version:
|
|
102
|
+
version: 3.0.0
|
|
105
103
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
106
104
|
requirements:
|
|
107
105
|
- - ">="
|
|
108
106
|
- !ruby/object:Gem::Version
|
|
109
107
|
version: '0'
|
|
110
108
|
requirements: []
|
|
111
|
-
rubygems_version:
|
|
112
|
-
signing_key:
|
|
109
|
+
rubygems_version: 4.0.9
|
|
113
110
|
specification_version: 4
|
|
114
111
|
summary: An ActiveRecord-like model that uses a hash or file as a datasource
|
|
115
112
|
test_files: []
|