Ruby on Rails - Trailblazer Tutorial: Validations and Classes - ruby on rails tutorial - rails guides - rails tutorial - ruby rails
What is Trailblazer?
- Trailblazer is a framework on top of Rails to serve as architectural guidance.
- It’s like a mesh-up of all the gems I’ve done before with some new concepts like operation, which will model every high level domain action.
- A high level domain operation, as I call it, is something like updating a comment, deleting a user, getting a list of all the recent comments, and so on.
- In essence, it encompasses everything the user can do through the user interface or via the API.
Validations
- Validation in happens in the validate method, and only there.
- Reform will deserialize the fragments and their values to the form and its nested subforms, and once this is done, run validations.
- It returns the result boolean, and provide potential errors via errors.
ruby on rails tutorial tags - ruby , rail , ruby on rails , rail forum , ruby on rails tutorial , ruby tutorial , rails guides , rails tutorial , learn ruby
Validation Groups
- Grouping validations enables you to run them conditionally, or in a specific order. You can
use :if
to specify what group had to be successful for it to be validated
validation :default do
required(:title).filled
end
validation :unique, if: :default do
configure do
def unique?(value)
# ..
end
end
required(:title, &:unique?)
end
Clicking "Copy Code" button will copy the code into the clipboard - memory. Please paste(Ctrl+V) it in your destination. The code will get pasted. Happy coding from Wikitechy - ruby on rails tutorial - rails guides - ruby rails - rubyonrails - learn ruby on rails - team
- This will only run the database-consuming :unique validation group if the :default group was valid.
- Chaining groups works via the :after option. This will run the group regardless of the former result. Note that it still can be combined with :if.
validation :email, after: :default do
configure do
def email?(value)
# ..
end
end
required(:email, &: email?)
end
Clicking "Copy Code" button will copy the code into the clipboard - memory. Please paste(Ctrl+V) it in your destination. The code will get pasted. Happy coding from Wikitechy - ruby on rails tutorial - rails guides - ruby rails - rubyonrails - learn ruby on rails - team
- At any time you can extend an existing group using :inherit
validation :email, inherit: true do
required(:email).filled
end
Clicking "Copy Code" button will copy the code into the clipboard - memory. Please paste(Ctrl+V) it in your destination. The code will get pasted. Happy coding from Wikitechy - ruby on rails tutorial - rails guides - ruby rails - rubyonrails - learn ruby on rails - team
- This appends validations to the existing :email group.
Dry-validation:
- Dry-validation is the preferred backend for defining and executing validations.
- The purest form of defining validations with this backend is by using a validation group. A group provides the exact same API as a Dry::Validation::Schema. You can learn all the details on the gem’s website
require "reform/form/dry"
class AlbumForm < Reform::Form
feature Reform::Form::Dry
property :title
validation :default do
required(:title).filled
end
end
Clicking "Copy Code" button will copy the code into the clipboard - memory. Please paste(Ctrl+V) it in your destination. The code will get pasted. Happy coding from Wikitechy - ruby on rails tutorial - rails guides - ruby rails - rubyonrails - learn ruby on rails - team
- Custom predicates have to be defined in the validation group. If you need access to your form you must add option :form to your configure block
validation :default do
configure do
option :form
def unique?(value)
Album.where.not(id: form.model.id).find_by(title: value).nil?
end
end
required(:title).filled(:unique?)
end
Clicking "Copy Code" button will copy the code into the clipboard - memory. Please paste(Ctrl+V) it in your destination. The code will get pasted. Happy coding from Wikitechy - ruby on rails tutorial - rails guides - ruby rails - rubyonrails - learn ruby on rails - team
- In addition to dry-validation’s API, you have access to the form that contains the group via form
validation :default do
configure do
option :form
def same_password?(value)
value == form.password
end
end
required(:confirm_password).filled(:same_password?)
end
Clicking "Copy Code" button will copy the code into the clipboard - memory. Please paste(Ctrl+V) it in your destination. The code will get pasted. Happy coding from Wikitechy - ruby on rails tutorial - rails guides - ruby rails - rubyonrails - learn ruby on rails - team
Dry: Error Messages
- You need to provide custom error messages via dry-validation mechanics.
validation :default do
configure do
config.messages_file = 'config/error_messages.yml'
end
# ..
end
Clicking "Copy Code" button will copy the code into the clipboard - memory. Please paste(Ctrl+V) it in your destination. The code will get pasted. Happy coding from Wikitechy - ruby on rails tutorial - rails guides - ruby rails - rubyonrails - learn ruby on rails - team
- A simple error messages file might look as follows.
en:
errors:
same_password?: "passwords not equal"
Clicking "Copy Code" button will copy the code into the clipboard - memory. Please paste(Ctrl+V) it in your destination. The code will get pasted. Happy coding from Wikitechy - ruby on rails tutorial - rails guides - ruby rails - rubyonrails - learn ruby on rails - team
ruby on rails tutorial tags - ruby , rail , ruby on rails , rail forum , ruby on rails tutorial , ruby tutorial , rails guides , rails tutorial , learn ruby
ActiveModel:
- In Rails environments, the AM support will be automatically loaded.
- In other frameworks, you need to include
Reform::Form::ActiveModel::Validations
either into a particular form class, or simply into Reform::Form and make it available for all subclasses.
require "reform/form/active_model/validations"
Reform::Form.class_eval do
feature Reform::Form::ActiveModel::Validations
end
Clicking "Copy Code" button will copy the code into the clipboard - memory. Please paste(Ctrl+V) it in your destination. The code will get pasted. Happy coding from Wikitechy - ruby on rails tutorial - rails guides - ruby rails - rubyonrails - learn ruby on rails - team
Uniqueness Validation
- Both ActiveRecord and Mongoid modules will support “native” uniqueness support where the validation is basically delegated to the “real” model class. This happens when you use validates_uniqueness_of and will respect options like :scope, etc.
class SongForm < Reform::Form
include Reform::Form::ActiveRecord
model :song
property :title
validates_uniqueness_of :title, scope: [:album_id, :artist_id]
end
Clicking "Copy Code" button will copy the code into the clipboard - memory. Please paste(Ctrl+V) it in your destination. The code will get pasted. Happy coding from Wikitechy - ruby on rails tutorial - rails guides - ruby rails - rubyonrails - learn ruby on rails - team
- Be warned, though, that those validators write to the model instance. Even though this usually is not persisted, this will mess up your application state, as in case of an invalid validation your model will have unexpected values
- This is not Reform’s fault but a design flaw in ActiveRecord’s validators.
ruby on rails tutorial tags - ruby , rail , ruby on rails , rail forum , ruby on rails tutorial , ruby tutorial , rails guides , rails tutorial , learn ruby
Unique Validation:
- You’re encouraged to use Reform’s non-writing unique: true validation, though.
require "reform/form/validation/unique_validator"
class SongForm < Reform::Form
property :title
validates :title, unique: true
end
Clicking "Copy Code" button will copy the code into the clipboard - memory. Please paste(Ctrl+V) it in your destination. The code will get pasted. Happy coding from Wikitechy - ruby on rails tutorial - rails guides - ruby rails - rubyonrails - learn ruby on rails - team
- This will only validate the uniqueness of title.
- For uniqueness validation of multiple fields, use the :scope option.
validates :user_id, unique: { scope: [:user_id, :song_id] }
Clicking "Copy Code" button will copy the code into the clipboard - memory. Please paste(Ctrl+V) it in your destination. The code will get pasted. Happy coding from Wikitechy - ruby on rails tutorial - rails guides - ruby rails - rubyonrails - learn ruby on rails - team
Confirm Validation
- Likewise, the confirm: true validation from Active Resource is considered dangerous and should not be used. It also writes to the model and probably changes application state.
- Instead, use your own virtual fields.
class SignInForm < Reform::Form
property :password, virtual: true
property :password_confirmation, virtual: true
validate :password_ok? do
errors.add(:password, "Password mismatch") if password != password_confirmation
end
end
Clicking "Copy Code" button will copy the code into the clipboard - memory. Please paste(Ctrl+V) it in your destination. The code will get pasted. Happy coding from Wikitechy - ruby on rails tutorial - rails guides - ruby rails - rubyonrails - learn ruby on rails - team
Validations for File Uploads
- In case you’re processing uploaded files with your form using Carrier Wave, Paperclip, Dragonfly or Paper dragon we recommend using the awesome file_ validators gem for file type and size validations.
class SongForm < Reform::Form
property :image
validates :image, file_size: {less_than: 2.megabytes},
file_content_type: {allow: ['image/jpeg', 'image/png', 'image/gif']}
Clicking "Copy Code" button will copy the code into the clipboard - memory. Please paste(Ctrl+V) it in your destination. The code will get pasted. Happy coding from Wikitechy - ruby on rails tutorial - rails guides - ruby rails - rubyonrails - learn ruby on rails - team
Classes
- Every step in Trailblazer needs to be separated into a different class such as
Comment::Operation::Update
andComment::Operation::
Delete.
- The better way to handle classifying you can use inheritance to make creating classes easy in Trailblazer. So, you have the same validations and forms for
create
andupdate,
you can just inherit acreate
operation from theupdate
operation. - No other code needs to be written, as it will inherit the
contract
and the code, so there is nothing you need to override. - It may sound crazy because you’ll need a class for every step, but if you use inheritance, you can also have reforms in your models.
- Working on something that automatically creates classes for you, so if you have really simple objects, you can use
runtime generator
for the classes so you won’t have to write 8 different operations for a model that just has an email.