- Read Tutorial
- Watch Guide Video
In this guide, we are going to add another field called hours
to our posts
database table. This is an important field, since this application's goal is managing overtime hours. I didn't add it earlier because I don't like to add items until I'm ready to use them.
To start open your console and add the hours field with a migration command:
rails g migration add_post_hour_request_to_posts overtime_request:decimal
We are using the decimal
data type here because we want users to be able to give partial hours, such as 4.5
hours or 1.5
hours. Now open the migration file, and add a default value of 0.0
since we want the hourly value to always start at 0.0
.
# db/migrate/20160726165516_add_post_hour_request_to_posts.rb class AddPostHourRequestToPosts < ActiveRecord::Migration def change add_column :posts, :overtime_request, :decimal, default: 0.0 end end
Next let's migrate the database with the command:
bundle exec rake db:migrate
Now, I'm going to quickly do a universal search to see where we are using our Post.create
method so that we can add in our new hours
parameter. In seeds.rb
, let's add hours
to the list of Post
arguments for our test data.
# db/seeds.rb 100.times do |post| Post.create!(date: Date.today, rationale: "#{post} rationale content", user_id: @user.id, overtime_request: 2.5) end puts "100 Posts have been created"
Next, we are using the create method in our integration tests in several places, let's add the overtime_request
field with a value of 3.5
in each spot.
# spec/features/post_spec.rb # Line 6 let(:post) do Post.create(date: Date.today, rationale: "Rationale", user_id: user.id, overtime_request: 3.5) end # Line 36 post_from_other_user = Post.create(date: Date.today, rationale: "This post shouldn't be seen", user_id: other_user.id, overtime_request: 3.5) # Line 60 post_to_delete = Post.create(date: Date.today, rationale: 'asdf', user_id: delete_user.id, overtime_request: 3.5) # Line 69 describe 'creation' do before do visit new_post_path end it 'has a new form that can be reached' do expect(page.status_code).to eq(200) end it 'can be created from new form page' do fill_in 'post[date]', with: Date.today fill_in 'post[rationale]', with: "Some rationale" fill_in 'post[overtime_request]', with: 4.5 # Added here expect { click_on "Save" }.to change(Post, :count).by(1) end it 'will have a user associated it' do fill_in 'post[date]', with: Date.today fill_in 'post[rationale]', with: "User Association" fill_in 'post[overtime_request]', with: 4.5 # Added here click_on "Save" expect(User.last.posts.last.rationale).to eq("User Association") end end
Next, we'll update our post
factories. Open posts.rb
, and include these fields:
# FactoryGirl.define do factory :post do date Date.today rationale "Some Rationale" overtime_request 3.5 user end factory :second_post, class: "Post" do date Date.yesterday rationale "Some more content" overtime_request 0.5 user end end
Now, go to post_spec.rb
in spec/models
and let's see what happens when we add overtime_request
, and make it nil
.
# spec/models/post_spec.rb it 'cannot be created without a date, rationale, and overtime_request' do @post.date = nil @post.rationale = nil @post.overtime_request = nil expect(@post).to_not be_valid end
If you run rspec
, everything passes. But, it shouldn't pass since our overtime hours can't be nil
.
So, let's make this field mandatory by adding it to the list of required fields in the model, like this:
# app/models/post.rb validates_presence_of :date, :rationale, :overtime_request
Next we need to ensure that our overtime_request
is greater than 0.0
since it wouldn't make sense to have an overtime request with no time requested. Let's create another test case that is going to check if our overtime_request
is greater than 0.0
.
# spec/models/post_spec.rb it 'has an overtime_request greater than 0.0' do @post.overtime_request = 0.0 expect(@post).to_not be_valid end
So in this case we're updating the value to 0.0
and we want the post
to be rendered invalid.
If you run rspec
, t gives a failure, which is what we want.
To implement this feature, go to post.rb
to add the validation:
# app/models/post.rb validates :overtime_request, numericality: { greater_than: 0.0 }
If we test this, it throws an error.
However the error isn't with our implementation code. Instead we have an error in the test case "will have a user associated with it."
. In the next guide we'll walk through how to clean up the test to get the full suite of tests back to green.