冒险村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

Android Studio Mac 版本 git log 中文无法显示

打开Preference,选择 Appearance & Behavior 勾选 Use c...

连续 30 天 玩玩看 ProtoPie - Day 19

ProtoPie 其实也有一些我这次可能玩不到的部分。 也就是企业方案。(还是我 Request ...

[Day26] Micro Services

在前几天的 App Engine 与 K8S 中,或许我已经大致的提过 Micro Services...

Day 29 - 计算均线资料

本篇重点 在SQLite的Table中,新增栏位 透过pandas.DataFrame.rollin...

[DAY2] 听说 Rails 开发很快速?

先来介绍一点关於 Ruby on Rails 这个框架 ,他采用了 ORM 来处理 Ruby 和资料...