・ Rails tutorial is the 4th edition ・ This study is the 3rd lap (2nd lap after Chapter 9) ・ The author is a beginner who has done all of Progate.
・ If you read it, you will not understand it. ・ Search and summarize terms that you do not understand (at the bottom of the article, glossary). ・ Dive into what you do not understand. ・ Work on all exercises. ・ Do not copy chords as much as possible.
Last! !! !! !! !! Run through to the end! !! !! !! !!
Click here for the BGM that decorates the last. My Bloody Valentine "Loveless" A piece that seems to start and end. No longer in charge of punch lines. Let's listen while making brain juice at a loud volume.
2. With reference to Figure 14.7, what will be the result if user.following is executed for the user with id = 2? Also, user.following.map (&: id) for the same user. What would the result be if you run? Imagine. → Returns the id of the user that user 2 is following (1 in this case). The latter is the array.
>> user = User.first
User Load (0.2ms) SELECT "users".* FROM "users" ORDER BY "users"."id" ASC LIMIT ? [["LIMIT", 1]]
=> #<User id: 1, name: "Example User", email: "[email protected]", created_at: "2020-09-21 06:47:51", updated_at: "2020-09-21 06:47:51", password_digest: "$2a$10$nAPmDn2RaEHJcHlMrK2PK.nOxUN4ULh7yUHchZRZtSZ...", remember_digest: nil, admin: true, activation_digest: "$2a$10$l9hNDaXUmopBnprlT0H7J.YFieEB8U9OoNgA0mzcrPS...", activated: true, activated_at: "2020-09-21 06:47:51", reset_digest: nil, reset_sent_at: nil>
>> other_user = User.second
User Load (0.2ms) SELECT "users".* FROM "users" ORDER BY "users"."id" ASC LIMIT ? OFFSET ? [["LIMIT", 1], ["OFFSET", 1]]
=> #<User id: 2, name: "Ms. Jerry Hermann", email: "[email protected]", created_at: "2020-09-21 06:47:52", updated_at: "2020-09-21 06:47:52", password_digest: "$2a$10$4n7IPw3AcdhW6IzNuLygIuVLA26qlTNneHXDXIqW0zp...", remember_digest: nil, admin: false, activation_digest: "$2a$10$QNHMG3qKng0pFdQdDfGNMeFZaDiddcT0z3ovdEVcOcn...", activated: true, activated_at: "2020-09-21 06:47:52", reset_digest: nil, reset_sent_at: nil>
>> user.active_relationships.create(followed_id: other_user.id)
(0.1ms) SAVEPOINT active_record_1
User Load (0.1ms) SELECT "users".* FROM "users" WHERE "users"."id" = ? LIMIT ? [["id", 1], ["LIMIT", 1]]
User Load (0.1ms) SELECT "users".* FROM "users" WHERE "users"."id" = ? LIMIT ? [["id", 2], ["LIMIT", 1]]
SQL (3.4ms) INSERT INTO "relationships" ("follower_id", "followed_id", "created_at", "updated_at") VALUES (?, ?, ?, ?) [["follower_id", 1], ["followed_id", 2], ["created_at", "2020-09-23 12:37:03.376561"], ["updated_at", "2020-09-23 12:37:03.376561"]]
(0.1ms) RELEASE SAVEPOINT active_record_1
=> #<Relationship id: 1, follower_id: 1, followed_id: 2, created_at: "2020-09-23 12:37:03", updated_at: "2020-09-23 12:37:03">
2. After completing the previous exercise, check the value of active_relationship.followed and the value of active_relationship.follower, and make sure that each value is correct. → It appears at the bottom of the above answer.
has_many: Array name, through :: Table name, source :: Original set of array ... It's kind of confusing. Shouldn't it have been defined by the name used in the original name? Question.
>> user = User.first
User Load (0.2ms) SELECT "users".* FROM "users" ORDER BY "users"."id" ASC LIMIT ? [["LIMIT", 1]]
=> #<User id: 1, name: "Example User", email: "[email protected]", created_at: "2020-09-21 06:47:51", updated_at: "2020-09-21 06:47:51", password_digest: "$2a$10$nAPmDn2RaEHJcHlMrK2PK.nOxUN4ULh7yUHchZRZtSZ...", remember_digest: nil, admin: true, activation_digest: "$2a$10$l9hNDaXUmopBnprlT0H7J.YFieEB8U9OoNgA0mzcrPS...", activated: true, activated_at: "2020-09-21 06:47:51", reset_digest: nil, reset_sent_at: nil>
>> other_user = User.second
User Load (0.3ms) SELECT "users".* FROM "users" ORDER BY "users"."id" ASC LIMIT ? OFFSET ? [["LIMIT", 1], ["OFFSET", 1]]
=> #<User id: 2, name: "Ms. Jerry Hermann", email: "[email protected]", created_at: "2020-09-21 06:47:52", updated_at: "2020-09-21 06:47:52", password_digest: "$2a$10$4n7IPw3AcdhW6IzNuLygIuVLA26qlTNneHXDXIqW0zp...", remember_digest: nil, admin: false, activation_digest: "$2a$10$QNHMG3qKng0pFdQdDfGNMeFZaDiddcT0z3ovdEVcOcn...", activated: true, activated_at: "2020-09-21 06:47:52", reset_digest: nil, reset_sent_at: nil>
>> user.following?(other_user)
User Exists (0.6ms) SELECT 1 AS one FROM "users" INNER JOIN "relationships" ON "users"."id" = "relationships"."followed_id" WHERE "relationships"."follower_id" = ? AND "users"."id" = ? LIMIT ? [["follower_id", 1], ["id", 2], ["LIMIT", 1]]
=> false
>> user.follow(other_user)
(0.1ms) SAVEPOINT active_record_1
User Load (0.1ms) SELECT "users".* FROM "users" WHERE "users"."id" = ? LIMIT ? [["id", 1], ["LIMIT", 1]]
SQL (6.4ms) INSERT INTO "relationships" ("follower_id", "followed_id", "created_at", "updated_at") VALUES (?, ?, ?, ?) [["follower_id", 1], ["followed_id", 2], ["created_at", "2020-09-23 14:03:47.235565"], ["updated_at", "2020-09-23 14:03:47.235565"]]
(0.1ms) RELEASE SAVEPOINT active_record_1
User Load (0.1ms) SELECT "users".* FROM "users" INNER JOIN "relationships" ON "users"."id" = "relationships"."followed_id" WHERE "relationships"."follower_id" = ? LIMIT ? [["follower_id", 1], ["LIMIT", 11]]
=> #<ActiveRecord::Associations::CollectionProxy [#<User id: 2, name: "Ms. Jerry Hermann", email: "[email protected]", created_at: "2020-09-21 06:47:52", updated_at: "2020-09-21 06:47:52", password_digest: "$2a$10$4n7IPw3AcdhW6IzNuLygIuVLA26qlTNneHXDXIqW0zp...", remember_digest: nil, admin: false, activation_digest: "$2a$10$QNHMG3qKng0pFdQdDfGNMeFZaDiddcT0z3ovdEVcOcn...", activated: true, activated_at: "2020-09-21 06:47:52", reset_digest: nil, reset_sent_at: nil>]>
>> user.following?(other_user)
User Exists (0.2ms) SELECT 1 AS one FROM "users" INNER JOIN "relationships" ON "users"."id" = "relationships"."followed_id" WHERE "relationships"."follower_id" = ? AND "users"."id" = ? LIMIT ? [["follower_id", 1], ["id", 2], ["LIMIT", 1]]
=> true
>> user.unfollow(other_user)
Relationship Load (0.2ms) SELECT "relationships".* FROM "relationships" WHERE "relationships"."follower_id" = ? AND "relationships"."followed_id" = ? LIMIT ? [["follower_id", 1], ["followed_id", 2], ["LIMIT", 1]]
(0.1ms) SAVEPOINT active_record_1
SQL (0.2ms) DELETE FROM "relationships" WHERE "relationships"."id" = ? [["id", 1]]
(0.1ms) RELEASE SAVEPOINT active_record_1
=> #<Relationship id: 1, follower_id: 1, followed_id: 2, created_at: "2020-09-23 14:03:47", updated_at: "2020-09-23 14:03:47">
>> user.following?(other_user)
User Exists (0.2ms) SELECT 1 AS one FROM "users" INNER JOIN "relationships" ON "users"."id" = "relationships"."followed_id" WHERE "relationships"."follower_id" = ? AND "users"."id" = ? LIMIT ? [["follower_id", 1], ["id", 2], ["LIMIT", 1]]
=> false
2. Let's look back at the result of executing each command in the previous exercise and check what kind of SQL was actually output. → As above. INSERT and DELETE.
Oh yeah. Is the reason why I used through and source in the previous section to handle one table from different sides? Even so, followed_id is difficult to understand.
>> user = User.first
User Load (0.2ms) SELECT "users".* FROM "users" ORDER BY "users"."id" ASC LIMIT ? [["LIMIT", 1]]
=> #<User id: 1, name: "Example User", email: "[email protected]", created_at: "2020-09-21 06:47:51", updated_at: "2020-09-21 06:47:51", password_digest: "$2a$10$nAPmDn2RaEHJcHlMrK2PK.nOxUN4ULh7yUHchZRZtSZ...", remember_digest: nil, admin: true, activation_digest: "$2a$10$l9hNDaXUmopBnprlT0H7J.YFieEB8U9OoNgA0mzcrPS...", activated: true, activated_at: "2020-09-21 06:47:51", reset_digest: nil, reset_sent_at: nil>
>> other1 = User.second
User Load (0.2ms) SELECT "users".* FROM "users" ORDER BY "users"."id" ASC LIMIT ? OFFSET ? [["LIMIT", 1], ["OFFSET", 1]]
=> #<User id: 2, name: "Ms. Jerry Hermann", email: "[email protected]", created_at: "2020-09-21 06:47:52", updated_at: "2020-09-21 06:47:52", password_digest: "$2a$10$4n7IPw3AcdhW6IzNuLygIuVLA26qlTNneHXDXIqW0zp...", remember_digest: nil, admin: false, activation_digest: "$2a$10$QNHMG3qKng0pFdQdDfGNMeFZaDiddcT0z3ovdEVcOcn...", activated: true, activated_at: "2020-09-21 06:47:52", reset_digest: nil, reset_sent_at: nil>
>> other2 = User.third
User Load (0.1ms) SELECT "users".* FROM "users" ORDER BY "users"."id" ASC LIMIT ? OFFSET ? [["LIMIT", 1], ["OFFSET", 2]]
=> #<User id: 3, name: "Bernice Rippin", email: "[email protected]", created_at: "2020-09-21 06:47:52", updated_at: "2020-09-21 06:47:52", password_digest: "$2a$10$fsftEGHfcujlrAy4h.X2VelOSKNXNDnk71MbkBPOqSA...", remember_digest: nil, admin: false, activation_digest: "$2a$10$4DlqqHWVesXipOA4xC/XAOlA70S8T6PjkH3/T4RAI7M...", activated: true, activated_at: "2020-09-21 06:47:52", reset_digest: nil, reset_sent_at: nil>
>> other1.follow(user)
(0.1ms) SAVEPOINT active_record_1
User Load (0.1ms) SELECT "users".* FROM "users" WHERE "users"."id" = ? LIMIT ? [["id", 2], ["LIMIT", 1]]
SQL (0.1ms) INSERT INTO "relationships" ("follower_id", "followed_id", "created_at", "updated_at") VALUES (?, ?, ?, ?) [["follower_id", 2], ["followed_id", 1], ["created_at", "2020-09-23 22:04:23.011442"], ["updated_at", "2020-09-23 22:04:23.011442"]]
(0.1ms) RELEASE SAVEPOINT active_record_1
User Load (0.1ms) SELECT "users".* FROM "users" INNER JOIN "relationships" ON "users"."id" = "relationships"."followed_id" WHERE "relationships"."follower_id" = ? LIMIT ? [["follower_id", 2], ["LIMIT", 11]]
=> #<ActiveRecord::Associations::CollectionProxy [#<User id: 1, name: "Example User", email: "[email protected]", created_at: "2020-09-21 06:47:51", updated_at: "2020-09-21 06:47:51", password_digest: "$2a$10$nAPmDn2RaEHJcHlMrK2PK.nOxUN4ULh7yUHchZRZtSZ...", remember_digest: nil, admin: true, activation_digest: "$2a$10$l9hNDaXUmopBnprlT0H7J.YFieEB8U9OoNgA0mzcrPS...", activated: true, activated_at: "2020-09-21 06:47:51", reset_digest: nil, reset_sent_at: nil>]>
>> other2.follow(user)
(0.1ms) SAVEPOINT active_record_1
User Load (0.1ms) SELECT "users".* FROM "users" WHERE "users"."id" = ? LIMIT ? [["id", 3], ["LIMIT", 1]]
SQL (0.1ms) INSERT INTO "relationships" ("follower_id", "followed_id", "created_at", "updated_at") VALUES (?, ?, ?, ?) [["follower_id", 3], ["followed_id", 1], ["created_at", "2020-09-23 22:04:33.583218"], ["updated_at", "2020-09-23 22:04:33.583218"]]
(0.1ms) RELEASE SAVEPOINT active_record_1
User Load (0.1ms) SELECT "users".* FROM "users" INNER JOIN "relationships" ON "users"."id" = "relationships"."followed_id" WHERE "relationships"."follower_id" = ? LIMIT ? [["follower_id", 3], ["LIMIT", 11]]
=> #<ActiveRecord::Associations::CollectionProxy [#<User id: 1, name: "Example User", email: "[email protected]", created_at: "2020-09-21 06:47:51", updated_at: "2020-09-21 06:47:51", password_digest: "$2a$10$nAPmDn2RaEHJcHlMrK2PK.nOxUN4ULh7yUHchZRZtSZ...", remember_digest: nil, admin: true, activation_digest: "$2a$10$l9hNDaXUmopBnprlT0H7J.YFieEB8U9OoNgA0mzcrPS...", activated: true, activated_at: "2020-09-21 06:47:51", reset_digest: nil, reset_sent_at: nil>]>
>> user.followers.map(&:id)
User Load (0.2ms) SELECT "users".* FROM "users" INNER JOIN "relationships" ON "users"."id" = "relationships"."follower_id" WHERE "relationships"."followed_id" = ? [["followed_id", 1]]
=> [2, 3]
2. After completing the above exercise, check that the execution result of user.followers.count matches the number of users you followed earlier. → Below
>> user.followers.count
(0.2ms) SELECT COUNT(*) FROM "users" INNER JOIN "relationships" ON "users"."id" = "relationships"."follower_id" WHERE "relationships"."followed_id" = ? [["followed_id", 1]]
=> 2
3. What is the content of the SQL statement output as a result of executing user.followers.count? Also, are there any differences from the execution result of user.followers.to_a.count? Tip: What's the difference if a user has 1 million followers? Think about it. → SQL is as above. It may take time and load to make an array. So only count is better.
>> user.followers.to_a.count
=> 2
>> User.first.followers.count
User Load (0.1ms) SELECT "users".* FROM "users" ORDER BY "users"."id" ASC LIMIT ? [["LIMIT", 1]]
(0.2ms) SELECT COUNT(*) FROM "users" INNER JOIN "relationships" ON "users"."id" = "relationships"."follower_id" WHERE "relationships"."followed_id" = ? [["followed_id", 1]]
=> 38
2. As with the previous exercise, let's confirm that the results of User.first.following.count also match. → This is also OK
>> User.first.following.count
User Load (0.1ms) SELECT "users".* FROM "users" ORDER BY "users"."id" ASC LIMIT ? [["LIMIT", 1]]
(0.2ms) SELECT COUNT(*) FROM "users" INNER JOIN "relationships" ON "users"."id" = "relationships"."followed_id" WHERE "relationships"."follower_id" = ? [["follower_id", 1]]
=> 49
Member routing: You can add new routing to RESTful routing. member takes the form of a block. Handles URLs that include user ids. If id is not specified, use collection.
2. Display the Home page and profile page from your browser and check if the statistics are displayed correctly. → Both stats are displayed.
3. Let's write a test for the statistical information displayed on the Home page. Tip: Try adding to the test shown in Listing 13.28. In the same way, let's add a test to the profile page. → Below. When I looked it up, I found that @ user.active (or passive) _relationships was written. Can I use either one? When I tried it on the console, both returned the same result, but maybe relationships is better because it requires less processing?
saite_layout_tesr.rb
test "stats" do
log_in_as(@user)
get root_path
assert_match @user.following.count.to_s, response.body
assert_match @user.followers.count.to_s, response.body
end
user_profile_test.rb
test "profile display" do
get user_path(@user)
assert_template 'users/show'
assert_select 'title', full_title(@user.name)
assert_select 'h1', text: @user.name
assert_select 'h1>img.gravatar'
assert_match @user.following.count.to_s, response.body
assert_match @user.followers.count.to_s, response.body
assert_match @user.microposts.count.to_s, response.body
assert_select 'div.pagination', count: 1
@user.microposts.paginate(page: 1).each do |micropost|
assert_match micropost.content, response.body
end
end
>> user.active_relationships.count
(0.1ms) SELECT COUNT(*) FROM "relationships" WHERE "relationships"."follower_id" = ? [["follower_id", 1]]
=> 49
>> user.following.count
(0.2ms) SELECT COUNT(*) FROM "users" INNER JOIN "relationships" ON "users"."id" = "relationships"."followed_id" WHERE "relationships"."follower_id" = ? [["follower_id", 1]]
=> 49
2. Comment out the code associated with assert_select in Listing 14.29 to make sure the test turns red correctly. → That? Will it be RED? … Ah, right? I also had to comment out render. I commented out only the @users block. following.
ruby:show_follow.html.erb
<% provide(:title, @title) %>
<div class="row">
<aside class="col-md-4">
<section class="user_info">
<%= gravatar_for @user %>
<h1><%= @user.name %></h1>
<span><%= link_to "view my profile", @user %></span>
<span><b>Microposts:</b><%= @user.microposts.count %></span>
</section>
<section class="stats">
<%= render 'shared/stats' %>
<% if @users.any? %>
<div class="user_avatars">
<%# @users.each do |user| %>
<%#= link_to gravatar_for(user, size: 30), user %>
<%# end %>
</div>
<% end %>
</section>
</aside>
<div class="col-md-8">
<h3><%= @title %></h3>
<% if @users.any? %>
<ul class="users follow">
<%#= render @users %>
</ul>
<%= will_paginate %>
<% end %>
</div>
</div>
2. After completing the exercise, let's take a look at the Rails server log. Which template is drawn when follow / unfollow is executed? → Rendering users/show.html.erb within layouts/application
Ajax implementation: ① Enter remote: true in form_for. (2) Enter the respond_to method in the action of the controller. Receive Ajax requests. (3) In case JS is disabled on the browser side, add the description for it to the config / application.rb file. ④ Enter jQuery in action name.js.erb. I forgot jQuery ... Will you review it with progate?
2. After confirming in the previous exercise, let's browse the Rails server log and check what the template looks like immediately after executing follow / unfollow. → Rendering relationships/create.js.erb Rendering relationships/destroy.js.erb
You can test the operation of Ajax just by entering xhr: true.
2. What is the result of deleting only one of the lines with xhr: true in Listing 14.40? The cause of the problem that occurs at this time and why the test confirmed in the previous exercise detected this problem. Think about it. → I don't know how much to delete, but if you delete it so that the grammar does not change, it will be GREEN. Is it because there is no format to display when JS is disabled? (It's ambiguous whether the exercise I mentioned earlier is Exercise 1 or the latest deletion ...)
user.rb
def feed
Micropost.where("user_id IN (?)", following_ids)
end
2. How can I not include posts from followers in Listing 14.44? And which test in Listing 14.42 would fail if I made such a change? → The opposite of 1. Erase the former set. #Check the posts of the users you are following. The following 3 lines of FAIL are returned.
3. How can I include posts from users I don't follow in Listing 14.44? And which test in Listing 14.42 would fail if I made such a change? Tip: Follow yourself and follow Think about what kind of set the user who is doing and the other set represents. → This means that all micro posts are the point. So below. FAIL confirms the last # post of an unfollowed user.
user.rb
def feed
Micropost.all
end
following_test.rb
test "feed on Home page" do
get root_path
@user.feed.paginate(page: 1).each do |micropost|
assert_match CGI.escapeHTML(micropost.content), response.body
end
end
2. In the code in Listing 14.49, the expected HTML is escaped with the CGI.escapeHTML method (this method has the same purpose as CGI.escape dealt with in 11.2.3). Why did you need to escape the HTML in this code? Think about it. Tip: Try removing the escaping process and carefully examine the resulting HTML content. Something is wrong with the contents of the micro post. You can also use the terminal search function (Cmd-F or Ctrl-F) to search for "sorry" to help determine the cause. → Wow, when I tested it, I got a terrible amount of error text. If you search for sorry, "Your words made sense, but your sarcastic tone did not." = "Your words make sense, but your ironic tone wasn't." I mean, is there something that can't be displayed without escaping?
-You can flexibly name and handle table elements by setting has_many in the model. • Routing can be nested to add new to resources. -Adopt Ajax for the form using jQuery. -SQL can be used as needed. ・ Tutorial is just a tutorial. Know that you've finally reached the start line (a commandment to yourself).
Two and a half laps completed! !! Thank you! !! !!
Starting from September 1st, today is the 25th. I managed to finish it within the month I was aiming for. I think that the content learned in the tutorial has come to my mind, but as I research the questions each time, I feel that there are 99% of things I do not know yet. Therefore, it is the last sentence of the summary. Rather, it feels like I'm still up to stand on the starting line. I'm just starting to climb, so this endlessly distant man slope ...
Well, that's it for the Rails tutorial. The next stage is going to school. At this point, I realized that self-propelled ability and self-study ability are more important than honest school ununun. However, as the title of the article suggests, I don't have time to say something lenient. In order to challenge the world, it is necessary to concentrate tightly and study in the backwaters. So the next move is to study at school. Either way, I think it's the same to research and think for yourself and write the code, but it's definitely worth it to have the instructor look at your code and tell you what you need, and it will save you time. I think it will be connected. It's an adult way of telling money. I'm imitating it.
If you have a free time to write something like that, talk about studying! See you again! I like writing articles, so I'll do my best to write useful articles someday! !!
⇦ Click here for Chapter 13 Click here for premise and author status for learning
・ Ajax Abbreviation for Asynchronous JavaScript + XML. Technology that moves the contents of a page in various ways without moving or reloading the page.
·asynchronous When transferring data, exchange data without worrying about the timing matching (synchronization) between the transmitting side and the receiving side.
・ XML (Extensible Markup Language) An extensible markup language. One of the rules of writing. It is mainly used for the purpose of facilitating data exchange and management.
・ DOM (Document Object Model) It's not the black one hovering. It is a mechanism for freely operating Web pages such as HTML from a program, and has a hierarchical structure (tree structure).
Recommended Posts