store_model 1.3.0 → 1.5.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: f464327535385fc17ade5f91d0c88ac4cc09233f995bc48d4e926ecd6cab4b67
4
- data.tar.gz: 4497217fa0c66f0e8587e1e66e7ace5a83209835901ed300f15bab8a6651990b
3
+ metadata.gz: 5cc3ab45857fd85292b845bb4b7dccfe0c3df64e4baebb1387599800f16caafe
4
+ data.tar.gz: a772d44ba83b7236992f21b854a1b7a76ef353c2b32083f996a9c78306402468
5
5
  SHA512:
6
- metadata.gz: b19c7f3fa44d7fc49925d450d1b97318002174b38dff46ae84611d61eb857833fd660570a1a4244eb8b21b60d9242d33c7e6e2e62471a3306bd8c46389308727
7
- data.tar.gz: b710ea76a0ecb1ac7193dc5e536b947456895c1839b6efd92b5e06a5dec560d7d67f019c7c92e5c92ab5cd36df96ef730ff03fb638cbff933419fd066e3583df
6
+ metadata.gz: d2ece15986e487b1eb67c6a81dc8c2a6173f726f7be72ee531328b9fe79271a30d6cd608d0d51d4d32ffd59316e7f961c946445d83f686099dc9992dc256f990
7
+ data.tar.gz: e9e4512c14d680360db6fb57b0e9a96676a62377656057ab4a530730c38c91826f7603bf5ea11e46e1c8673c2d0c93d48a6c1347350db34a6c2cd9f6753fd9a2
data/README.md CHANGED
@@ -1,4 +1,4 @@
1
- # StoreModel [![Gem Version](https://badge.fury.io/rb/store_model.svg)](https://rubygems.org/gems/store_model) [![Coverage Status](https://coveralls.io/repos/github/DmitryTsepelev/store_model/badge.svg?branch=master)](https://coveralls.io/github/DmitryTsepelev/store_model?branch=master)
1
+ # StoreModel [![Gem Version](https://badge.fury.io/rb/store_model.svg)](https://rubygems.org/gems/store_model) [![Coverage Status](https://coveralls.io/repos/github/DmitryTsepelev/store_model/badge.svg?branch=master)](https://coveralls.io/github/DmitryTsepelev/store_model?branch=master) ![](https://ruby-gem-downloads-badge.herokuapp.com/store_model?type=total)
2
2
 
3
3
  **StoreModel** gem allows you to wrap JSON-backed DB columns with ActiveModel-like classes.
4
4
 
@@ -22,12 +22,6 @@ class Product < ApplicationRecord
22
22
  end
23
23
  ```
24
24
 
25
- <p align="center">
26
- <a href="https://evilmartians.com/?utm_source=store_model">
27
- <img src="https://evilmartians.com/badges/sponsored-by-evil-martians.svg" alt="Sponsored by Evil Martians" width="236" height="54">
28
- </a>
29
- </p>
30
-
31
25
  ## Why should I wrap my JSON columns?
32
26
 
33
27
  Imagine that you have a model `Product` with a `jsonb` column called `configuration`. This is how you likely gonna work with this column:
@@ -42,7 +36,7 @@ product.save
42
36
 
43
37
  This approach works fine when you don't have a lot of keys with logic around them and just read the data. However, when you start working with that data more intensively–you may find the code a bit verbose and error-prone.
44
38
 
45
- For instance, try to find a way to validate `:model` value to be required. Despite of the fact, that you'll have to write this validation by hand, it violates single-repsponsibility principle: why parent model (`Product`) should know about the logic related to a child (`Configuration`)?
39
+ For instance, try to find a way to validate `:model` value to be required. Despite of the fact, that you'll have to write this validation by hand, it violates the single-responsibility principle: why parent model (`Product`) should know about the logic related to a child (`Configuration`)?
46
40
 
47
41
  > 📖 Read more about the motivation in the [Wrapping JSON-based ActiveRecord attributes with classes](https://evilmartians.com/chronicles/wrapping-json-based-active-record-attributes-with-classes) post
48
42
 
@@ -97,6 +91,10 @@ _Usage note: Rails and assigning Arrays/Hashes to records_
97
91
  4. [Alternatives](./docs/alternatives.md)
98
92
  5. [Defining custom types](./docs/defining_custom_types.md)
99
93
 
94
+ ## Credits
95
+
96
+ Initially sponsored by [Evil Martians](http://evilmartians.com).
97
+
100
98
  ## License
101
99
 
102
100
  The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
@@ -10,16 +10,42 @@ module StoreModel
10
10
  module ClassMethods # :nodoc:
11
11
  # Enables handling of nested StoreModel::Model attributes
12
12
  #
13
- # @param associations [Array] list of associations to define attributes
13
+ # @param associations [Array] list of associations and options to define attributes, for example:
14
+ # accepts_nested_attributes_for [:suppliers, allow_destroy: true]
15
+ #
16
+ # Supported options:
17
+ # [:allow_destroy]
18
+ # If true, destroys any members from the attributes hash with a
19
+ # <tt>_destroy</tt> key and a value that evaluates to +true+
20
+ # (e.g. 1, '1', true, or 'true'). This option is off by default.
14
21
  def accepts_nested_attributes_for(*associations)
15
- associations.each do |association|
22
+ associations.each do |association, options|
16
23
  case attribute_types[association.to_s]
17
24
  when Types::One
25
+ define_association_setter_for_single(association, options)
18
26
  alias_method "#{association}_attributes=", "#{association}="
19
27
  when Types::Many
20
- define_method "#{association}_attributes=" do |attributes|
21
- assign_nested_attributes_for_collection_association(association, attributes)
22
- end
28
+ define_association_setter_for_many(association, options)
29
+ end
30
+ end
31
+ end
32
+
33
+ private
34
+
35
+ def define_association_setter_for_many(association, options)
36
+ define_method "#{association}_attributes=" do |attributes|
37
+ assign_nested_attributes_for_collection_association(association, attributes, options)
38
+ end
39
+ end
40
+
41
+ def define_association_setter_for_single(association, options)
42
+ return unless options&.dig(:allow_destroy)
43
+
44
+ define_method "#{association}=" do |attributes|
45
+ if ActiveRecord::Type::Boolean.new.cast(attributes.stringify_keys.dig("_destroy"))
46
+ super(nil)
47
+ else
48
+ super(attributes)
23
49
  end
24
50
  end
25
51
  end
@@ -27,9 +53,16 @@ module StoreModel
27
53
 
28
54
  private
29
55
 
30
- def assign_nested_attributes_for_collection_association(association, attributes)
56
+ def assign_nested_attributes_for_collection_association(association, attributes, options)
31
57
  attributes = attributes.values if attributes.is_a?(Hash)
32
- send "#{association}=", attributes
58
+
59
+ if options&.dig(:allow_destroy)
60
+ attributes.reject! do |attribute|
61
+ ActiveRecord::Type::Boolean.new.cast(attribute.stringify_keys.dig("_destroy"))
62
+ end
63
+ end
64
+
65
+ send("#{association}=", attributes)
33
66
  end
34
67
  end
35
68
  end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module StoreModel # :nodoc:
4
- VERSION = "1.3.0"
4
+ VERSION = "1.5.0"
5
5
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: store_model
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.3.0
4
+ version: 1.5.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - DmitryTsepelev
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2022-10-21 00:00:00.000000000 Z
11
+ date: 2023-01-16 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activerecord