- Read Tutorial
- Watch Guide Video
We are now going to implement the functionality for the SMS workflow we designed earlier.
We are not going to have tests here because for the most part, these tests can only check the rails framework. This is why there's a lot of opinions about using test driven development for implementing rake tasks. Personally, I'm not a big fan of these because I don't think the code tests our logic.
So, we are going to start with the basic code and refactor it later.
Before that, let's add a phone number for each user. To do that, the command is:
rails g migration add_phone_to_users phone:string
Next, migrate the database with the code
bundle exec rake db:migrate
We also have to make phone number a required field. So, search for User.create
in the sublime editor and add the phone number field everywhere, just like the code in the seeds.rb
file.
# db/seeds.rb @user = User.create(email: "test@test.com", password: "asdfasdf", password_confirmation: "asdfasdf", first_name: "Jon", last_name: "Snow", phone: "4322386131") puts "1 User created" AdminUser.create(email: "admin@test.com", password: "asdfasdf", password_confirmation: "asdfasdf", first_name: "Admin", last_name: "Name", phone: "4322386131") puts "1 Admin User created"
Make the same changes in the post_spec.rb
and users.rb
as well.
Next, we have to do some extensive validations. Twilio will throw an error if the phone number is in the format "555-555-5555", so we need it to match this format "5555555555", and also, we want to restrict it to just 10 characters. In addition, we want only numbers and no other characters.
So, our validations should cover these requirements:
Let's run rspec
to ensure that everything is working fine. And it's not! If you see, we have 24 examples and all 24 failed! A quick look at the error messages show that all point to the same error, which is:
This is interesting because our SMS module has nothing to do with these tests.
Ok, the problem is a syntax error I made in a previous guide. Open the spec_helper.rb
file and change the name of our module in line #11 from FakeSMS
to FakeSms
. So, it should now be:
# spec/spec_helper.rb config.before(:each) do stub_const("SmsTool", FakeSms) end
Run rspec
again, and everything should pass.
Moving on, open user_spec.rb
in spec/models
and modify the test "cannot be created without first_name , last_name" to make phone numbers a required field.
Now, if you run rspec
, it should fail. But, it doesn't!
Let's see why. I think three items maybe an overkill. So, let's isolate them like this:
# spec/models/user_spec.rb it "cannot be created without first_name" do @user.first_name = nil expect(@user).to_not be_valid end it "cannot be created without last_name" do @user.last_name = nil expect(@user).to_not be_valid end it "cannot be created without phone" do @user.phone = nil expect(@user).to_not be_valid end
Now, we have one failure, and that's exactly what we want. To fix this error, open user.rb
and include phone in the list of validates_presence_of
validators. So, it should look like this:
# app/models/user.rb validates_presence_of :first_name, :last_name, :phone
Now, rspec
should pass.
Next, let's update the administrate dashboard. Open user_dashboard.rb
, and add the phone
attribute to ATTRIBUTE_TYPES
, SHOW_PAGE_ATTRIBUTES
and FORM_ATTRIBUTES
.
# app/dashboards/user_dashboard.rb require "administrate/base_dashboard" class UserDashboard < Administrate::BaseDashboard ATTRIBUTE_TYPES = { posts: Field::HasMany.with_options(searchable: false), id: Field::Number.with_options(searchable: false), email: Field::String.with_options(searchable: true), password: Field::String.with_options(searchable: false), sign_in_count: Field::Number.with_options(searchable: false), current_sign_in_at: Field::DateTime.with_options(searchable: false), last_sign_in_at: Field::DateTime.with_options(searchable: false), current_sign_in_ip: Field::String.with_options(searchable: false), last_sign_in_ip: Field::String.with_options(searchable: false), first_name: Field::String.with_options(searchable: false), last_name: Field::String.with_options(searchable: false), created_at: Field::DateTime.with_options(searchable: false), updated_at: Field::DateTime.with_options(searchable: false), type: Field::String.with_options(searchable: false), phone: Field::String.with_options(searchable: false), }.freeze COLLECTION_ATTRIBUTES = [ :posts, :email, :type ].freeze SHOW_PAGE_ATTRIBUTES = [ :posts, :email, :phone, :sign_in_count, :current_sign_in_at, :last_sign_in_at, :current_sign_in_ip, :last_sign_in_ip, :first_name, :last_name, :created_at, :updated_at, :type, ].freeze FORM_ATTRIBUTES = [ :email, :password, :first_name, :last_name, :phone, ].freeze end
Run rspec
again to ensure we haven't broken any functionality.
Now, let's check in the browser. Sign in as an admin and create a new user. That's all good.
Next, open admin_user_dashboard.rb
, and add the phone
field, just like we did to the user_dashboard
.
Check in the browser to see if you can create a new admin user, and with that working we can take a break.