Picky

Murat Ogulcan Sahin
5 min readMar 5, 2021

If you are from NYC, at some point you put your old furniture, dusty books, scratchy vinyls on the curbside, thinking maybe someone would like to have them or you were the one who picked them. These items usually goes to lucky ones who were happened to be passing by the right place at the right time. As I always complain about myself being unlucky, I built Picky to not leave this pick up free things from neighborhood game up to my luck.Picky web app allows its users to view items/pickies that other users put on the curbside and access those items’ locations and to post their own picky.

Active Record and Sinatra libraries are used in order to provide functional database to the app and make HTML requests. These two libraries helped to reduce lines for our code via their built-in methods. Also Bcrypt gem is required to secure user password in the database safely. In this article, I will touch on these three topics.

Active Record
Active Record is a Object Relational Mapping (ORM) system that allows us to build and manipulate our database and connects our objects to the database. It works its magic and database table columns become attributes of our model objects. Its built-in methods make SQL queries available to us with only a couple lines of code. Picky is an object oriented app and has MVC design pattern. The relationship between model objects are made through the data which is persisted to the database that is set via Active Record. The database relationships are implemented by Active Record Associations methods.

In Picky, our models are User, Product and Location objects. Their relationships are like:

  • User has many Products and has many Locations through Products.
  • Product belongs to a User and a Location.
  • Location has many Products and has many Users through Products.
Implementation of active record associations

It is important to add that when creating database tables for your models, you should follow the conventions of Active Record in order to construct relationships. For this app, #has_many, #belongs_to and #has_many :through methods are used. These methods help to form relationships between objects by persisting the data to their tables and using each others foreign keys as connection point. Since our User and Location objects are connected through Product object, products database table has to have user_id and location_id columns.

using Active Record’s methods in #change method to manipulate or to build the database

The data persisted in these columns refers to the id of product’s user in the users table and the product’s location in locations table. For example :

has_many, belongs_to, has_many :through relationships diagram

The photo above tells us Seller and Buyer models has a has_many relationship through Item model. If seller3 wants to find out the zip code of the buyer for their item4 to mail the product, the code most likely is going to look something like this:

seller3.items.find_by(item_name: "item4").buyer.zip_code
=> 11221

Every method in this line of code (#items, #find_by, #buyer, #zip_code) is provided us by Active Record methods. In this example our items table’s foreign key columns acts as bridge between the tables.

Sinatra
Sinatra is a DSL (Domain Specific Language) library that handles HTTP requests and keep our web server up and running. Its methods can accept a block of Ruby code because it is built on Rack which is written in Ruby language as Sinatra. In those blocks, we shape our web app in a way of the user requested and this makes it a dynamic web app.

GET/POST/PATCH/DELETE are the HTTP request methods to indicate the desired CRUD action to be performed for a given resource. Also user should be navigated after a request. In Picky, RESTful Routes are applied for this navigation event.

Picky RESTful Routes

The important thing to know here is HTML forms only support GET and POST requests. If a user wants to edit or delete data, these can be performed with PATCH or DELETE requests. So we need a middle man between user and server to make this happen. This middleman’s name is Rack::MethodOverride.

Rack::MethodOverride is a module of Rack that is used to make update and delete CRUD (create, read, update, delete) actions happen. It can be implemented by adding use Rack::MethodOverride to our rackup file along our other custom middlewares.

config.ru file of Picky

Shortly our Rack::MethodOverride interrupts a PATCH or DELETE request before ApplicationController runs and executes Sinatra’s patch or delete method’s block that we wrote in Ruby. In these blocks we interfere with our database so in order to make Sinatra and Active Record work together, we should make sure that we have sinatra, activerecordand sinatra-activerecord gems installed and required.

Bcrypt
When a user signs up, they enter an username(and/or email) and a password to log in to their account. Our code should authenticate the user by matching username and password they put in with the data we stored in our database. However storing a password is a big risk for safety of users and our app. Any password that is stored as it is or even hashed can be accessible either by hackers or developers of the app and this is a dangerous risk to integrate to our data storing structure. In this case, we need something more advance that pushes the computer power limits to figure out encryption algorithm.

Bcrypt gem combines hashing and salting and bcrypted version of user’s password is stored in the database. Basically hashing is using an algorithm to modify the password and salting is adding random characters to the password. After a password goes under hashing and salting, it comes out as a very long string of characters that is safe enough to store in our database.

Bcrypt Implementation

  1. Add gem 'bcrypt' to gemfile
  2. Run bundle install in your project directory command line
  3. Call #has_secure_password method in the model class that you want to authenticate
  4. Add password_digest column instead of your password column in your model’s database table
  5. In your controller’s post '/login' method block, call #authenticate method on model’s instance. This method should accept user’s input of password text field.
users_controller post method block authentication

--

--