Skip to content

Commit

Permalink
Add convenience methods to instantiate model from type (#192)
Browse files Browse the repository at this point in the history
* Add convenience methods to instantiate model from type

* Add docs for StoreModel::Model.from_value

---------

Co-authored-by: Ben Gladwell <[email protected]>
  • Loading branch information
bengladwell and bengladwell authored Nov 7, 2024
1 parent a1e1972 commit 023c181
Show file tree
Hide file tree
Showing 4 changed files with 85 additions and 1 deletion.
3 changes: 2 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -111,7 +111,7 @@ Resulting in:
In the controller:
```ruby
def create
@supplier = Supplier.new(supplier_params)
@supplier = Supplier.from_value(supplier_params)
@supplier.save
end

Expand All @@ -126,6 +126,7 @@ end

1. [Installation](./docs/installation.md)
2. StoreModel::Model API:
* [Instantiation](./docs/installation.md)
* [Validations](./docs/validations.md)
* [Enums](./docs/enums.md)
* [Nested models](./docs/nested_models.md)
Expand Down
52 changes: 52 additions & 0 deletions docs/instantiation.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
## Instantiation

You can, of course, instantiate a store model object using `new`:
```ruby
class Configuration
include StoreModel::Model

attribute :model, :string
attribute :color, :string

validates :color, presence: true
end

config = Configuration.new(model: "spaceship", color: "red")
```

However, the instance will not have all of the behavior that an instance of a store model
"type" would have. For instance, instantiating with `new` will raise errors when unknown
attributes are passed, rather than providing the [Unknown attributes](./unknown_attributes.md) behavior.

Store model "types" are what are assigned to `attribute` definitions in ActiveModel classes.

E.g.:
```ruby
class Product < ApplicationRecord
attribute :configuration, Configuration.to_type
end
```

If you want to instantiate not just a store model class, but the associated type, you can use
the `from_value` class method:
```ruby
config = Configuration.from_value(model: "spaceship", color: "red", some_other_attribute: "foo")
```

Similarly, if you want to instantiate an array of store model objects, you can use `from_values`:
```ruby
configs = Configuration.from_values([
{model: "spaceship", color: "red", some_other_attribute: "foo"},
{model: "car", color: "blue", some_other_attribute: "bar"}
])
```

These methods are shorthand for
```ruby
Configuration.to_type.cast_value(value)
```
and
```ruby
Configuration.to_array_type.cast_value(values)
```
respectively.
13 changes: 13 additions & 0 deletions lib/store_model/model.rb
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,19 @@ def self.included(base) # :nodoc:
base.extend StoreModel::TypeBuilders

base.attribute_method_suffix "?"

base.extend(ClassMethods)
end

# Class methods for StoreModel::Model
module ClassMethods
def from_value(value)
to_type.cast_value(value)
end

def from_values(values)
to_array_type.cast_value(values)
end
end

attr_accessor :parent
Expand Down
18 changes: 18 additions & 0 deletions spec/store_model/model_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,24 @@
}
end

describe ".from_value" do
context "when unknown attributes are provided" do
it "adds unknown attributes" do
config = Configuration.from_value(attributes.merge(foo: "bar"))
expect(config.unknown_attributes).to include("foo" => "bar")
end
end
end

describe ".from_values" do
context "when unknown attributes are provided" do
it "adds unknown attributes" do
config = Configuration.from_values([attributes.merge(foo: "bar")])
expect(config[0].unknown_attributes).to include("foo" => "bar")
end
end
end

describe "#initialize" do
context "when symbolized hash is passed" do
subject { Configuration.new(attributes) }
Expand Down

0 comments on commit 023c181

Please sign in to comment.