activerecord-null 0.1.0 → 0.1.2

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: 7bb3c3183d7c9c124c3858a72534649bf8e501f6371942e8a1a06697df1caadf
4
- data.tar.gz: c280cf8d79aba38ded094dd6140f2ff4f7075b295531326f4e23ecb2df7a4524
3
+ metadata.gz: f5da1cf27cad7e88a6c6696874f43ea35670baea4ba390b6d19d2ab9f044d842
4
+ data.tar.gz: fd69ad9dfe3b66e186aecb8b6b8411d814fad60ad908d2816e0e9a0ac2ad0a39
5
5
  SHA512:
6
- metadata.gz: c861a1f9cb0cc2685e6a611810521539ae1c6e91bff2864607d44f342380d1822bb9cd7f0ed32b9791d6e52dcc7e8c57b7a7ee01371964b6df25c0b8df83b3a5
7
- data.tar.gz: 9aa04f050ad57a08a6005b8ac01b27548644a4098e301452a58d3c8f5d66c4d76efc158b5d6cb1347c36ae7906e2b01c00eaba0add423621c4a54963b9687f5e
6
+ metadata.gz: 5c9f845b168b47184197bfc10367fc4a7b93bec34e9f31e01a81a88c64b4a55e7b1d09e911ed08cf19eb562738cc9255f43e43a03d5a832ced57d295e642fcca
7
+ data.tar.gz: a7fb4fe100e29d9151d2fefd5696db658171f4c061a0ded77424b7c1d2e947db4fec50c4c5d6cb0132a56463b22bfddc0da98ce064670d02c1713b159b1042bf
data/CHANGELOG.md CHANGED
@@ -5,8 +5,16 @@ All notable changes to this project will be documented in this file.
5
5
  The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
6
6
  and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7
7
 
8
- ## [0.1.0] - 2024-10-23
8
+ ## [0.1.2] - 2025-06-17
9
+
10
+ ## [0.1.1] - 2024-10-25
9
11
 
10
12
  ### Added
11
13
 
12
- - Initial release
14
+ - `null?` method to both parent class objects and null objects
15
+ - Null objects now have default nil values for attributes of the mimic model class
16
+ - `Null()` method can now accept a hash of attribute names and values to assign to the null object
17
+ - `has_query_constraints?` method to null objects
18
+ - `respond_to?` method to null objects
19
+ - `_read_attribute` method to null objects
20
+ - Null class now return false for `composite_primary_key?`
data/README.md CHANGED
@@ -48,6 +48,26 @@ It will even work with associations.
48
48
  User.null.posts # => []
49
49
  ```
50
50
 
51
+ By default, the null object will have the same attributes as the original model and will return `nil` for all attributes.
52
+
53
+ You can override this by passing a hash to the `Null` method where the key is an array of attributes and the value is the value to return for the attribute.
54
+
55
+ ```ruby
56
+ class User < ApplicationRecord
57
+ Null([:name, :team_name] => "Unknown") do
58
+ def other_attribute = "Other"
59
+ end
60
+ end
61
+ ```
62
+
63
+ You may also pass a callable to the hash which will be used to determine the value for the attribute.
64
+
65
+ ```ruby
66
+ class User < ApplicationRecord
67
+ Null([:name, :team_name] => -> { "Unknown" })
68
+ end
69
+ ```
70
+
51
71
  ## Development
52
72
 
53
73
  After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake test` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
@@ -17,6 +17,18 @@ module ActiveRecord
17
17
  def self.table_name = @mimic_model_class.to_s.tableize
18
18
 
19
19
  def self.primary_key = @mimic_model_class.primary_key
20
+
21
+ def self.define_attribute_methods(attribute_names, value: nil)
22
+ attribute_names.each do |attribute_name|
23
+ unless method_defined?(attribute_name)
24
+ if value.is_a?(Proc)
25
+ define_method(attribute_name, &value)
26
+ else
27
+ define_method(attribute_name) { value }
28
+ end
29
+ end
30
+ end
31
+ end
20
32
  end
21
33
 
22
34
  def mimic_model_class = self.class.mimic_model_class
@@ -34,12 +46,16 @@ module ActiveRecord
34
46
  end
