https://github.com/rstankov/miniform
Sugar around ActiveModel::Model
https://github.com/rstankov/miniform
activemodel form gem ruby
Last synced: 12 months ago
JSON representation
Sugar around ActiveModel::Model
- Host: GitHub
- URL: https://github.com/rstankov/miniform
- Owner: RStankov
- License: mit
- Created: 2015-02-22T21:18:36.000Z (about 11 years ago)
- Default Branch: master
- Last Pushed: 2024-04-21T19:48:10.000Z (almost 2 years ago)
- Last Synced: 2025-02-27T01:11:09.450Z (12 months ago)
- Topics: activemodel, form, gem, ruby
- Language: Ruby
- Homepage:
- Size: 62.5 KB
- Stars: 30
- Watchers: 4
- Forks: 7
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
- Changelog: CHANGELOG.md
- License: LICENSE.txt
Awesome Lists containing this project
README
[](http://badge.fury.io/rb/mini_form)
[](https://codeclimate.com/github/RStankov/MiniForm)
[](https://coveralls.io/r/RStankov/MiniForm)
# MiniForm
Helpers for dealing with form objects and nested forms.
## Installation
Add this line to your application's Gemfile:
```ruby
gem 'mini_form'
```
And then execute:
$ bundle
Or install it yourself as:
$ gem install mini_form
## Usage
```ruby
class ProductForm
include MiniForm::Model
attributes :id, :name, :price, :description
validates :name, :price, :description, presence: true
# called after successful validations in update
def perform
@id = ExternalService.create(attributes)
end
end
```
```ruby
class ProductsController < ApplicationController
def create
@product = ProductForm.new
if @product.update(product_params)
redirect_to product_path(@product.id)
else
render :edit
end
end
private
def product_params
params.require(:product).permit(:name, :price, :description)
end
end
```
### Delegated attributes
Attributes can be delegated to a sub object.
```ruby
class SignUpForm
include MiniForm::Model
attr_reader :account, :user
attributes :name, :email, delegate: :user
attributes :company_name, :plan, delegate: :account
validates :name, :email, :company_name, :plan, presence: true
def initialize
@account = Account.new
@user = User.new account: @account
end
def perform
user.save!
account.save!
end
end
```
```ruby
form = SignUpForm.new
form.name = 'name' # => form.user.name = 'name'
form.name # => form.user.name
form.plan = 'free' # => form.account.plan = 'free'
form.plan # => form.account.plan
```
### Nested validator
`mini_form/nested` validator runs validations on the given model and copies errors to the form object.
```ruby
class SignUpForm
include MiniForm::Model
attr_reader :account, :user
attributes :name, :email, delegate: :user
attributes :company_name, :plan, delegate: :account
validates :account, :user, 'mini_form/nested' => true
def initialize
@account = Account.new
@user = User.new account: @account
end
def perform
account.save!
user.save!
end
end
```
### Nested models
Combines delegated attributes and nested validation into a single call.
```ruby
class SignUpForm
include MiniForm::Model
model :user, attributes: %i(name email)
model :account, attributes: %i(company_name plan)
def initialize
@account = Account.new
@user = User.new account: @account
end
def perform
account.save!
user.save!
end
end
```
### Auto saving nested models
Most of the time `perform` is just calling `save!`. We can avoid this by using `model`'s `save` option.
```ruby
class SignUpForm
include MiniForm::Model
model :user, attributes: %i(name email), save: true
model :account, attributes: %i(company_name plan), save: true
def initialize
@account = Account.new
@user = User.new account: @account
end
end
```
### Before/after callbacks
```ruby
class SignUpForm
include MiniForm::Model
# ... code
before_update :run_before_update
after_update :run_after_update
private
def run_before_update
# ...
end
def run_after_update
# ...
end
# alternatively you can overwrite "before_update"
def before_update
end
# alternatively you can overwrite "after_update"
def after_update
end
end
```
### Using in forms
Using `main_model` will delegate `id`, `to_param`, `persisted?` and `new_record?` to the model. Allowing you to use it in forms.
```ruby
class SignUpForm
include MiniForm::Model
main_model :user
def initialize
@user = User.new(account: @account)
end
end
```
```eruby
<% form_for SignUpForm.new %>
```
### Delegating model attributes
```ruby
class SignUpForm
include MiniForm::Model
model :user, attributes: %i(name email), read: %i(id)
def initialize
@user = User.new(account: @account)
end
end
```
```
form = SignUpForm.new
form.update! form_params
form.id # => delegates to `user.id`
form.id = 42 # => raises `NoMethodError`
```
### Methods
Method
Description
.model
Defines a sub object for the form
.attributes
Defines an attribute, it can delegate to sub object
.attribute_names
Returns list of attribute names
#initialize
Meant to be overwritten. By defaults calls `attributes=`
#attributes=
Sets values of all attributes
#attributes
Returns all attributes of the form
#update
Sets attributes, calls validations, saves models and `perform`
#update!
Calls `update`. If validation fails, it raises an error
#perform
Meant to be overwritten. Doesn't do anything by default
#before_update
Meant to be overwritten.
#after_update
Meant to be overwritten.
#before_assignment
Meant to be overwritten.
#after_assignment
Meant to be overwritten.
#transaction
If ActiveRecord is available, wraps `perform` in transaction.
## Contributing
1. Fork it
2. Create your feature branch (`git checkout -b my-new-feature`)
3. Commit your changes (`git commit -am 'Add some feature'`)
4. Push to the branch (`git push origin my-new-feature`)
5. Run the tests (`rake`)
6. Create new Pull Request
## License
**[MIT License](https://github.com/RStankov/MiniForm/blob/master/LICENSE.txt)**