Reputation: 667
I've a fairly detailed Rails form (<%= form_for(@pay_line) do |f| %>
) that takes multiple values input by the user.
I need to check a number of things on this form before I commit the values to the database (such as the net pay is not a negative etc.). I'd normally use jQuery but some of the calculations are very detailed and rely on join queries in the controller etc. so as far as I can see, it's not really an option.
I'm wondering how I should go about this. Is there a way to send the form to the database for processing before committing and if certain things fail, send the values back with a message saying certain things need to be adjusted by the user? Or is there another option I can use?
Hopefully I've explained it properly but if I haven't, let me know and I'll give more details.
Thanks for looking
Upvotes: 0
Views: 650
Reputation: 10726
You can achieve this using ActiveRecord::Validations.
It allows you to run some validations on a model before committing the changes to the database, and access to the errors when the model is invalid:
class Person < ActiveRecord::Base
validates :name, presence: true
end
>> p = Person.new
# => #<Person id: nil, name: nil>
>> p.errors.messages
# => {}
>> p.valid?
# => false
>> p.errors.messages
# => {name:["can't be blank"]}
Assuming you want to edit a Person
, save its changes or display its errors
when the changes are invalid, you could do something like this:
# config/routes.rb
YourApp.routes.draw do
resources :persons, only: [ :edit, :update ]
# This generates requests :
# GET '/persons/1/edit' (used to display the form)
# POST '/persons/1 (used to save the changes)
end
# app/controllers/persons_controller.rb
class PersonsController < ApplicationController
def edit
@person = Person.find(params[:id])
# used to display the edit form
end
def update
@person = Person.find(params[:id])
if @person.update_attributes(params[:person])
# the changes are valid, here we simply redirect
# to the home page
redirect_to(root_path)
else
# the changes are invalid, we display the form
# again
render :edit
end
end
The edit view will display both the person form and its possible errors :
<%# app/views/persons/edit.html.erb %>
<% if @person.errors.any? %>
<ul>
<% @person.errors.full_messages.each do |error_message| %>
<li><%= error_message %></li>
<% end %>
</ul>
<% end %>
<%= form_for(@person) do %>
<%# your custom form fields %>
<% end %>
Notice the example above generates page reload when submitting the form.
To prevent this, you might use Ajax requests to send the form in JS to the Rails server. In this case, the Rails server could render JSON instead of HTML.
Upvotes: 1
Reputation: 333
You can use a custom validator for more complex validation.
To validate net pay:
class MyValidator < ActiveModel::Validator
def validate(record)
unless record.net_pay > 0
record.errors[:name] << 'Net pay must be greater than 0!'
end
end
end
class Person
include ActiveModel::Validations
validates_with MyValidator
end
Upvotes: 1