35
47
  end
36
48
 
49
+ def null? = true
50
+
37
51
  def destroyed? = false
38
52
 
39
53
  def new_record? = false
40
54
 
41
55
  def persisted? = false
42
56
 
57
+ def _read_attribute(_) = nil
58
+
43
59
  def method_missing(method, ...)
44
60
  reflections = mimic_model_class.reflect_on_all_associations
45
61
  if (reflection = reflections.find { |r| r.name == method })
@@ -63,7 +79,7 @@ module ActiveRecord
63
79
  private
64
80
 
65
81
  def define_memoized_association(method, value)
66
- define_singleton_method(method) do
82
+ self.class.define_method(method) do
67
83
  if instance_variable_defined?(:"@#{method}")
68
84
  instance_variable_get(:"@#{method}")
69
85
  else
@@ -2,6 +2,6 @@
2
2
 
3
3
  module ActiveRecord
4
4
  module Null
5
- VERSION = "0.1.0"
5
+ VERSION = "0.1.2"
6
6
  end
7
7
  end
@@ -15,25 +15,62 @@ module ActiveRecord
15
15
  # Define a Null class for the given class.
16
16
  #
17
17
  # @example
18
- # class Business
18
+ # class Business < ApplicationRecord
19
19
  # Null do
20
20
  # def name = "None"
21
21
  # end
22
22
  # end
23
23
  #
24
24
  # Business.null # => #<Business::Null:0x0000000000000000>
25
+ # Business.null.name # => "None"
25
26
  #
26
- def Null(klass = self, &)
27
+ # class User < ApplicationRecord
28
+ # Null([:name, :team_name] => "Unknown")
29
+ # end
30
+ #
31
+ # User.null.name # => "Unknown"
32
+ # User.null.team_name # => "Unknown"
33
+ #
34
+ # @param inherit [Class] The class from which the Null object inherits attributes
35
+ # @param assignments [Array] The attributes to assign to the null object
36
+ def Null(inherit = self, assignments = {}, &)
37
+ if inherit.is_a?(Hash)
38
+ assignments = inherit
39
+ inherit = self
40
+ end
27
41
  null_class = Class.new do
28
42
  include ::ActiveRecord::Null::Mimic
29
- mimics klass
43
+ mimics inherit
30
44
 
31
45
  include Singleton
46
+
47
+ class << self
48
+ def method_missing(method, ...)
49
+ mimic_model_class.respond_to?(method) ? mimic_model_class.send(method, ...) : super
50
+ end
51
+
52
+ def respond_to_missing?(method, include_private = false)
53
+ mimic_model_class.respond_to?(method, include_private) || super
54
+ end
55
+ end
56
+ end
57
+ null_class.class_eval(&) if block_given?
58
+
59
+ nil_assignments = inherit.attribute_names
60
+ if assignments.any?
61
+ assignments.each do |attributes, value|
62
+ nil_assignments -= attributes
63
+ null_class.define_attribute_methods(attributes, value:)
64
+ end
32
65
  end
33
- null_class.class_eval(&)
34
- const_set(:Null, null_class)
66
+ null_class.define_attribute_methods(nil_assignments)
67
+ inherit.const_set(:Null, null_class)
68
+
69
+ inherit.define_singleton_method(:null) { null_class.instance }
70
+ end
35
71
 
36
- define_singleton_method(:null) { null_class.instance }
72
+ def self.extended(base)
73
+ base.define_method(:null?) { false }
37
74
  end
38
75
  end
39
76
  end
@@ -15,13 +15,15 @@ end
15
15
 
16
16
  class Post < ApplicationRecord
17
17
  belongs_to :user
18
+
19
+ Null([:description] => -> { "From the callable!" })
18
20
  end
19
21
 
20
22
  class User < ApplicationRecord
21
23
  belongs_to :business
22
24
  has_many :posts
23
25
 
24
- Null do
26
+ Null([:team_name, :other] => "Unknown") do
25
27
  def name = "None"
26
28
  end
27
29
  end
@@ -33,7 +35,23 @@ class ActiveRecord::TestNull < Minitest::Spec
33
35
  end
34
36
  end
