欢迎访问 生活随笔!

生活随笔

当前位置: 首页 >

ActiveSupport::Concern 和 gem 'name_of_person'(300✨) 的内部运行机制分析

发布时间:2023/11/30 52 豆豆
生活随笔 收集整理的这篇文章主要介绍了 ActiveSupport::Concern 和 gem 'name_of_person'(300✨) 的内部运行机制分析 小编觉得挺不错的,现在分享给大家,帮大家做个参考.

理解ActiveRecord::Concern:

参考:include和extend的区别:

https://www.cnblogs.com/chentianwei/p/9408963.html

 

传统的模块看起来像:

module Mdef self.included(base) # base(一个类)扩展了一个模块"ClassMethods", base的类方法就包含了"ClassMethods"模块中的方法。base.extend ClassMethods # base添加了一个:disabled方法。base.class_eval doscope :disabled, -> { where(disabled: true) }endendmodule ClassMethods...end end

 

使用ActiveSupport::Concern:

 

require 'active_support/concern'module M# M扩展了模块Concern,可以使用Concern的方法。 extend ActiveSupport::Concern# 当M被一个类包括后,这个类就可以使用块内的方法了。 included doscope :disabled, -> { where(disabled: true) }end# 当M被一个类包括后,这个类的类方法就扩展了,?的方法就作为类方法使用。 class_methods do...end end

 

gem 'name_of_person'

一个小的gem,为英文网站用户的注册名字添加了很多调用的方法。

https://github.com/basecamp/name_of_person/tree/master/lib/name_of_person

  • 加载了gem后,
  • ActiveRecord::Base包含了模块HasPersonName, 就可以使用lib/name_of_person/has_person_name.rb中的方法:类方法has_person_name.
  • 在Rails app中, app/model/user.rb, 使用has_person_name方法后,就include包含了模块Assignable。 User的实例就新增了2个实例方法,这两个方法会调用模块PersonName中的方法
    • @user.name=: 调用PersonName.full(name)方法,@user的first_name, last_name属性被分配值。
    • @user.name:  返回一个PersonName.new对象,这个对象可以使用:
      • full | initials | familiar 等定义在模块PersonName中的方法。
      • first | last

    使用方法:

    1 . User类必须包括first_name, last_name2个属性,添加validates :first_name, :last_name, presence: true

    2. 当实例化一个@user时,代码内部调用name= 方法为first_name, last_name属性分配值!

    (这里不是很理解,是否是devise这个gem,当发现必须验证first_name, last_name后,自动调用name=方法?)

    3. 之后通过@user.name.xxx就可以使用不同的名和姓的组合。

     

    分析:先看三张图:

    图2

     

     

    图3:

     

     

     

    @user.name的内部运行机制:

    首先是一个判断:

    if @user.first_nameNameOfPerson::PersonName.new(@user.first_name, @user.last_name) end

    如果first_name存在,则新增一个PersonName对象,调用initialize方法

    def initialize(first, last = nil)raise ArgumentError, "First name is required" unless first.present?@first, @last = first, lastsuper fullend

    然后调用full这个方法,进行if判断

    def full@full ||= last.present? ? "#{first} #{last}" : firstend
    分析:
    如果@user.last_name存在(last.present?),则 把@user的两个name属性合并,并分配给@full对象。

    最后返回一个PersonName对象实例, 内部包括@first, @full, 及@last(根据@user决定是否存在)

     

    @user.name = "Dav Tom"内部运行分析:

    def name=(name)full_name = NameOfPerson::PersonName.full(name)self.first_name, self.last_name = full_name.try(:first), full_name.try(:last)end

     

    首先:调用模块PersonName的类方法full。

    • 把传入的字符串参数分成first, last变量
    • 如果first变量存在,则新建一个PersonName对象
    • 之后的分析和@ueser.name相同。 
    def self.full(full_name)first, last = full_name.to_s.strip.split(/\s+/, 2)new(first, last) if first.present?end

     

    转载于:https://www.cnblogs.com/chentianwei/p/9829164.html

    总结

    以上是生活随笔为你收集整理的ActiveSupport::Concern 和 gem 'name_of_person'(300✨) 的内部运行机制分析的全部内容,希望文章能够帮你解决所遇到的问题。

    如果觉得生活随笔网站内容还不错,欢迎将生活随笔推荐给好友。