I made a reply function for the Rails Tutorial extension (Part 4): A function that makes the user unique

This is a continuation of creating a reply function in Chapter 14 of the Rails Tutorial. Up to the last time, I was able to input and display the reply. Next, create a place to make the user unique.

Ability to make users unique

model change design

Tips in the tutorial

Add a unique user name to the user registration field so that it can be used with @reply.

Based on that, I will add a column to the model.

Find a way to add columns in the tutorial as well.

It was in Chapter 9 that we added columns to the user model. Just in case, make sure it's up to date compared to the source. sample_app / db / schema.rb Looking at it, admin and reset_sent_at are quite different. There were also some in the folders under migrate. Try searching for "migra" from the back of the text. Then, I got caught in Chapter 12. I was adding a column in Listing 12.6. Figure 12.5 was the latest.

Make the image to which you want to add columns a diagram, similar to the tutorial.

Column name attribute
id integer
name string
email string
.. ..
reset_sent_at datetime
unique_name string

Figure. User model with uniquely named columns

Find the place where you created the unique index in the tutorial. Try searching for "index". Then I got caught in Chapter 6. I was adding an index to my email address in Listing 6.29.

Model change coding

Add a column to model.

ubuntu:~/environment/sample_app (reply-micropost) $ rails generate migration add_unique_name_to_users unique_name:string
Running via Spring preloader in process 2911
      invoke  active_record
      create    db/migrate/20201018232033_add_unique_name_to_users.rb

Enter the line to create the index by hand, referring to Listing 6.29.

db/migrate/20201018232033_add_unique_name_to_users.rb


class AddUniqueNameToUsers < ActiveRecord::Migration[5.1]
  def change
    add_column :users, :unique_name, :string
    add_index :users, :unique_name, unique: true
  end
end

Make changes to the database.

ubuntu:~/environment/sample_app (reply-micropost) $ rails db:migrate

model change test

Create a test with a unique name. It may have been better to make it first. Add the test to user_test.rb.

test/models/user_test.rb green


  def setup
    @user = User.new(name: "Example User", email: "[email protected]",
                     password: "foobar", password_confirmation: "foobar",
                     unique_name: "Example")
  end

test/models/user_test.rb red


   test "unique_name should be present" do
    @user.unique_name = "    "
    assert_not @user.valid?
  end

Create a test similar to email. I made a test and found that it was unique but allowed blanks.

The function to prevent blanks was created in the email column as well, so look for it in the tutorial. It was in Listing 6.9. Add in the same way.

app/models/user.rb


  validates :password, presence: true, length: {minimum: 6}, allow_nil: true
  validates :unique_name, presence: true, length: {maximum: 50}, uniqueness: true

I was able to test that it was unique and did not allow blanks.

test/models/user_test.rb green


  test "unique_name shuould be unique" do
    duplicate_user = @user.dup
    duplicate_user.email = @user.email.upcase + "aa"
    @user.save
    assert_not duplicate_user.valid? 
  end

Let's check the test data on the console.

>> user = User.first
>> user.valid?
=> false
>> user.errors.full_messages
=> ["Unique name can't be blank", "Unique name has already been taken"]

The second person is the same, so modify the test data. Change it to include unique_name. I will take out the first name part of the first and last name from name, and first name in English and put it in unique_name.

db/seeds.rb


99.times do |n|
  name  = Faker::Name.name
  email = "example-#{n+1}@railstutorial.org"
  password = "password"
  unique_name = name.split(' ')[0]
  User.create!( name: name,
                email: email,
                password:              password,
                password_confirmation: password,
                activated: true,
                activated_at: Time.zone.now,
                unique_name: unique_name)
end

Put the data back in the database.

