分享

[Rails][notes] Refactoring官網閱讀紀錄[6]

記錄自己官網文件閱讀的注釋與筆記
主要也是訓練自己閱讀英文挑戰
https://guides.rubyonrails.org/getting_started.html
注釋 rails Concerns

Image by 2211438 from Pixabay

8 Refactoring

我們已經有了 article 跟comment 兩個功能 ,現在我們來看看app/views/articles/show.html.erb 一個冗長的頁面,因此我們來對
它進行改造

8.1 Rendering Partial Collections

首先我們將評論的部分取出,建立檔案app/views/comments/_comment.html.erb
  

<p>

  <strong>Commenter:</strong>

  <%= comment.commenter %>

</p>


<p>

  <strong>Comment:</strong>

  <%= comment.body %>

</p>

然後修改app/views/articles/show.html.erb
  

<h1><%= @article.title %></h1>


<p><%= @article.body %></p>


<ul>

  <li><%= link_to "Edit", edit_article_path(@article) %></li>

  <li><%= link_to "Destroy", article_path(@article),

                  method: :delete,

                  data: { confirm: "Are you sure?" } %></li>

</ul>


<h2>Comments</h2>

<%= render @article.comments %>


<h2>Add a comment:</h2>

<%= form_with model: [ @article, @article.comments.build ] do |form| %>

  <p>

    <%= form.label :commenter %><br>

    <%= form.text_field :commenter %>

  </p>

  <p>

    <%= form.label :body %><br>

    <%= form.text_area :body %>

  </p>

  <p>

    <%= form.submit %>

  </p>

<% end %>

透過<%= render @article.comments %>將app/views/comments/_comment.html.erb渲染回來
透過@article.comments收集每一篇評論組成一個格陣列,當作引述傳入
render將會遍歷這個陣列。

8.2 Rendering a Partial Form

接著建立檔案app/views/comments/_form.html.erb將新增
評論的部分移到這個檔案
  

<%= form_with model: [ @article, @article.comments.build ] do |form| %>

  <p>

    <%= form.label :commenter %><br>

    <%= form.text_field :commenter %>

  </p>

  <p>

    <%= form.label :body %><br>

    <%= form.text_area :body %>

  </p>

  <p>

    <%= form.submit %>

  </p>

<% end %>

app/views/articles/show.html.erb改為
  

<h1><%= @article.title %></h1>


<p><%= @article.body %></p>


<ul>

  <li><%= link_to "Edit", edit_article_path(@article) %></li>

  <li><%= link_to "Destroy", article_path(@article),

                  method: :delete,

                  data: { confirm: "Are you sure?" } %></li>

</ul>


<h2>Comments</h2>

<%= render @article.comments %>


<h2>Add a comment:</h2>

<%= render 'comments/form' %>

Rails 很聰明會意識到你要渲染的檔案室app/views/comments下的
_from.html.erb。
而@article 是一個實體變數可以供view的每一個部分使用

8.3 Using Concerns

Concerns是一個讓開發者更容易管理、了解及建立大型的
controllers or models。
他的優點是提供多個models 或 controllers 共享及重用相同的Concerns。
Concerns 透過實作可包含modles 或是 controller的方法模組化。
也就是說將多個model 或是controller 會共用的的方法 打包成一個檔案。
你可以在你的controller 或modle 中使用concerns就像使用module一樣。
在開始建立rails 專案時Rails 幫我們建立了以下兩個檔案
  

app/controllers/concerns

app/models/concerns

如果要給定BLOG文章具有這種狀態,例如該文章是公開的或是隱藏的該文章是公開的或是隱藏的又或著該篇文章封存了,評論也可能是隱藏的或是可見的。
我們可以替文章的資料表增加一個欄位為status ,透過建立一個migration添加後欄位狀態 model 如下:
加入 migration
  

bin/rails generate migration AddStatusToArticles status:string

bin/rails generate migration AddStatusToComments status:string


  

