Rails Photo App: Building a Public Feed
Published: 2021-05-07 10:07:28

**Photo Dump**: A collection of seemingly unrelated pictures. 
Building a photo dump app just feels incomplete without a public feed. After all, public feeds can be sources of inspiration, procrastination, and just about everything else in between. So why not - it'd be a cute, lil feature. 

#Build the App#
One of the first things I noticed while building my app: *Rails is magical*, and part of that magic is its built-in generators. To start a new project with essential files and structure, just run `rails new app_name`. 

##Helpful Gems##
The Gemfile already comes with several useful gems, but one that really simplifies the process is **Devise**, a customizable authentication solution. It takes care of common helper methods, like `current_user`. To use Devise, specify it in the Gemfile: `gem "devise", github: "heartcombo/devise"` and run `bundle install`.

##Setting Up the MVC Structure w/Devise##
Here comes more Rails magic. 

###Create the Database###
Run `rails generate devise:install`, which also triggers helpful instructions that will appear in the terminal.

Using Rails' built-in generator, I created a photos table with `rails generate migration create_table_name`. It already fills in the class name and has it inherit from ActiveRecord::Migration. All that's left is to add attributes -  a necessary one being `:public`.

![](https://i.ibb.co/XkCcjGN/Screen-Shot-2021-05-07-at-3-21-17-AM.png)

Because I wanted to clearly show whether a user selected their photo as private/public in the view, I made it a string. 

To create a model with a table, run `rails generate devise MODEL` (I used User), and customize/configure it as necessary.

Finally, run the migrations with `rails db:migrate`.

###Create the Models###
Running `rails generate devise USER` already took care of setting up the User model for me, and included are default Devise modules. In addition, I created a photo model and also ensured that it has both a url and private/public specification, the latter a necessary part in creating a public feed, with validations. 

###Create the Views###
Views are what the user sees and interacts with. For the public feed, I created an *all.html.erb* in the application folder under views. However, it could also go in home.html.erb as well.

###Create the Controllers###
For the public feed, I needed three controllers:
* users controller
* photos controller
* application controller. 

#Build the Public Feed#
![](https://i.ibb.co/zbWWk68/Screen-Shot-2021-05-07-at-4-39-02-AM.png)

##Routes##
In the config folder is *routes.rb*. Rails' router recognizes URLs, sends them to a controller's action, and with even more magic, generates paths. *Hardcoding strings in views? What's that.* 

To have access to all seven CRUD routes in one, I used `resources` for both users and photos. Furthermore, I nested photos in its parent resource users. 

Because I always want **/all** to show the public feed, I set it as a singular resource with `get "all", to: "application#all", as: "all"`. 
![](https://i.ibb.co/0YwY9jz/Screen-Shot-2021-05-07-at-4-26-18-AM.png)

##Finishing Up the Controllers##
Going back to the application controller, which is essentially  just for the public feed, I wrote a simple, short method **all**, using an ActiveRecord scope method `.where`.
![](https://i.ibb.co/YXq96Kw/Screen-Shot-2021-05-07-at-4-51-17-AM.png)
`.where` selects from all photos, in which the `:public` attribute contains the string "public."

##Rendering the Views##
Almost done. Now to actually show the public feed. 

###Selecting Private/Public###
But first, photos need to be created and saved as well as marked either "private/public." To do that, I created a form in *new.html.erb* under photos, so a user can fill out a form that when submitted, triggers **post** and creates and saves a photo with the necessary attribute. 
![](https://i.ibb.co/PgXB74V/Screen-Shot-2021-05-07-at-8-13-54-PM.png)

With a drop-down list, I allow the user to select from the choices of either "private" or "public," which are converted to strings. In the *photo.rb*, I set a constant **CHOICES** equal to an array of, well, choices: `CHOICES = ["private", "public"]`.  

**Finally**, with an each do block, I iterate through each photo and display them with an image tag and URL.

![](https://i.ibb.co/p2WSwPY/Screen-Shot-2021-05-07-at-8-35-26-PM.png)

And there it is - a public feed to spice up what would otherwise be a standard app.