Rails Form Submit
I started using Ruby on Rails around four years ago, but I usually just played with trivial examples, and never really dived into it. Now that I am developing something not-so-trivial, it’s good opportunity to really understand the concept, instead of walking around it all the time.
The problem I would like to discuss in this post is form submission. Using Rails resource generator, we could get complete CRUD for a model, and it works out of the box, but it’s a black box. This time, let’s create part of it manually to gain some insight.
rails new form_submit
cd form_submit
bundle
rails g controller home edit
We wouldn’t use rails model generator, so we just create a activemodel
compatible model.
module HomeHelper class UserModel include ActiveModel::Model attr_accessor :name, :age end end
In the edit
action, we would instantiate an object of that model, and pass it to the view.
include HomeHelper
def edit @user = UserModel.new( name: ‘albert’, age: 30 ) end
The view contains a form, and looks like the following. The as
part would show itself when we look at the submitted data.
%h1 Home#edit
= simple_form_for @user, as: :user_model, url: ‘’ do |f| = f.input :name = f.input :age, collection: 18…60
= f.submit 'Save'
Add one more method update
in home
controller to handle form submission, and adding the rule for that in the routing file.
def update redirect_to action: :edit #since we don’t know what to write here for now end
config/routes.rb
post ‘home/edit’, to: ‘home#update’
If we test this in the browser, and try to submit the form, we could see the submitted data in the console, something like:
Parameters: { … “user_model”=>{“name”=>“albert”, “age”=>“30”}, “commit”=>“Save”}
We could construct the model using the submitted data, and render it using the edit
view. Just for fun, we would increment the age
value. Since
the model is not backed up by a table in database, its type is unknown; hence the string to integer conversion.
def update @user = UserModel.new(params[:user_model]) @user.age = @user.age.to_i + 1 render :edit end
The conversion is not needed if this model is an actual active model. In fact, let’s see how much needs to be changed, if we replace the model with a real active model.
rails g model User name:string age:integer rake db:migrate
Actions in the controller need to be updated to use the new model. The conversion is not needed, for its type is specified when we create the model.
In addition, the key
in submitted data becomes :user
, which is corresponding to the model name. At last, we need to permit fields meant to be
updated explicitly because of Strong Parameters
def edit @user = User.new( name: ‘albert’, age: 30 ) end
def update @user = User.new(params.require(:user).permit(:name, :age)) @user.age = @user.age + 1 render :edit end
So is the view:
= simple_form_for @user, url: ‘’ do |f| = f.input :name = f.input :age, collection: 18…60
= f.submit 'Save'
The complete code is available here