35
37
 
38
+ describe ".has_query_constraints?" do
39
+ it "returns false" do
40
+ expect(User::Null.has_query_constraints?).must_equal false
41
+ end
42
+ end
43
+
44
+ describe ".composite_primary_key?" do
45
+ it "returns false" do
46
+ expect(User::Null.composite_primary_key?).must_equal false
47
+ end
48
+ end
49
+
36
50
  describe "Null" do
51
+ it "is null" do
52
+ expect(User.null.null?).must_equal true
53
+ end
54
+
37
55
  it "is not persisted" do
38
56
  expect(User.null.persisted?).must_equal false
39
57
  end
@@ -82,5 +100,35 @@ class ActiveRecord::TestNull < Minitest::Spec
82
100
  expect(User.null.posts).must_be_kind_of ActiveRecord::Relation
83
101
  expect(User.null.posts.to_a).must_equal []
84
102
  end
103
+
104
+ it "has default nil values for attributes of the mimic model class" do
105
+ expect(Post.null.title).must_be_nil
106
+ end
107
+
108
+ it "creates a Null object without a block" do
109
+ expect(Post.null).must_be_instance_of Post::Null
110
+ end
111
+
112
+ it "assigns the named attributes with the given values" do
113
+ expect(User.null.team_name).must_equal "Unknown"
114
+ end
115
+
116
+ it "assigns callable values to attributes" do
117
+ expect(Post.null.description).must_equal "From the callable!"
118
+ end
119
+
120
+ it "reads attributes and returns nil" do
121
+ expect(Post.null._read_attribute(:description)).must_be_nil
122
+ end
123
+
124
+ it "responds to mimic methods" do
125
+ expect(Post.null.respond_to?(:description)).must_equal true
126
+ end
127
+ end
128
+
129
+ describe "Parent class object" do
130
+ it "is not null" do
131
+ expect(User.new.null?).must_equal false
132
+ end
85
133
  end
86
134
  end
@@ -5,11 +5,13 @@ ActiveRecord::Schema.define do
5
5
 
6
6
  create_table :users do |t|
7
7
  t.string :name
8
+ t.integer :team_name
8
9
  t.references :business
9
10
  end
10
11
 
11
12
  create_table :posts do |t|
12
13
  t.string :title
14
+ t.string :description
13
15
  t.references :user
14
16
  end
15
17
  end
data/test/test_helper.rb CHANGED
@@ -3,11 +3,10 @@
3
3
  require "simplecov" if ENV["CI"]
4
4
 
5
5
  $LOAD_PATH.unshift File.expand_path("../lib", __dir__)
6
+ require "activerecord/null"
6
7
 
7
8
  require "active_record"
8
9
  ActiveRecord::Base.establish_connection(adapter: "sqlite3", database: ":memory:")
9
10
  load "test/support/schema.rb"
10
11
 
11
- require "activerecord/null"
12
-
13
12
  require "minitest/autorun"
metadata CHANGED
@@ -1,14 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: activerecord-null
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0
4
+ version: 0.1.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Jim Gay
8
- autorequire:
9
8
  bindir: exe
10
9
  cert_chain: []
11
- date: 2024-10-23 00:00:00.000000000 Z
10
+ date: 1980-01-02 00:00:00.000000000 Z
12
11
  dependencies:
13
12
  - !ruby/object:Gem::Dependency
14
13
  name: activerecord
@@ -49,7 +48,6 @@ metadata:
49
48
  homepage_uri: https://github.com/SOFware/activerecord-null
50
49
  source_code_uri: https://github.com/SOFware/activerecord-null
51
50
  changelog_uri: https://github.com/SOFware/activerecord-null/blob/main/CHANGELOG.md
52
- post_install_message:
53
51
  rdoc_options: []
54
52
  require_paths:
55
53
  - lib
@@ -64,8 +62,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
64
62
  - !ruby/object:Gem::Version
65
63
  version: '0'
66
64
  requirements: []
67
- rubygems_version: 3.5.9
68
- signing_key:
65
+ rubygems_version: 3.6.7
69
66
  specification_version: 4
70
67
  summary: Null Objects for ActiveRecord
71
68
  test_files: []