DEV Community

Elias Robert Hakim
Elias Robert Hakim

Posted on

Partial to Rails

During the last few weeks, I have been pouring my time and energy into making the jump from Ruby into Rails. My immediate reaction to running the command

rails new

was "WOW!"

That amazement has not worn off...

Building out my first Rails app became an exercise in frustration, as the abstraction in the Rails platform soon concealing functions that were explicit in Sinatra in a shroud of ambiguity.

"I thought Rails was supposed to help me, not hurt me." I said to myself as I was manually building out my views pages for each model. And I was absolutely right- Rails IS supposed to help the developer with it's built in functionality- it doesn't hurt you, you just have to peel back the mysticism and become familiar with the ways it helps you!

In my case, I want to talk about rendering templates. Let's start talking about this method in the context of a Sinatra app.

get '/bikes/new' do
@bike = Bike.new
erb :'bikes/new'
end

In this method I'm having to specify that I'm sending a get request to the /bikes/new path and in the context of that path I am setting up an instance variable with a freshly instantiated instance of my Bike class. I'm also specifying exactly which .erb file to render.

In this case, the new.erb file contains a form with which we will populate the attribues of our bike object with information.

<form action="/bikes" method="POST">
<h2> Enter information below: </h2>
<input type="text" name="bikes[name]" placeholder="Name"><br>
<input type="text" name="bikes[description]" placeholder="Description"><br><br>
<input type="text" name="bikes[serial_number]" placeholder="Serial Number"><br><br>
<input type="submit" value="Create Bike">
</form>

Let's take a look at a similar method for a similar application, but instead built out in the rails framework.

def new
@bike = Bike.new
end

Okay, what is happening here? We are setting our instance variable to be a new instance of our bike class, but it doesn't look like there is anything else going on... there are no explicit instructions like the Sinatra example.

That is because Rails is intelligent, and built around conventions. Because of these conventions, Rails knows that you are sending a get request, and that it needs to render the new.html.erb view for our bike class. Rails even knows that file will exist in the app/views/bikes path. Lets take a look at what is in this file.

<h1> Enter Your Bike's Information Here: </h1>
<%= form_with(model: @bike, url: userbikes_path, method: "post")do |b| %>
<p> Brand:</p>
<%= b.collection_select(:bike_id, Bike.all, :id, :brand) %> <br><br>
<%= render 'form' %>
<% end %>

Okay, this is getting crazy- right? Where is our form?! Certainly Rails is smart, but how does it know what we want our form to contain? Well, it doesn't! But it has an amazing feature that will help reduce code smell.

<%= render 'form' %>

This line is telling rails to look for a file in the same directory called _form.html.erb. What is the purpose of this you ask?

Well, take our object for example. Our bike object has attributes that store data- a name, a model, serial number. When we are creating a form for this object we want to have a field for each submit-able attribute so we can attach the data to the correct attribute. We also may want to edit all of these attributes in the future for a variety of reasons. So we should have another form that communicates with our edit method, and this form should be almost identical to the new form, shouldn't it? Yes!

With the functionality of rails, we are able to build the bones for this form in our _form.html.erb file. Let's take a look at what this may look like:

<%= form_with(model: [@bike]) do |b| %>
<%= b.label :name %><br>
<%= b.text_field :name %><br>
<%= b.label :serial_number %><br>
<%= b.text_field :serial_number %><br>
<%= b.label :notes %><br>
<%= b.text_field :notes %><br>
<%= b.submit "Save Bike" %>
<% end %>

So in my bikes/new.html.erb, when I call <%= render 'form' %> I am telling Rails to look for that _form.html.erb and render that code where I am calling the render funtion.

Then, in my bikes/edit.html.erb file, I can call the body of the same form, but set the path the post request to call the edit method instead of sending that information to the update method like it does in the new page.

How cool is that? That is Rails cool!

Top comments (0)