Random musings on programming, mostly.
Sinatra
When I was first tasked with building a Sinatra app for a final project at Flatiron School I had trouble deciding what it was I wanted to build. The requirements were fairly open ended and included the following:
It took a few false starts to find what it was I wanted to build, I eventually settled on a craigslist type ad posting app. It seemed to fit the requirements and would be an interesting study on how a site like craigslist might work.
So how to start, for me planning on paper when starting a new project is critical. It allows me to sketch out various parts of the program including models, views, controllers, and db schema just to name a few. A rough sketch in hand it was time to get to work.
I first sketched out my models, and their various attributes and methods and created the db migrations needed to build the app. (Note: the Section model was added later as an improvement to the completed app.
class Ad < ActiveRecord::Base belongs_to :user belongs_to :section end
class User < ActiveRecord::Base has_many :ads has_many :sections, through: :ads has_secure_password end
class Section < ActiveRecord::Base has_many :ads has_many :users, through: :ads def slug self.name end def self.find_by_slug(slug) User.find_by(:name => slug) end end
ActiveRecord::Schema.define(version: 20170203075732) do create_table "ads", force: :cascade do |t| t.string "title" t.string "content" t.integer "user_id" t.integer "section_id" end create_table "sections", force: :cascade do |t| t.string "name" end create_table "users", force: :cascade do |t| t.string "username" t.string "email" t.string "password_digest" end end
So you can see how our models will interact with each other. A user may have many ads. Each ad belongs to a user and also has a section.
Next step is to begin building routes. This step was also planned out on paper first. I determined routes based on how a potential user might use the app. For example a user would need the ability to sign up, log in, create an ad, manage his/her existing ads… Same applies to both ads and sections.
An example route to create a new ad found in ads_controller.rb
get '/ads/new' do if logged_in? erb :'/ads/new' else redirect to '/login' end end
You can probably gather that when the app gets a request at /ads/new it verifies that a user is logged in and then displays the appropriate page, in this case new.erb which has a form to create a new ad. The same concept applies to patch and delete commands. See the route below used to delete an ad.
delete '/ads/:id/delete' do @ad = Ad.find_by_id(params[:id]) @ad.destroy redirect to '/ads' end
This route takes the :id paramater passed via the request to /ads/:id/delete and finds the ad with that id in our database. It then destroys that instance of the ad in our database and takes the user back to the list of ads via redirect.
Last, but most definitely not least, I created my views. Views are simply what the user sees in the browser when navigating the app. In actuality the creating of views went hand in hand with creating the routes. I generally build a route, using the example above of the route to create a new add, and at the same time build the associated .erb file that that route will display or receive a request from. Below is an example view for displaying the above mentioned new ad creation view.
<h1>Create New Ad</h1> <form method="POST" action="/ads"> <p><label>Title: </label><br> <input type="text" name="title" id="title"></p> <p><label>Content: </label><br> <textarea type="text" name="content" rows="10" cols="30" id="content"></textarea></p> <label>Section:</label><br> <% Section.all.each do |section| %> <input type="radio" name = "section" value="<%= section.id %>"> <%= section.name %><br> <% end %> <br><input type="submit" name="Create" value="Create" id="submit"> </form>
This is mostly just html used to display an input form in which the user can create a new ad and submit it. One important thing to notice is the actual erb (Embedded Ruby) code. For example we are using <%= %> and <% %> to inject ruby code into our html.
Hopefully this post will give you an idea on how to get started building your next Sinatra project in Ruby. I had fun building the app and encourage you to experiment with it here https://github.com/SYoung82/fakelist