## ROR TUTORIAL (3RD ED.) Ch11 User microposts

1. 每次都要新增一個branch
2. 怎麼使用Amazon.com’s Simple Storage Service (S3)
3. user:references這樣寫可以直接產生關聯，然後會有user_id (belongs_to :user會自動產生)

The generate command produces a migration to create a microposts table in the database (Listing 11.1); compare it to the analogous migration for the users table from Listing 6.2. The biggest difference is the use of references, which automatically adds a user_id column (along with an index and a foreign key reference)3 for use in the user/micropost association.

4. 把micropost叫出來的時候，要按特定的user，還要有特定的順序，所以:user_id:create_at都要記得上index
Because we expect to retrieve all the microposts associated with a given user id in reverse order of creation, Listing 11.1 adds an index (Box 6.2) on the user_id and created_at columns:

By including both the user_id and created_at columns as an array, we arrange for Rails to create a multiple key index, which means that Active Record uses both keys at the same time.

5. 要記得rake db:migrate，資料庫才會被更新。
With the migration in Listing 11.1, we can update the database as usual:

6. assert @micropost.valid?答案是valid，所以assert會是true (因為都還沒有設任何的validation，要到micropost.rb去設validates :user_id, presence: true)

7. 'assert_not @micropost.valid?' 答案是valid，所以assert_not會是false (因為都還沒有設任何的validation，要到micropost.rb去設validates :user_id, presence: true)

8. assert_not @micropost.valid?也會是valid，雖然@micropost.content是空白的，但因為沒有validation，所以還是valid。

9. assert_not @micropost.valid?也是valid，因為還沒有設定少於140個字母。

10. 要這樣設才有會讓7跟8是not valid，然後才會變true：validates :content, presence: true, length: { maximum: 140 }

11. 第二個寫法才是正確的，可以順便產生user_id

These latter methods constitute the idiomatically correct way to make a micropost, namely, through its association with a user. When a new micropost is made in this way, its user_id is automatically set to the right value.

12. 這邊又要去想一下newbuild的差別
(As with new, build returns an object in memory but doesn’t modify the database.)

13. default_scope可以將資料從資料庫按照我們所需要的順序叫出來
We’ll get the test to pass using a Rails method called default_scope, which among other things can be used to set the default order in which elements are retrieved from the database

14. 'order'是default_scope的一個argument
To enforce a particular order, we’ll include the order argument in default_scope, which lets us order by the created_at column as follows:order(:created_at)

15. 這樣就可以由新到舊的。
default_scope -> { order(created_at: :desc) }
Listing 11.16 introduces the “stabby lambda” syntax for an object called a Proc (procedure) or lambda, which is an anonymous function (a function created without a name). The stabby lambda -> takes in a block (Section 4.3.2) and returns a Proc, which can then be evaluated with the call method. We can see how it works at the console:
Proc(procedure)跟lambda是匿名函數(不需要取名字)，然後可以用call 去呼叫。

16. dependent: :destroy: user被刪除的時候，user的micropost也要被刪除，所以是要放在user.rb
has_many :microposts, dependent: :destroy

17. render @users這樣的寫法，rails會自己去找_user.html.erb的partial。所以我們可以用render @microposts去找 _micropost.html.erb 的partial

automatically renders each of the users in the @users variable using the _user.html.erb partial. We’ll define an analogous _micropost.html.erb partial so that we can use the same technique on a collection of microposts as follows:

18. <%= will_paginate @microposts %>will_paginate如果是放在User Controller，會自動去找@user這個變數，如果是放在User Controller，但是又希望他去找其他的變數，如@microposts，那就要把變數寫在後面。如<%= will_paginate @microposts %>。要記得定義@microposts，@microposts = @user.microposts.paginate(page: params[:page])
As before, we’ll use the will_paginate method:<%= will_paginate @microposts %>
If you compare this with the analogous line on the user index page, Listing 9.41, you’ll see that before we had just<%= will_paginate %>
This worked because, in the context of the Users controller, will_paginate assumes the existence of an instance variable called @users (which, as we saw in Section 9.3.3, should be of class ActiveRecord::Relation). In the present case, since we are still in the Users controller but want to paginate microposts instead, we’ll pass an explicit @microposts variable to will_paginate. Of course, this means that we will have to define such a variable in the user show action (Listing 11.22).

