冒险村01 - Begin from linter(1)

01 - Begin from linter : rails_best_practices

好的开始,是成功的一半。

不管是前端、後端,当一个团队每个成员撰写程序的风格不同,对於维护、开发都相对会困难些。如果有个统一的规定,会一定程度提高专案开发效率。这类型的 tools 在每个程序都有相对应的 linter 可以使用。

这次开头第一篇就从名字很浅显易懂的 rails_best_practices 开始吧!一看就知道这个 gem 在做什麽(虽然说 官方网站 已经有点久没更新 & Github Commit 没什麽新的东西,但至少还是一个不错使用的工具,也在上个专案使用了约一年多左右)

gem install

  # Gemfile
  gem "rails_best_practices"

Usage

  # At the root directory of a Rails app
  bundle exec rails_best_practices

  # for HTML output
  bundle exec rails_best_practices -f html

以 User has_many post 的例子来看:

  # Schema
  create_table "posts", force: :cascade do |t|
    t.string "title"
    t.text "content"
    t.boolean "is_available"
    t.integer "user_id", null: false
    t.datetime "created_at", precision: 6, null: false
    t.datetime "updated_at", precision: 6, null: false
    t.index ["user_id"], name: "index_posts_on_user_id"
  end

  create_table "users", force: :cascade do |t|
    t.string "name"
    t.string "email"
    t.string "tel"
    t.datetime "created_at", precision: 6, null: false
    t.datetime "updated_at", precision: 6, null: false
  end

  # model
  # user.rb
  class User < ApplicationRecord
    has_many :posts
  end

  # post.rb
  class Post < ApplicationRecord
    belongs_to :user
  end

在 post index 页面中,假如想显示 Post 所有栏位 & 来自於哪个 User Name,可能会这样子写:

  # app/views/posts/index.html.erb
  <% @posts.each do |post| %>
    <tr>
      <td><%= post.title %></td>
      <td><%= post.content %></td>
      <td><%= post.is_available %></td>
      # User Name
      <td><%= post.user.name %></td>
    </tr>
  <% end %>

执行 bundle exec rails_best_practices 会发现出现 law of demeter 的错误讯息,原因其实就是出在 post.user.name 的部分

  /blog/app/views/posts/index.html.erb:22 - law of demeter

  Please go to https://rails-bestpractices.com to see more useful Rails Best Practices.

  Found 1 warnings.

可以写个 user_name 方法来呼叫关联 user 的 name,不过如果要显示 user 更多的其他栏位(e.g. email),等於要一直写更多的方法,这时候其实可以用 delegate 来做,相对於行数也比较短。

  # model
  # user.rb
  class User < ApplicationRecord
    has_many :posts
  end

  # post.rb
  class Post < ApplicationRecord
    belongs_to :user

    # (1) 
    def user_name
      user.name
    end

    def user_email
      user.email
    end

    # (2)
    delegate :name, :email, to: :user, prefix: true
  end

  # app/views/posts/index.html.erb
  <% @posts.each do |post| %>
    <tr>
      <td><%= post.title %></td>
      <td><%= post.content %></td>
      <td><%= post.is_available %></td>
      # User Name & Email
      <td><%= post.user_name %></td>
      <td><%= post.user_email %></td>
    </tr>
  <% end %>

透过 Delegate 来把 attributes 给关联的 model 来使用让逻辑更容易理解,更改後再跑一次就 No warning found,没问题啦!

Source Code: |=============================================================================================================================|

Please go to https://rails-bestpractices.com to see more useful Rails Best Practices.

No warning found. Cool!

RubyGems

参考来源

My blog



<<:  Day 16 self-attention的实作准备(二) 设定tensorflow和keras的环境

>>:  Day16 专有名词介绍 I

[自然语言处理基础] 文本预处理(I):断开文本的锁练

前言 上次我们提到原始文本往往夹带大量无意义的字符,於是我们利用了正则表达式来清理资料。然而此时的文...

【Side Project】 目标:网路订餐网站

作为软件工程师的我们应该都曾有过一个疑问,开始写程序之前,要不要先做规划。 这个问题也曾经困扰着我跟...

第12车厢-table界的神器!DataTables介绍篇(2)

延续上篇<第11车厢-table界的神器!DataTables介绍篇(1)>,今日再介...

[Day_2] Python 资料型别与变数

资料型别 以下给大家介绍一些常用的资料型别,如下 : 符号 说明 False 布林值False 0 ...

【Day 10】os模组

OS模组(Python内建) 说明 : os模组是一种与作业系统相关的模组,提供数十种与作业系统沟通...