$ rails db:migrate:reset
ubuntu:~/environment/sample_app (reply-micropost) $ rails db:seed
rails aborted!
ActiveRecord::RecordInvalid: Validation failed: Unique name has already been taken
/home/ubuntu/.rvm/gems/ruby-2.6.3/gems/activerecord-5.1.6/lib/active_record/validations.rb:78:in `raise_validation_error'

I got an error. Let's see how many data have been entered on the console.

> User.count
   (0.2ms)  SELECT COUNT(*) FROM "users"
=> 14

There should be 100, but only 14 are included. The error message says "Unique name has already been taken", so I suspect that the unique_name is duplicated. Try it on the console to see why it overlaps.

ubuntu:~/environment/sample_app (reply-micropost) $ rails console
>> 99.times do |n|
?> name = Faker::Name.name
>> puts name.split(' ')[0].split(' ')[0]
>> end
Mr.
Forest
Araceli
Mrs.
Cody
Mr.

I was stepping on that I could retrieve the first_name, but the first word of the name was MR. MR. Seems to have various variations such as Mrs, and I think it is difficult to make it unique with simple logic, so I will give up taking it out. Change name and unique_name as irrelevant values.

db/seeds.rb


99.times do |n|
  name  = Faker::Name.name
  email = "example-#{n+1}@railstutorial.org"
  password = "password"
  unique_name = Faker::Name.first_name
  User.create!( name: name,
                email: email,
                password:              password,
                password_confirmation: password,
                activated: true,
                activated_at: Time.zone.now,
                unique_name: unique_name)
end

Put the data back in the database. At that time, since the data is already included, initialize it once.

ubuntu:~/environment/sample_app (reply-micropost) $ rails db:migrate:reset
ubuntu:~/environment/sample_app (reply-micropost) $ rails db:seed

No error occurred. Let's look at the data on the console to see if it has entered.

>> User.last
  User Load (0.2ms)  SELECT  "users".* FROM "users" ORDER BY "users"."id" DESC LIMIT ?  [["LIMIT", 1]]
=> #<User id: 100, name: "Cassandre Cummerata", email: "[email protected]", created_at: "2020-10-21 23:25:17", updated_at: "2020-10-21 23:25:17", password_digest: "$2a$10$5/ddAbowTuZim/atIYzia.jYf5omGvECsfm0AX78v3i...", remember_digest: nil, admin: false, activation_digest: "$2a$10$wMZu8WO6BCWrvYY.oPjMReGiXs0nqJ0TuyA3OZ4QWhu...", activated: true, activated_at: "2020-10-21 23:25:17", reset_digest: nil, reset_sent_at: nil, unique_name: "Julia">

unique_name has been set.

Time required

3.5 hours from 10/18 to 10/22.

Recommended Posts

I made a reply function for the Rails Tutorial extension (Part 4): A function that makes the user unique
I made a reply function for the Rails Tutorial extension (Part 1)
I made a reply function for the Rails Tutorial extension (Part 5):
I made a reply function for Rails Tutorial extension (Part 2): Change model
I tried to make a reply function of Rails Tutorial extension (Part 3): Corrected a misunderstanding of specifications
Rails Tutorial Extension: I created a follower notification function
I tried to make a message function of Rails Tutorial extension (Part 1): Create a model
I tried to make a message function of Rails Tutorial extension (Part 2): Create a screen to display
[Rails] I made a draft function using enum
Tutorial to create a blog with Rails for beginners Part 1
Tutorial to create a blog with Rails for beginners Part 0
I made a GitHub Action that makes it easy to understand the execution result of RSpec
I made a Ruby container image and moved the Lambda function
I made a question that can be used for a technical interview
Rails Tutorial Extension: I tried to create an RSS feed function
I made a simple recommendation function.
I implemented the multiple image upload function in Rails so that multiple images can be slid for the post
I made a plugin for IntelliJ IDEA
Introducing the Spring Boot Actuator, a function that makes the operation of Spring Boot applications easier.
I made a THETA API client that can be used for plug-in development
I searched for a lightweight framework that answers the sudden "make it quickly"
[Must-see for fledgling engineers] A story that the world expanded when I actually operated a web service that I made by myself
I made a Diff tool for Java files
I rewrote the Rails tutorial test with RSpec
Use [Rails] devise Guest user function (for portfolio)
I made a viewer app that displays a PDF
I made a Ruby extension library in C
I summarized the naming conventions for each Rails
I made a LINE bot with Rails + heroku
I made a portfolio with Ruby On Rails
I wrote a test code (Junit & mockit) for the code that calls the AWS API (Java)
When I created a user my page, the user editing function of devise became strange.
I made a function to register images with API in Spring Framework. Part 1 (API edition)