This is a continuation of creating a reply function in Chapter 14 of the Rails Tutorial.
When a micropost with @reply written is posted, a function to put an ID in in_reply_to of model make.
The only thing to change is to receive the post and save the model. Find out where it is.
Search the net for methods that operate on strings. https://www.sejuku.net/blog/11843 start_with? (Check if it starts with the specified string) http://rubytips86.hatenablog.com/entry/2014/03/28/132953 Read.
While digging into the features, I realized that it was a misunderstanding that I thought the content would start with @reply. 「@reply exampleuser hogehoge...」 I thought it was, but it should be correct 「@exampleuser hogehoge...」 was.
Even so, if the name contains blanks, you know you have a problem. For example, I came up with the idea that if the name is "Ola Lakin I" and you post it as "@Ola Lakin I", you can only find the name "@Ola".
One possible solution is to add a unique id. Actually, I said the same thing in the text, but at this point I finally got a pinch.
I will think about how to make the following unique because the text also describes the specific method. For the time being, we will assume that @name is unique and does not include blanks. After creating the feature on this premise, we will make some unique changes.
Try the method you searched on the net on the console.
>> s = "@Example hoge hoge aa"
=> "@Example hoge hoge aa"
>> b = s.scan(/@\w+/)
=> ["@Example"]
Find out what happens when the string does not contain @xx.
>> s2 = "Example hoge hoge aa"
=> "Example hoge hoge aa"
>> b2 = s2.scan(/@\w+/)
=> []
>> b2[0]
=> nil
It became nil.
Next, try removing the leading @.
>> b = s.scan(/@\w+/)
=> ["@Example"]
>> b[0].slice!(0)
=> "@"
>> b[0]
=> "Example"
Now you can retrieve the word @xxx.
Think the screen doesn't need to be changed and look at the text where to change the controller. I am creating in controllers / microposts_controller.rb.
controllers/microposts_controller.rb
def create
@micropost = current_user.microposts.build(micropost_params)
#Check for reply
if reply_id = @micropost.content.scan(/@\w+/)
@micropost.in_reply_to = reply_id[0].slice![0]
end
if @micropost.save
flash[:succsess] = "Micropost created!"
redirect_to root_url
else
@feed_items = []
render 'static_pages/home'
end
end
Since we will change the controller, write test first. The test item is that creating a reply micropost will increase the number of recipients by 1. Depending on where you write the test, think about how to separate it from the integration test.
Read back the tutorial for an example of testing the controller. In the microposts in Chapters 13 and 14, the integration test was done after the model test. In 13.3.1, the content of the controller test was to test whether you are logged in.
Let's actually look at the test source. Under the controllers folder. Both were tests to see if you were logged in and displayed the correct page. We found that the integration test was good for verifying the processed results.
Let's write an integration test.
test/integration/reply_test.rb RED
test "reply to user " do
log_in_as(@user)
content = "@#{@other.name} reply test content"
post microposts_path, params: { micropost: {content: content }}
log_in_as(@other)
get root_path
assert_not @other.following?(@user)
assert_match content, response.body
end
When I ran the test, I got an error with the fixture data.
ERROR["test_reply_to_user_", ReplyTest, 0.3831760289999693]
test_reply_to_user_#ReplyTest (0.38s)
NoMethodError: NoMethodError: undefined method `id' for nil:NilClass
test/fixtures/microposts.yml:54:in `get_binding'
It looks like not found. If you look on the net, it depends on the order in which fixtures are called, and if there are external restrictions It seems to be troublesome.
Instead of creating test data with fixture, try to post in model test.
By the way, I will correct the misunderstanding of @ reply's specification when I made the fixture before.
test/models/user_test.rb
test "feed should have the reply posts" do
michael = users(:michael)
malory = users(:malory)
assert_not malory.following?(michael)
reply_post = michael.microposts.create!(content: "@malory reply test",
in_reply_to: malory.id)
assert michael.feed.include?(reply_post)
assert malory.feed.include?(reply_post)
end
The test is now passed.
Change the controller.
controllers/microposts_controller.rb
def create
@micropost = current_user.microposts.build(micropost_params)
#Check for reply
if reply_id = @micropost.content.scan(/@\w+/)[0]
reply_id.slice!(0)
@micropost.in_reply_to = User.find_by(name: reply_id)
end
if @micropost.save
flash[:succsess] = "Micropost created!"
redirect_to root_url
else
@feed_items = []
render 'static_pages/home'
end
end
Correct the test data. Create a user with no space between the first and last name.
test/fixtures/users.yml
Bob:
name: Bob
email: [email protected]
password_digest: <%= User.digest('password') %>
activated: true
activated_at: <%= Time.zone.now %>
The test is still Red, so when I debugged with puts, I found a mistake and fixed it. I needed an id.
Before modification @ micropost.in_reply_to = User.find_by (name: reply_id) After modification @ micropost.in_reply_to = User.find_by (name: reply_id) .id
controllers/microposts_controller.rb
def create
@micropost = current_user.microposts.build(micropost_params)
#Check for reply
if reply_id = @micropost.content.scan(/@\w+/)[0]
reply_id.slice!(0)
@micropost.in_reply_to = User.find_by(name: reply_id).id
end
if @micropost.save
flash[:succsess] = "Micropost created!"
redirect_to root_url
else
@feed_items = []
render 'static_pages/home'
end
end
The test is now GREEN.
Let's test it on the screen. I created a user with no space and confirmed that it works.
2.5 hours from 10/11 to 10/17.
Recommended Posts