I have been trying to become a master at making a rails app from scratch, so I wanted to write about my journey in doing it. I will be making a rails app to handle this very blog you are reading right now. If all goes well, it will be deployed on Heroku and I will be able to update it as the only user, but potentially others could use the same code or create a community blog.
So, as an initial measure, you should make sure that your computer has Rails, Ruby, and other basic development frameworks installed. Hopefully you haven’t made it to my blog before doing this, but if you have, you should go to the download pages of these things and get those on your machine.
You should decide before starting a project which Ruby version you want to use. Maybe you know that some things you want to do are easier in earlier or later versions. You can use the rvm gem to set the version you are going to use. Then type ‘rvm use (the version)’ into the command line. For instance, for my blog project I am typing:
$ rvm use 2.5.3
Now let’s make a new project!
Note: if you want to deploy later to Heroku, read this article over and follow the instructions. (https://medium.com/@kasiarosenb/deploying-your-rails-app-on-heroku-a2096dc40aac) You’ll need to use Postgres as the database, not sqlite3 which comes with rails automatically. I am going to give the most basic instructions on making an app here without worrying about that.
In the terminal, type ‘rails new (app name)’ like so:
$ rails new emilyblog
You’ll need to cd into your new project directory, create a repo on GitHub, initialize git, commit, and push to the new repo. I know you can do this!
You’ll need to run bundler:
$bundle install
And open the project in a text editor! I like to use atom.
Now’s the fun part. You get to decide what you want to build and what structure it will have. I personally like to start with the user experience, and imagine what the user sees when first encountering this app. For this project, the user could be anyone, but I’ll be using it for my own blogging purposes. So, I want to make sure no one else can post on my blog. So, I’ll need authentication. I want to use the devise gem for that, and I’ll need a login form, which comes with devise.
I’ll then need some kind of dashboard for the user to see how to post a new blog post and to view the posts already made. The reader of this blog should be able to see an index of all posts and browse through them. So, I’ll need a user model and a posts model.
I have to think hard before starting: do I want to add complexity by having more models? Maybe I want to categorize my posts too. Posts will be able to have many categories, and categories have many posts. Oh, boy! I need a join table called post categories to handle this many-to-many relationship! I won’t go into creating this kind of thing here, but how to do that is explained nicely in this article on Stack Overflow.
I’ll just make a model for posts and for users, keep it simple for this project. But the important thing is that you PLAN IT OUT before going further.
I want to use the devise gem for authentication, so I followed these instructions to install the gem and use it, and it also will create a user model and migration for users. Then, I want to create the post migration, controller, and views, so I enter this command in the terminal:
$ rails g scaffold Post title:string created:string content:string
Don’t worry if you forget to add a column for one of these tables. You can easily add those later. The hard thing to add later is the overall relationships between the models. That’s why planning ahead is crucial.
Now we’re ready to migrate! But since we’re using Postgres as our database, we need to create the database first. Run:
$ rails db:create
Then migrate! Run:
$ rake db:migrate
We now need to make sure the models are related to each other properly. Posts belong to users, and users have many posts. So, in the user.rb file, make sure it looks like this:
class User < ApplicationRecord
has_many :posts
devise :database_authenticatable, :registerable,
:recoverable, :rememberable, :validatable
end
And the post.rb file looks like this:
class Post < ApplicationRecord
belongs_to :user
end
Let’s go into the console and see if we did what we came to do. Run:
$ rails console
And let’s see what’s working.
$ post = Post.new(title: "test")
Tells me that there’s a new post now!
Great! Can we give it a user? Let’s create one:
$ user = User.new(email: "emily@emily.com", password: "emily")
And I needed to have included a user_id in the Post table if I want posts to be associated with users, so I need to create a new migration now:
$ rails g migration add_userid_to_posts user_id:integer
And rake db:migrate again! Go into the rails console again and create the test user and test post again, and then try:
$ post.user_id = 1
That should associate the post with the user! Great, the database looks good to go.
So, let’s start up the rails server and see what we have! We will need a root path in our routes.rb file (found in the config directory), so when we fire up the server it knows where to go first. Add this to that file:
$ root “posts#index”
And run:
$ rails s
If you followed all the instructions in the Rails Girls post about devise above, you should see a login form.
Congratulations! I think that is actually the hardest part of making an app for the first time. The set up was so hard for me the first time I did it!
Now, let’s make sure posts are showing up on the page and there’s a way to submit a new post. Let’s go to the controller, in the app folder find the posts_controller.rb file. Our viewer will always land on the index page first since we set that as the root path, so let’s make sure that the root action method is set up. It should look like this:
def index
@posts = Post.all
end
It’s already set up! This means that when the index view file has @posts in it, it will reference all the posts that are in the database. We don’t have any yet, so let’s make one. We will need to go to the new.html.erb file in the views/posts folder, and just have a look before you go at the new action in the controller:
def new
@post = Post.new
end
This means that the view will render and instantiate an empty object, the post. Let’s go see. Go to http://localhost:3000/posts/new and also look at the new.html.erb file. Wow! This is already set up for us via a partial layout. If you look at the file _form.html.erb, you’ll see the form. I am going to tweak it so that the content comes in on a test area - that will make it easier to see my post as I type it.
<%= form.label :content %>
<%= form.text_area :content %>
Refresh, and make a post! When you git submit there will be an error saying the user doesn’t exist. That’s because we didn’t create a way for the post to be associated with a user. The create action in the controller should look like this:
def create
@post = Post.new(post_params)
@post.user_id = current_user.id
respond_to do |format|
if @post.save
format.html { redirect_to @post, notice: 'Post was successfully created.' }
format.json { render :show, status: :created, location: @post }
else
format.html { render :new }
format.json { render json: @post.errors, status: :unprocessable_entity }
end
end
end
Now, try submitting your post again! It works! You are amazing. You have a blog now!
A couple of weeks ago, I made a Rails project using the Marvel Developer API, which is a very well-maintained way to access tons of information about Marvel comic book and movie characters. My project used Faraday, a gem for calling APIs in Rails, and it required an API public and private key to access the database.
I was really stuck at one point on the way the API wanted me to send the parameters. They explain in their documentation that a hash of the timestamp, public key, and private key needs to be passed as parameters when calling the API, but I struggled to find out how to generate such a hash. (Note: the documentation will also say the hash is only needed for server-side applications, but I found this not to be true.)
The documentation mentions an example of a hash generator, ‘md5(ts+privateKey+publicKey)’, so I searched 'MD5 for Rails', and I found this resource describing how to use it. This MD5 class comes with the standard rails library, and I used hexidigest, which worked fine.
To use it, enter the string you want to create as an argument, for instance with the Marvel API you’ll need to pass a specific string like so (after you've set the necessary strings as variables):
hash = Digest::MD5.hexdigest( "#{timestamp}#{private_key}#{public_key}" )
And you’ve got a hash encrypted in a way that you can use for the Marvel API or other authentication situations!
I recently ‘finished’ a Rails project named Register Your Kid, although I doubt it will ever be finished. I wanted to make it as an app for a local arts center in my neighborhood who has trouble because they only conduct registration on paper as of now. I wanted to make it more accessible and digital.
The hardest part of creating this project was the nested forms. I want to walk you through a bit of how I managed to create these. The key seemed to be in the url path that the form_for directed the params to, since the data had to go to the kids controller in this form you see in views/parents/show.html.erb:
<% if exists?(k) %>
<%=form_for k, url: parent_kid_path(@parent, k), method: :patch do |f|%>
<%= f.collection_select :course_id, Course.all, :id, :title%>
<%= f.submit "Submit" %>
<%end%>
<%end%>
The course that the kid is being registered for here needed to be associated with the kid object, which I reference with “k”. The kid is already associated with the parent whose show page this is appears on, because of the nested route parent_kid_path. I just needed to make sure that the course was associated with that particular kid. In the Kids controller, I allowed the POST request from this form to move the data as params to the update method:
def update
@kid = Kid.find(params[:id])
@kid.update(course_id: params[:kid][:course_id])
redirect_to parent_path(session[:id])
end
The kid is located in the database and then updated with the new course information when it’s given a course id.
This project was so fun and I learned a ton! I hope to add front end features soon using JavaScript.
Code is going on behind the scenes for me constantly. I just did a spin class during which I was planning a project in my head.
A non-profits arts center in my community, Adams Morgan, runs such amazing programs that my daughter and I attend. I ask them if I could make an application for them that would end up being my rails project. They need a way for parents to apply for classes online. I like this idea to make things easier and to reduce paper, so it was perfect. I mapped it out in my brain while on the bike: there’d be three models. One for students, one for classes, and one for teachers. The teachers have has_many relationships to classes and have has_many relationships to students through classes, students have has_many relationships to classes and have has_many relationships to teachers through classes, and classes belong_to students and teachers. Classes and teachers and students all have many-to-many relationships. It’s just the beginning but I have something good going here.
I had to think about the forms and nested resources I’ve been learning this week - how to make a sign-up form appear in a RESTful route that helps the form assume certain things like who the teacher is. I could have the form direct people to teachers/:id/classes/:id/new to create answers to POST in a form. This is exciting.
I felt like I was just chugging along slowly lab by lab until someone ave me a chance to make a real-world practical tool, and I am so inspired now that I am going to make this awesome thing happen!
I created a sinatra project! It's still unbelievable to me how much I've learned. I decided to bring in my past experience in philosophy to make a useful application that allows users to log in and create/share thought experiments, organizing them into branches of philosophy. I had so much fun doing it. Click here to see a video demo! Also, check out the code here.
I found that the hardest part was mastering the user login authentication and controlling the contributions of each user as their own, so that no one but the user can modify or delete a post. So, I want to give some helpful tips here for how to get started with user authentication.
For starters, you'll need to make helper methods that will determine whether a user is logged in and the session id of the current user. You'll need these methods in order to write the code in your controllers that route the user to the proper pages, for instance if they try to make a post but you want them to instead log in first.
Here are the helper methods I used, and I credit their existence to my partner, Bekah, from the Fwitter group project I'd done previously. I found that the code worked great and I encourage you to also use it:
helpers do
def logged_in?
!!session[:user_id]
end
def current_user
User.find(session[:user_id])
end
end
I put these two methods in my application controller.
Later, when I was writing the patch request in the experiments controller, for example, I would use the #current_user method to decide whether the user could actually edit that contribution (if they were logged in as the user who created it) or whether it would redirect them back to the index page.
patch "/experiments/:id" do
@story = Experiment.find_by(id: params[:id])
if current_user.id == @story.user_id
@story.title = params[:title]
@story.story = params[:story]
@story.branch_id = params[:branch_id]
@story.save
else
flash[:message] = "That's not your story to edit"
redirect :"/experiments"
end
flash[:message] = "Updated"
redirect "/experiments/#{@story.id}"
end
As you can see, I made a conditional statement that stopped the program from allowing the user to make the edit unless the post's id was the same as the current user's (session) id. I like to think of it as the gatekeeper to which actions are possible to the user, behind the scenes. If they don't meet those requirements, it routes them back to the index page that shows all the experiments.
I used the #logged_in helper method, for instance, when I was showing the user a page to welcome them after they've logged in. Obviously I didn't want the user to see that unless they're logged in, and they shouldn't make it that far unless the log in was successful.
# welcome page after logging in
get "/users" do
if logged_in?
@all_users = User.all
@user = current_user
erb :"/users/index.html"
else
redirect "/start"
end
end
The consitional statement here first determines if the user logged in, and then it assignes the instance varibale @user the value of the current user. that's how in the view page I can welcome that exact user by name. I do this in the views/users/index.html.erb view.
Welcome, <%=@user.username.capitalize%>, to the wonderful world of Philosophy Thought Experiments to help you live your life!
I hope this helps someone out there hoping to authenticate their users in Sinatra for the first time.
I have been programming with other learners who are located in other cities for about a month now and it’s been so fun. Nothing feels as great as bringing together your experiences and widening your horizons through talk about code. You think you’re all alone struggling and triumphing but then you realize there’s a whole world out there of independent coders who are going through the same.
I've been making a little side project with Billy Pittman, who is a tad behind me in the Learn.co Flatiron School curriculum, and I created a Twitter clone as part of the Flatiron School Online Bootcamp with someone named Bekah a couple weeks ago. She has kids too, and an unpredictable schedule as well. We loved working together because we totally understood each other! It took us just under a week to complete the lab and meet the requirements collectively. We started out talking for an hour over video communication and then dove into our parts. We thought we’d be able to divide up the project and work simultaneously on different parts, coming together to merge them later, but quickly found that our parts depended on each other, so we decided to do it “pass” style (we passed it back and forth and never working on it at the same time). I wanted to document some of that for anyone out there who may be struggling with the same things we faced when starting out, especially with regards to git and GitHub collaboration.
First of all, if you’re working remotely with a small team like that on a project and doing it “pass” style, I recommend messaging the person before starting to work on your part of it and after being done. The other person would also always check the messages before starting and finishing. This eliminates any risk of incompatible versions that will ultimately take up more time than it’s worth to sort through.
I then recommend always always always remembering to work on a separate branch of your own and leaving the master alone until you know what you’ve worked on is working and ready to push. This is hard to remember as a beginner, but you have to get in the habit. This is how you make a new branch:
git checkout -b [name of your new branch]
So, when you want to switch back to the master branch and merge, first add changes:
git add .
Then commit:
git commit “[say what changes you’re making]”
Then, I always push:
git push
And finally, you’re ready to switch back to the master and push the changes up to the main project you’re both working on:
git checkout master
And you’ll need to merge first:
git merge [name of your new branch you’d been working on]
And, crossing fingers there were no conflicts to be resolved between the changes and the master code, you push again!
To then get the changes later that your partner pushed, you will want to be on the master branch and pull:
git pull [the GitHub repo name you copy to the clipboard]
And before working, again always switch to your other branch (I find myself making a whole new one every time just to be sure and to avoid confusion for myself).
I hope this helps someone!
In 2005, I wrote a dissertation for my honours degree in philosophy at Otago about artificial intelligence (a sexy notion at the time, when AI wasn’t something humanity had seen in real life yet). In it, I argued that the criteria for personhood included the ability to adapt to an environment to the point that tools could be created/used to solve a novel problem. This was what I defined as intelligence, and the criteria for a computer having the possibility of becoming a ‘person’. No simple thesis, as it turned out.
I wouldn’t have believed anyone if they’d ever told me that I would be programming computers thirteen years later. What would I conclude now that I’ve been learning programming? I now have the foundations of knowledge on how computers really work. And what I’ve learned is: computers are stupid. (Also, I’ve heard it said numerous times at beginner coding workshops.) What does ‘stupid’ mean? I can tell you. It means they’re inanimate objects with human operators. They need ‘persons’ to give them any semblance of free agency and intelligence, and any feeling you may have that they are a ‘person’ is an elaborate illusion. As the Turing test proves, your feeling that something is an intelligent person carries the story very far. If a computer passes the Turing test, that just means that a human operator passed the Turing test.So, computers are stupid. So far.
Could they be persons someday? Could they meet my criteria for intelligence? I think that was my ultimate question then and still is the question we’re all wondering now. Our brains are just a neural network - this could potentially be reproduced in an artificial creation, right?
I’m still holding onto hope.
It’s time to reflect on my learning journey.
Almost exactly a year ago, after having taken some beginner codecademy and other courses in various coding languages, I began an 8-week evening course where I joined a few other classmate and an awesome teacher to learn front end development. I knew I was completely in love from the first moment and I cherished each moment of this amazing experience into learning web development. I created this website at the end. After that, someone actually paid me to make a custom Wordpress site for them. Then, I landed a job at Flatiron School and my life was forever changed. I was given the opportunity to complete the Online Software Engineering course, and here I am pretty much 50% of the way through it. I have worked on it in any moment of the day I can - I’m a mom working full time, but coding is my obsession and I push through, even when my two year old daughter is pulling my hair as I push something to GitHub. As she tests my calm and my ability to give her ample attention, I am somehow still able to read rspec tests to debug. I strive to keep valuing my abilities as a parent while still making time to learn about key/value pairs. I wanted to list the three most difficult things in this learning journey in this post, but I have been sitting here for five minutes trying to come up with them. Looking back, everything is so clear, although so many struggles faced me throughout the time learning it all. This clarity is incredible proof of the power of the human mind - because just a few months ago I didn’t understand object orientation, join tables, or two to build a method. I must have learned a lot!I finally came to the end of the Ruby section of my learning on Learn.co and I was overwhelmed when reading the description of the final project for it, thinking that I didn’t understand enough to truly set up and create an executable product. For anyone out there reading this facing similar imposter syndrome: you will be able to do this!
I spent a day reading all the material about it and then dove right in to watching the walkthrough video by Avi. That cleared so much of it up, and I watched it again, pausing probably every minute, to set up my project structure just the way he did. I actually ran into a few roadblocks along the way there - including not being able to run my console using ./bin/console. But through some google searches I found that all I had to do was update my Ruby version. I found these instructions.
For my project, I didn’t want to create a CLI program that displays movie times or something. I wanted to make a game. I used to be a teacher in South Korea, and I loved to design silly games for my students to practice English while being challenged with something out of the ordinary. I also feel very inspired by both Adam Neumann, CEO of WeWork, and by RuPaul. So, I chose to scrape a quotes website (BrainyQuotes) and then have a random quote returned that the user has to guess which of these famous people said it. They’re both such interesting and surprising people, you actually might not be able to guess right away each time! I certainly had fun playing it myself, since I don’t know all the quotes from each of them. I would imagine someone could go to the BrainyQuotes website and find the same landing page for another famous person and change which page it scrapes, tailoring it for their own uses (again, picturing it to be used in a classroom.)
One of the concepts I struggled the most with was when to use an instance vs. a class method. I understand that the class methods are used to do something to all objects in a class, but the instance methods are used to do things to instances of the class. Some methods aren't applicable to the whole class, only to instances of it. For instance, a method that changes the elements in an array in order to be used later to change something about all the objects in the class doesn't need to be a class method. I am still wrapping my head around it, but I am confident that my understanding will grow the longer I solve these kinds of problems in Object Orientation.
I just finished the lab called "OO Banking" on the Learn platform and I had to wrap my head around booleans as the only thing that can be named in conditions of an if statement in order to solve this lab. Consider this code:
class Transfer
attr_accessor :status, :bankaccount
attr_reader :amount, :sender, :receiver
def initialize(sender, receiver, amount)
@sender = sender
@receiver = receiver
@status = "pending"
@amount = amount
end
def valid?
sender.valid? && receiver.valid?
end
def execute_transaction
if sender.balance < amount
@status = "rejected"
return "Transaction rejected. Please check your account balance."
elsif @status != "complete" && sender.valid?
@receiver.balance = @receiver.balance + amount
@sender.balance = @sender.balance - amount
@status = "complete"
end
end
def reverse_transfer
if self.execute_transaction && valid? && @receiver.balance > amount && status == "complete"
#binding.pry
@receiver.balance = @receiver.balance - amount
@sender.balance = @sender.balance + amount
@status = "reversed"
end
end
end
In order for this code to work the way it should and reverse the transfer via #reverse_transfer that was executed in #execute_transaction, the if statement must only contain booleans. That means each component of the conditionals in the if statement have to return either "true" or "false". Which part doesn't do that?
It's the self.execute_transaction
that's the problem. That's a method that doesn't return true or false. I had included it in the conditional statement because i thought the transfer had to happen before it's reversed. Turns out, that wasn't necessary, and the whole problem of the last block of my code had to do with the first part of my if statement which wasn't a boolean.
Moral of today? Always ask others for help and always remember to check booleans and return values before making an if statement!
I took on this lab feeling good that I'd mastered some basic concepts in OO Ruby Programming. I love the elegant way that objects can communicate with each other - it seems so satisfying and organized. For a former writer and Philosophy major, this fit my brain flow perfectly!
However, I am still struggling to know when to return the array that's being added to in a method and when that's unecessary. For me, in my mind, the array is what it is and returning it isn't doing anything extra. Sometimes I think this is true. But sometimes if the method calls for something specific to be returned, the array needs to be explicitly returned.
In this lab, it doesn't matter. Take the method #back_project:
class Backer
attr_accessor :name, :title, :project, :backers, :backed_projects
def initialize(name)
@name = name
@backed_projects = []
end
def back_project(project)
magic = Project.new(project)
@backed_projects << project
@backed_projects
project.backers << self
project.backers
end
end
This does the same thing as this code:
class Backer
attr_accessor :name, :title, :project, :backers, :backed_projects
def initialize(name)
@name = name
@backed_projects = []
end
def back_project(project)
@backed_projects << project
project.backers << self
end
end
In this case, something just needs to be added to an array, and nothing is returned. It doesn't hurt anything to return the array!
I have just finished the Deli Counter Ruby lab in Learn.co, and it was interesting seeing the differences between how I solved that lab this time and over a month ago in JavaScript. First of all, I solved it so much faster this time, which means I've been grasping concepts relating to iteration and arrays! I love that I can really experience my learning progress this way. But also, I loved seeing the way Ruby handles this problem in a much simpler and more beautiful way than JavaScript.
Ruby is really a beautful language because it writes so clearly and is parsimoniously. In this lab, I knew to keep a unversal variable as my first item in the code, and that's the line (or the array) that was going to be used by every method. The first time I did this lab in JS, I struggled with the concept of local and universal variables. Since learning OO Ruby, I have really grasped those concepts plus instance varibales, and I can feel the progress I've made. I also really like the Ruby iteration process, it's so much easier to write and understand than the longer and more cumbersome looping in JS. I used both kinds of iteration to solve this lab, and it's liberating to really start to feel the ways I can solve the same problem multiple ways. Furthermore, I really like how the #each method and #each_with_index method in Ruby can be used so simply to iterate over arrays in a way my mind is really set up to grasp, perhaps more naturally than I grasped loops JS because of the incrementations and conditions involved with that.
I really love this platform, and that's not just because I work at Flatiron School. I think it's just amazing how the integrated learning environment allows me to flow through lessons and also look back at my Github profile easily to see how I solved labs in the past. It also really builds me up in an intuitive way to solve the most complicated labs. When I solved the Tic Tac Toe Object Oriented Ruby lab, it took a long time but I did really feel like it had prepared me.