My name is John Vicencio and I built Pinterested clone web app using Ruby on Rails.

Project Development Introduction

Pinterested in Rails (PIR) is a Pinterest clone app built using Ruby on Rails. The Rails project focuses on scaffolding and utilization of the Model View Controller (MVC) programing model. Gems are used like Devise, Masonry, Paperclip, Bootstrap and others for login/security, image animation, image uploads and responsive design.

App Walk-Through

PIR is a simple but functional social network app based on Pinterest. This is how the app works.

  1. Main page showing all the pins: Go to the home page at https://pinterestedinrails.mythoslife.com/ where you'll see all the pinned images by registered users.
  2. Top menu: The PIR logo "Pinterested" is shown on the top left side of the home page. On the top right hand side, a menu (navbar) is shown: Home, About, Login (Logout if you're logged in), Join and Contact. If you're logged in, you'll see other menu options like: Add (to add a pin with description and image for upload), Pins (to show all the pins that you can edit or destroy/delete if you posted them), and Edit Profile.
  3. About page: You can find out more about this app on the About page (documentation of this app, in this case)
  4. Contact page: If you have any questions, you can go to Contact page to enter your name, email and your message. Notice that name and email fields are validated and cannot be empty when sending a message (from the Contact form page).
  5. General notifcations and active menu: Notifcations are shown if something is wrong or if something is successfully entered correctly. Depending on what menu item you selected, that menu will be active. Click on the About page, that page will grey out that indicates that that menu is active or selected. The same if you were to click on the Contact page, which will be greyed out to indicate that the you are on Contact page.
  6. Logging in: Login using your email and password. The login form requires an authenticated and confirmable email and password from the database. A login will lock up with several attemps. You can now Pin, Edit or Delete Pins, Edit Profile, Cancel Account and Logout. When logging in, notice that it'll say "Welcome 'your name'" with a dropdown to "Add" a pin, show all "Pins", Edit Profile and Logout.
  7. Registration: Join Pintered if you're a new user. Enter your name, email and password.
  8. Forgot password? Passwords can be changed either when users are logged in (an edit can be done with confirmable password) or when users have fortoggen a password by clicking on the forgot password form (the database will confirm if the user exist and will then email a link to confirm for security purposes; email confirmation sent will expire).
  9. Editting profile: To change your Profile, first login and click on your name ddropdown menu, click on Edit Profile. Update your information. Once done, to apply the update, you'll need to enter your current password. You can change your password under Edit Profile as well but you'll still need to enter your current password. If you have forgotten your password, logout, click Join, and click on Forgot Password link at the bottom of that page.
  10. Cancelling an account: Existing users have the ability to cancel their accounts, which will be destroyed from the database records. To cancel your account, log in, go to Edit Profile, click on Cancel Account at the bottom of that page.
  11. Posting a Pin: Adding a Pin is simple. A Pin is a post of your favorite picture with a description. Log in, click on your name dropdown, click on Add (with a 'pin' icon), enter the description of the image, upload your image (must not exceed size limitation), and Submit to post your pin. Description and image are required and the image must not be other than an image file.
  12. Editing a posted pin: You can edit your Pins by logging in, look for the pin you posted that you want to change, click the Edit button. Make the changes like replacing the image or by changing the description you entered. Only the pins you posted can be edited not the pins of others. The app knows what pins you posted since you'll see the Edit and Delete buttons at the bottom of each pins and for other pins without these buttons are not your pins.
  13. Deleting a posted pin: Just like editing a pin, you can delete a pin as well. Log in, look for the pin to delete. Click on the Delete button. Only the Pins you posted can be deleted. The pins without the Delete button will not show since these were posted by other users.
  14. Searching a posted pin: Go to the main page, type a keyword of the description of the image that was posted, and search.

Web app components and technologies

  • Programming Language: Ruby, Javascript
  • User Experience: HTML5, HTML, CSS, CSS3, SASS
  • Framework/Library: Ruby on Rails, jQuery, Bootstrap
  • Programming Architecture: Model View Controller
  • Design: Responsive, clean and minimal with dynamic codes
  • Database: PostgreSQL on the production-side app and SQLite on the development-side
  • Ruby Gems used: Devise for adding and login a user, Bootstrap-sass for UI, ImageMagic and Paperclip for image upload, Amazon S3 for image storage, jQuery Masonry for collection of pins with animation and Will Paginate, its Bootstrap pagination, Mail Form, and Bootstrap Form
  • Version Control System: BitBucket through Git
  • Production Environment: Heroku as the production hosting
  • Development Environment: Mac for computer, Terminal, Bracket as IDE
  • Domain, Hosting, DNS: Heroku is pointed to a subdomain in GoDaddy

What does PIR Do?

PIR does the following features just like the actual Pinterest web app based on Create Read Update and Delete (CRUD) programming concept.

  1. Allows users to create pins that are associated to their user profile
  2. All users can see (read) all the pins made by all users who registered
  3. Allows users to register (create)
  4. Users can login and authenticated
  5. Allows registered users to view pertinent state when logged in as opposed to those who are not logged in
  6. Users can make changes (edit) on user profile information
  7. Users can cancel their own accounts
  8. Users can delete their own pins
  9. Users can search an image
  10. User Experience is intuitive, responsive with dynamic programming using MVC programming architecture of Ruby on Rails

How does end user's browser interacts with the PIR app and how are data handled?

PIR app uses the MVC architecture to handle web pages (views). A page request from a browser (such as typing a website) is routed through routes.rb (/config folder) first, looks for actions or methods inside the controller (/app/controllers/name_of_controller.rb) and returns a view. The user sees a web page (User Interface) on the browser. If the request requires a login, the controller will look at the model (using Devise gem to handle all the authentications and validations) to check if the user has already registered from the database; a new user will then be registered with authentication info stored in the database. The user will see a page (a view) that the registration is successful. Another use of the model is when a registered user has logged in, for example, and uploaded a pin where there are two things happen: the description is saved in the local database and the image is uploaded to a third-party database, in this case, through Amazon S3. The rest of the UI is done by Bootstrap, for the most part. For example, the responsive design and look-and-feel are handled by Bootstrap (CSS and any Javascript needed that works with any components). Additionally regarding the UI look-and-feel, Masonry jQuery handles the animation and positioning of the pinned images.

  • Homepage: https://pinterestedinrails.mythoslife.com/
  • Views (UI): home with all the pins (root, pins#index), about (home#about), partials redered on root (footer, header, jumbo), contact us (contacts#index), and login/sign up/authentication forms (rendered generally on header section)
  • Controllers: pins, home, contacts and application
  • Models: pin (with description text database, images uploaded to Amazon S3 on production end), user (with database using Devise gem), contact (using Mail Form, no database)

Web app development procedure:

Here's the general procedure I did to create PIR. A lot of my gems are installed from source 'https://rubygems.org' as seen in the Gemfile where you'll be able to read more about a particular gem under its documentation.

  • I first created the app using rails new pinterested from the Terminal. Ruby on Rails will generate a simple app framework. Running rails server the local host (localhost:3000) will show a generic Rails page. Also, in the production environment using Heroku, I've pointed that to a subdomain: https://pinterestedinrails.mythoslife.com (or if I had a domain, I could have pointed that to www.exampledomain.com.
  • I created a Home controller, rails generate controller home index about, which generated a home controller with index and about views. Later on, this home index view will the page where all the pins will be shown. This will show on URL as a page on localhost/home/index.
  • But I needed to change the route.rb to show on localhost/ as the root or home page. So I added root 'pins#index' rather than root 'home#index'in the route.rb file. For the About page route, I type in: get '/about', to: 'home#about' inside the routes.rb file. You can see the URL pattern and routing paths with this command on the terminal: rake routes.
  • I needed to create a version system using Git and BitBucket. Git allows to save versions of my app. Then I used BitBucket so that the codes have repository privately rather than using GitHub, which is public. Both are free.
  • I created a Heroku web host, which works great with Git version control system. The app codes are pushed to BitBucket and pushed to Heroku, which works very well with Git. After pushing a version of my app to Git, I can push this to Heroku by typing this on the terminal: git push heroku master, of course after typing these as well: git add --all, git commit -am 'some comment' and git push.
  • Before pushing anyting to Heroku (production environment), on the development environment will use SQLite and the production environment will use PostgreSQL. This can be done by some instruction on Gemfile file. Any changes to Gemfile will need to bundle install from the terminal.
  • To show the header and footer sections of a page, created two new partial views with a format naming convention '_partial.html.erb'. I can then type these line of code inside the applicaiton.html.erb views layouts: <%= render 'home/header' %> to render the navbar and <%= render 'home/footer' %> to render the footer section of each page. This is where the flash notifications will be shown if there are errors or message in relation to forms like Contact or login (so on) forms.
  • On the homepage where all the posted pins should show up, there's another partial view called _jumbo.html.erb which shows a Jumbotron component of Boostrap (added by adding gem 'bootstrap-sass', '~>' in Gemfile; changed stylesheets assets such as botsraply.css.scss which is a SASS file where you can add variables that will change the look-and-feel of the styling). This is also shown in application.html.erb: <%= render 'home/jumbo' %>. I can now style the User Interface using Boostrap.
  • To take care of the registraion, login, logout and their authenticaitons of the RIP app, I installed Devise by adding this to the Gemfile: gem 'devise', '~> 3.4.1'. On the terminal to generate related Devise views, this command is entered: rails generate devise:install. There are some instructions to manually set-up a few things for the Devise to work where /config/environments development.rb and production.rb needs to be pointed to localhost and the actual URL subdomain that Heroku is pointed to.
  • Creating a Devise user, rails generate devise user that will create a migration. Everything there's a migration (for database), I type in this on the teminal: rake db:migrate. This will create a table with email and password columns. Later on a 'name' column is created. For now, this created new routes. Checking out the new routes using the rake routes command on the terminal will list a lot more paths.
  • I can now add a few business logic on my views using the Devise gem such as: <%= current_user.name %> to show a certain link for current users and <% if user_signed_in? %> if a user is logged in. New routes like <%= link_to edit_user_registration_path %>, %= link_to destroy_user_session_path, method: :delete do %>, <%= link_to new_user_session_path do %> and so on will be shown under the _header.html.erb partial view that shows depending on whether a user is logged in or not. These new paths will be able to display pertinent views that are related to let say logging in, registration, logout and so on.
  • Any major changes to the app needs to be saved and pushed to Git and Heroku. Since there was a migration, there should also be a migration command to the Heroku: heroku run rake db:migrate.
  • The posting mechanism of the app will need a scaffolding of the following command on the terminal: rails generate scaffold pins description:string which just created a view, a controller, and a model with migration (another rake migration command will need to be typed on the terminal; will also need to run migration on Heroku). Scaffolding will affect the Boostrap. A manual delete of scaffold css is necessary. The pins view will have edit, create and destroy links that was created through scaffolding. A styling is necessary at this point.
  • Posting pins have a description section and an upload of an image. To handle the image, I used Paperclip. It requires an install in Gemfile, gem 'paperclip', '~> 4.2.1' (bundle install it) and a Image Magick library from the terminal rather than on Gemfile (since it's not a gem): sudo -apt-get install imagemagick. It's should be installed by confirming with identify command.
  • The validation that needed to be added in the Pins model per Paperclip documentation should say this: has_attached_file :image, validates_attachment_content_type :image, :content_type => /\Aimage/, validates_attachment_file_name :image, :matches => [/png\Z/, /jpe?g\Z/], and do_not_validate_attachment_file_type :image
  • I added a Pin image column using this command: rails generate paperclip pin image with a rake migration command after.
  • Pins view form will need to be changed to accept image <%= bootstrap_form_for @pin, html: { multipart: true } do |f| %>. This Bootstrap Form gem must also be bundle installed on Gemfile in this case for Bootstrap style forms: gem 'bootstrap_form'.
  • The pins controller has to have an image param for the form to work. Later on, I'll need to add a name to add on Devise.
  • To install images, I choose Amazon S3 because Heroku doesn't save images (only temporarily). In the Gemfile, it should show gem 'aws-sdk-v1'. The set-up needs an Amazon account, with bucket and some key to enter. Heroku would have be given the Amazon S3 authentication directly rather than typing it on the application itself for security measure.
  • Adding a name on the User database or table, rails generate migration AddNameToUser, will add a name field on the profile section.
  • The rest of the components of this app is the Masonry which animates the images when users resize the browser size. The gem needed is gem 'masonry-rails', '~> 0.2.4' wich requires gem 'jquery-turbolinks'. Will paginate gem 'will_paginate', '~> 3.0.7' and Boostrap style of it gem 'will_paginate-bootstrap', '~> 1.0.1' will handle the look-and-feel.
  • Create the Contact page is another gem install gem 'mail_form' with terminal command rails generate controller contact new create. This will create views but no model. A few validations options in the controller to work as well as email set-ups to send a live email message.
  • The last component is the Search section. Under the pin model, I added a method for a find query: where("lower(description) like ? OR lower(name) like ?", "%#{query.downcase}%", "%#{query.downcase}%") . The header partia view is where this search field box is shown as such <%= text_field_tag :search, params[:search], placeholder: "Search user or image", class: "form-control" %>. In the pins controller the result shows up @pins = Pin.joins(:user).search(params[:search]).order("created_at DESC").paginate(:page => params[:page], :per_page => 6) The last section of this statement is the paginate of 6 images per page.
  • Testing and debugging is a straigt forward entering of descriptions of images. There's a lot of user beta testers as well. I went manually logged in, signed-up, cancelled account, deleted posted pins, send myself a message through Contact page to make sure they work. But I delete a post or an account before going back to make any changes since and redo them. I pushed the app to Heroku and tested the production as well.