class Article < ApplicationRecord

  has_many :comments


  validates :title, presence: true

  validates :body, presence: true, length: { minimum: 10 }


  VALID_STATUSES = ['public', 'private', 'archived']


  validates :status, inclusion: { in: VALID_STATUSES }


  def archived?

    status == 'archived'

  end

end

而評論model的如下
  

class Comment < ApplicationRecord

  belongs_to :article


  VALID_STATUSES = ['public', 'private', 'archived']


  validates :status, inclusion: { in: VALID_STATUSES }


  def archived?

    status == 'archived'

  end

end

之後我們便可以在index樣板(app/views/articles/index.html.erb)使用
archived? 這個方法來顯示屬於該狀態的文章
  

<h1>Articles</h1>


<ul>

  <% @articles.each do |article| %>

    <% unless article.archived? %>

      <li>

        <%= link_to article.title, article %>

      </li>

    <% end %>

  <% end %>

</ul>


<%= link_to "New Article", new_article_path %>



如此你可以在看一次前兩個model中包含了一個重複的archived?
這時concern就派上用場了。
建立一個檔案app/models/concerns/visible.rb
我這裡先稱呼這個module叫做Visible
  

module Visible

  def archived?

    status == 'archived'

  end

end

這裡我可以將驗證也放入這個module,但會稍微複雜的是驗證是屬於類別調用方法,因此我們提供一個方法調用ActiveSupport::Concern (API Guide)
  

module Visible

  extend ActiveSupport::Concern


  VALID_STATUSES = ['public', 'private', 'archived']


  included do

    validates :status, inclusion: { in: VALID_STATUSES }

  end


  def archived?

    status == 'archived'

  end

end

現在我們可以將model中重複的邏輯刪除並將Visible包括進來
如下app/models/article.rb
  

class Article < ApplicationRecord

  include Visible

  has_many :comments


  validates :title, presence: true

  validates :body, presence: true, length: { minimum: 10 }

end

app/models/comment.rb:
  

class Comment < ApplicationRecord

  include Visible

  belongs_to :article

end

類別方法也可以放入concerns。如果我們要顯示計算公開文章或評論的數量
我們可以加入類別方法如下
  

module Visible

  extend ActiveSupport::Concern


  VALID_STATUSES = ['public', 'private', 'archived']


  included do

    validates :status, inclusion: { in: VALID_STATUSES }

  end


  class_methods do

    def public_count

      where(status: 'public').count

    end

  end


  def archived?

    status == 'archived'

  end

end

然後在view 你可以呼叫類別方法如下
  

<h1>Articles</h1>


Our blog has <%= Article.public_count %> articles and counting!


<ul>

  <% @articles.each do |article| %>

    <li>

      <%= link_to article.title, article %>

    </li>

  <% end %>

</ul>


<%= link_to "New Article", new_article_path %>

我們需要在controller 中加入:status的寫入許可
app/controllers/articles_controller.rb:
  

private

    def article_params

      params.require(:comment).permit(:commenter, :body, :status)

    end

app/controllers/comments_controller.rb:
  

private

    def comment_params

      params.require(:comment).permit(:commenter, :body, :status)

    end

這將就完成後端功能接著我們在表單加入 新增或修改這些狀態的欄位
app/views/articles/_form.html.erb
  

<div>

  <%= form.label :status %><br>

  <%= form.select :status, ['public', 'private', 'archived'], selected: 'public' %>

</div>

app/views/comments/_form.html.erb:
  

<p>

  <%= form.label :status %><br>

  <%= form.select :status, ['public', 'private', 'archived'], selected: 'public' %>

</p>

這樣就完成了這部分的重構了
#注釋  #rails  #Concerns 
分類:學習

評論
上一篇
  • [Rails][notes] Second Model官網閱讀紀錄[5]
  • 下一篇
  • [Rails][notes]刪除評論與簡易的身份認證-官網閱讀紀錄[7]
  • 更多文章
    載入中... 沒有更多了