19. count的好處：不會把所有資料從資料庫叫出來，然後再去計算長度，這樣太沒效率。'count'會直接在資料庫裡面先算好數量之後。
更進階的可以使用counter cache
As with paginate, we can use the count method through the association. In particular, count does not pull all the microposts out of the database and then call length on the resulting array, as this would become inefficient as the number of microposts grew. Instead, it performs the calculation directly in the database, asking the database to count the microposts with the given user_id (an operation for which all databases are highly optimized). (In the unlikely event that finding the count is still a bottleneck in your application, you can make it even faster using a counter cache.)

20. resources :microposts, only: [:create, :destroy] : 不需要new跟dit，只要create跟destroy因為大部份的動作都要在Profile跟Home執行。
the interface to the Microposts resource will run principally through the Profile and Home pages, so we won’t need actions like new or edit in the Microposts controller; we’ll need only create and destroy.

21. logged_in_user這個filter本來是放在User Controller裡面，可是因為現在Microposts Controller也要用，所以把他拿到Application controller裡面去，所有的Controller都可以用了!
Writing the application code needed to get the tests in Listing 11.30 to pass requires a little refactoring first. Recall from Section 9.2.1 that we enforced the login requirement using a before filter that called the logged_in_user method (Listing 9.12). At the time, we needed that method only in the Users controller, but now we find that we need it in the Microposts controller as well, so we’ll move it into the Application controller, which is the base class of all controllers (Section 4.4.4). The result appears in Listing 11.31.

22. 如果登入，就顯示app/views/shared/_user_info.html.erbapp/views/shared/_micropost_form.html.erb

23. _micropost_form.html.erb這個partial是在home.html.erb裡面，所以裡面的@micropost要在static_pages_controller.rb裡面定義，不過這個變數@micropost還是會送到Micropost Controller的create method去，所以Create那邊要接好micropoat_params

24. 每個user都要有feed，所以會把feed method放在User Controller裡。Micropost.where("user_id = ?", id)
我的理解：在User的Profile裡，如果要叫出來一個User所有的microposts的話，因為有關聯的關係，所以可以打成@user.microposts，不過為了增加易讀性，所以要把它包裝在feed method裡面，就可以改寫成@user.feed。
Since each user should have a feed, we are led naturally to a feed method in the User model, which will initially just select all the microposts belonging to the current user. We’ll accomplish this using the where method on the Micropost model (seen briefly before in Section 10.5), as shown in Listing 11.44.10

Alert readers might note at this point that the code in Listing 11.44 is essentially equivalent to writing

We’ve used the code in Listing 11.44 instead because it generalizes much more naturally to the full status feed needed in Chapter 12.

25. ("user_id = ?", id)這樣的寫法是為了防止SQL injection。
ensures that id is properly escaped before being included in the underlying SQL query, thereby avoiding a serious security hole called SQL injection. The id attribute here is just an integer (i.e., self.id, the unique ID of the user), so there is no danger of SQL injection in this case, but always escaping variables injected into SQL statements is a good habit to cultivate.

26. 接下來要開始用partial

27. 在首頁的地方，<%= render 'shared/feed' %> 將顯示_feed.html.erb這個partial。

28. _feed.html.erb這個partial，又會顯示@feed_items這個變數，因為這個變數的class是Micropost，所以又會自動去找_micropost.html.erb這個partial。

Here Rails knows to call the micropost partial because each element of @feed_items has class Micropost. This causes Rails to look for a partial with the corresponding name in the views directory of the given resource:app/views/microposts/_micropost.html.erb

29. 如果送出micropost失敗的話，會break。如果輸入一個空的rray好像也沒用。
At this point, creating a new micropost works as expected, as seen in Figure 11.15. There is one subtlety, though: on failed micropost submission, the Home page expects an @feed_items instance variable, so failed submissions currently break. The easiest solution is to suppress the feed entirely by assigning it an empty array, as shown in Listing 11.48. (Unfortunately, returning a paginated feed doesn’t work in this case. Implement it and click on a pagination link to see why.)

30. <%= render @feed_items %><%= render @microposts %>，這邊的@變數裡面應該都有複數的東西，可是為什麼不必用到each？
原來在Ch9的地方有講到：
9.3.5 Partial refactoring

