馬克的程式架構筆記

為了創造有價值的產品,想法、實作架構、行銷有同等的重要性

Rails Service層的使用時機

在Rails 102的作業中,有一段code自已覺得很醜,請教了一下xdite大:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
  def create_comment
    @post = Post.find(params[:id])
    comment = @post.comments.create(comment_params)
    comment.author = current_user

    if comment.save
      #取得所有人的email 去掉重覆的和自已的
      emails = @post.comments.map{ |x| x.author.email}
      emails_add_posts = emails + [@post.author.email]
      uniq_emails = emails_add_posts.uniq{|x| x}
      uniq_emails_delete_self = uniq_emails - [comment.author.email]

      PostMailer.sendmessage(uniq_emails_delete_self,@post, comment.comment).deliver
      redirect_to post_path(@post)
    else
      render :show
    end
  end

這個action主要的用途是用於在留言,而留言完成後需要寄信通知其他不重覆的回應者(不包括自已)

1
2
3
4
5
      #取得所有人的email 去掉重覆的和自已的
      emails = @post.comments.map{ |x| x.author.email}
      emails_add_posts = emails + [@post.author.email]
      uniq_emails = emails_add_posts.uniq{|x| x}
      uniq_emails_delete_self = uniq_emails - [comment.author.email]

這段code照了我想像的邏輯處理,但它不適合寫在controller裡面,Controller原本就只需處理由model取得資料—將資料展現在View這樣的動作,其餘額外的動作應該另外開一層Service。

於是就來把services目錄做出來

1
2
cd yourproject/app
mkdir services

rails已經幫你預先載入這個路徑下的檔案了,所以裡面新增的程式都可以在controller下呼叫

1
vi yourproject/app/services/post_mailer_service.rb

加入以下內容

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
class PostMailerService
  def initialize
  end

  #取得應收到訊息的email list
  #去掉重覆的和自已的
  def send_email_to_other_people(post,comment)
      emails = post.comments.map{ |x| x.author.email}
      emails_add_posts = emails + [post.author.email]
      uniq_emails = emails_add_posts.uniq{|x| x}
      uniq_emails_delete_self = uniq_emails - [comment.author.email]

      PostMailer.sendmessage(uniq_emails_delete_self,post, comment.comment).deliver
  end
end

原本的程式改為

1
2
3
4
5
6
7
8
9
10
...
    if comment.save

      PostMailerService.new().send_email_to_other_people(@post,comment)

      redirect_to post_path(@post)
    else
      render :show
    end
...

這樣雖然還不能說很漂亮,但已經達到我們要把不相關的邏輯由controller拆分出來的目的了。

參考文件 http://yedingding.com/2013/03/04/steps-to-refactor-controller-and-models-in-rails-projects.html

Comments