12/08/2018, 16:40

5 Câu hỏi vui về Ruby on Rails

1. Sử dụng ActiveSupport::Concern Vấn đề được đưa rả ở đây là: Khi một đối tượng của bạn được tạo ra, nhưng có rất nhiều mối quan hệ với các đối tượng khác trước đó, có nhiều function được dùng liên quan tới nó. VD: Một đối tượng User, Post, Like được tạo ra, và đối tượng user được nhắc đến ở ...

1. Sử dụng ActiveSupport::Concern

Vấn đề được đưa rả ở đây là: Khi một đối tượng của bạn được tạo ra, nhưng có rất nhiều mối quan hệ với các đối tượng khác trước đó, có nhiều function được dùng liên quan tới nó.

VD: Một đối tượng User, Post, Like được tạo ra, và đối tượng user được nhắc đến ở cả 2 bảng đối tượng Post & Like thông qua attr created_by_id.

Khi đó chúng ta nhận ra rằng cả 2 đối tượng User vs Post đều cần dùng tới một thuộc tính chung là: belongs_to :created_by, class_name: User, foreign_key: :created_by_id

Đây là lúc chúng ta dùng tới ActiveSupport::Concern.

require 'active_support/concern'

module Concerns::Userable
  extend ActiveSupport::Concern

  included do
    belongs_to :created_by, class_name: User, foreign_key: :created_by_id
  end
end

và trong 2 model của Post & Like chúng ta chỉ cần thêm như sau:

class Post < ActiveRecord::Base
  include Concerns::Userable
end
class Like < ActiveRecord::Base
  include Concerns::Userable
end
  • Ưu điểm: trong phương pháp này chúng ta có thể tránh được DRY code trong 2 model. Dễ sửa chữa những phần chung giữa 2 model.
  • Nhược điểm: Tuy nhiên phương pháp này cũng có 1 nhược điểm là khi chúng ta lạm dụng cách này quá nhiều dự án của chúng ta sẽ có số lượng file tăng 1 các khổng lồ, có thể dẫn tới khó đọc + debug trong quá trình sau này.

2. Service object

Delegate cùng là 1 phần mình được học từ khi bắt đầu với ruby. Nó giúp giải quyết những vấn đề riêng biệt có tính chuyên môn riêng cho từng đối tượng. Ví dụ được đưa ra ở đây là: giả sử với 2 đối tượng Blog, Like như trên, bây giờ có 1 yêu cầu update lại tất cả created_by trong 2 đổi tượng trên. Khi nhận yêu cầu bạn sẽ nghĩ khi controller gọi đến nó thì tương luôn trong controller và gọi đến Blog.update_all: created_by: user_id.

Vẫn ngon =)). Tuy nhiên giờ lại có 1 yêu cầu mới là: "tao chỉ muốn sửa created_by của 1 số thằng thôi!!" Thôi lại sửa rồi.

khí đó mình nghĩ nó là 1 chức năng riêng rồi, và được dùng lại > 1 lần rồi vậy có thể cho vao module như trên nhỉ. Hoặc có 1 cách khác bạn có thể dùng đến service object trong ruby:(phần này được hướng dẫn rất nhiều trên viblo).

3. Cho 1 mảng số và tính tổng?

[1,2,3, 4,5,6,7,8,9] câu hỏi quá đơn giản khi nhận được chúng ta có rất nhiều cách. Cách 1: duyệt vòng for chạy từ đàu đến cuối mảng và cộng thêm vào biến tổng.

Cách 2: sử dụng inject trong ruby: array.inject(:+)

Cách 3: đơn giản nhất gọi luôn hàm sum trong ruby: array.sum

rất nhiều cách làm với câu hỏi này, tuy nhiên hãy chọn cách làm nhanh nhất và phù hợp nhất để đạt mục đích.

4. metaprogramming là gì?

câu này hơi cao siêu rồi, lúc đầu mình nghe chằng biết nó là cái gì cả và mãi mới nhớ tên + đọc hiểu code do thằng nào đó viết theo lối này rất khó chịu. Tuy nhiên nó lại là thứ đang được dùng rất nhiều trong ruby.

metaprogramming: theo mình gọi thì nó là: code sinh ra code.

Vâng khó hiểu quá. Chúng ta đi tới:

VD: giả sử User trên chúng ta có 1 trường là role và càn check quyền của nó. trong khi đó role có các quyền như: :admin, :edit, :reading

và cần check quyền này. Khi đó chúng ta sẽ có đoạn code sau:

def admin?
     role ==  'admin'
end

def edit?
    role == 'edit'
end

def reading?
   role == 'reading'
end

chuẩn rồi tuy nhiên để tránh DRY code thì metaprograming sẽ có thể giải quyết được như code:

['admin', 'edit', 'reading'].each do |role|
    define_method "#{role}?" do
        role == role
    end
end

đơn giản nhưng khó hiểu.

5. Instance method, Class method & private method?

3 thành phần được dùng rất nhiều của một đối tượng mà thường thì mình rất để ý đến(chỉ dùng thôi).

Chúng ta có vi dụ sau:

class User

    def talk
        puts about
    end

     private
     def about
         "Tôi là 1 user"
     end
     
     class  << self
          def talk
              puts "Tao là 1 user"
          end
     end
end

Vâng đối với User trên chúng ta gọi bằng cách sau sẽ có kết quả khác nhau:

User.new.talk => Tôi là 1 user
User.talk => Tao1 user
User.new.about => NoMethodError: private method
User.about => NoMethodError: undefined method

Với câu thư 1: chúng ta biêt được rằng chúng ta gọi đến method talk với vai trò là 1 Instance method nó là 1 thuộc tính của đối tượng. Với câu thư 2: cũng gọi đến talk tuy nhiên thằng được gọi đến lại không phải là một thuộc tính của đối tượng mà nó là 1 Class method. Với câu thư 3, 4: nó thì không được hiều là cái gì cả vì chúng ta không thể gọi từ bên ngoài mà gọi được 1 function private. Tuy nhiên ruby có hàm hỗ trợ đó là send || try(Bạn nên hạn chế dùng 2 thuộc tính này nếu không bắt buộc) . 2 method send & try thường được dùng trong phần 4 metaprogramming.

Kết:

Bài này mình lấy ý tưởng từ trang codementor và viết trên sự hiểu biết của mình. Trong đó còn 1 số câu rất thú vị hi vọng mọi người có thê đoc. Rất cảm ơn.

0