Here Rails infers that @users is a list of User objects; moreover, when called with a collection of users, Rails automatically iterates through them and renders each one with the _user.html.erb partial. The result is the impressively compact code in Listing 9.48.
雖然Rails會把@user當作User的列表，一個集合，但是在patial的情況下，他會一個一個顯示出來。

31. 點了delete之後，micropost的id會被送到Micropost Controllerdestroy method去。
因為有設before_action的關係，他會先去執行correct_user method
@micropost = current_user.microposts.find_by(id: params[:id])
這邊的id: params[:id]micropost的id
we’ll find the micropost through the association, which will automatically fail if a user tries to delete another user’s micropost. We’ll put the resulting find inside a correct_user before filter, which checks that the current user actually has a micropost with the given id. The result appears in Listing 11.50.
假設current_usermicropost中找不到這個id，會return nil(不會跳出錯誤訊息)
(find會有錯誤訊息，find_by會return nil)
find vs find_by vs where
If no record is found, returns nil.

32. request.referrer || root_url
This uses the request.referrer method,11 which is closely related to the request.url variable used in friendly forwarding (Section 9.2.3), and is just the previous URL (in this case, the Home page).12 This is convenient because microposts appear on both the Home page and on the user’s profile page, so by using request.referrer we arrange to redirect back to the page issuing the delete request in both cases. If the referring URL is nil (as is the case inside some tests), Listing 11.50 sets the root_url as the default using the || operator. (Compare to the default options defined in Listing 8.50.)

33. 開始做上傳照片

34. Micropost Model會需要用到下面的gem，把他們都加到Gemfile

• carrierwave gem： 上傳照片
• mini_magick gem：image resizing (Section 11.4.3)
• fog gem： image upload in production (Section 11.4.4)
35. \$ rails generate uploader Picture：產生image uploader 圖片上傳器。
CarrierWave adds a Rails generator for creating an image uploader, which we’ll use to make an uploader for an image called picture。

36. 要用CarrierWave上傳照片很簡單：在generate之後，記得把名字(這邊是Picture)放到相對應的Model(這邊是Microposts)去就好了，記得要設成String
Images uploaded with CarrierWave should be associated with a corresponding attribute in an Active Record model, which simply contains the name of the image file in a string field. The resulting augmented data model for microposts appears in Figure 11.19.
To add the required picture attribute to the Micropost model, we generate a migration and migrate the development database:

37. 然後要加上這行：mount_uploader :picture, PictureUploader，才有辦法把image跟model連接起來。
The way to tell CarrierWave to associate the image with a model is to use the mount_uploader method, which takes as arguments a symbol representing the attribute and the class name of the generated uploader:
(Here PictureUploader is defined in the file picture_uploader.rb, which we’ll start editing in Section 11.4.2, but for now the generated default is fine.) Adding the uploader to the Micropost model gives the code shown in Listing 11.56.

38. html: { multipart: true } ：in the arguments to form_for, which is necessary for file uploads.
<%= f.file_field :picture %>： To include the uploader on the Home page

39. image_tag helper可以叫出來照片。
picture? boolean method 是CarrierWave跟據attribute的名字自動產生的method。
Once the image has been uploaded, we can render it using the image_tag helper in the micropost partial, as shown in Listing 11.59. Notice the use of the picture? boolean method to prevent displaying an image tag when there isn’t an image. This method is created automatically by CarrierWave based on the name of the image attribute. The result of making a successful submission by hand appears in Figure 11.20. Writing an automated test for image upload is left as an exercise (Section 11.6).

40. 開始限制上傳的照片的格式跟尺寸，在伺服器端跟瀏覽器端都需要做設定

42. 伺服器端：尺寸：Micropost model，size validation不是內建的，所以要自己寫

43. 用戶端：有兩個
類型：<%= f.file_field :picture, accept: 'image/jpeg,image/gif,image/png' %>
尺寸：

44. 把Query放在最下面

45. ImageMagick: 變更上傳圖檔的尺寸

46. MiniMagickCarrierWavemodule，是用來操控ImageMagick的介面

47. 做一下比較：
MiniMagick documentation
這邊的MyUploader後面是CarrierWave::Uploader::Base
這邊是不能超過200X200

CarrierWave documentation on MiniMagick
這邊的AvatarUploader的後面也是CarrierWave::Uploader::Base
這邊是要放大到200X200

這邊的存檔的地方是在本地端的資料夾

48. fog把上傳的存在雲端
: Configuring the image uploader for production.