Ruby学习与Cocoapods

一. Ruby的调试

Ruby安装

Ruby Vs Python
  • Python的解析器实现更成熟,第三方库质量高。但是Ruby包管理更简单、方便。
  • Python的应用领域广泛。而Ruby目前主要局限在在Web领域与精致项目。
  • Python语法简单,Ruby更强大、灵活。
// 查看ruby版本
$ ruby --version
ruby 2.6.3p62 (2019-04-16 revision 67580) [universal.x86_64-darwin20]
Ruby Version Manager(rvm & rbenv)
  • rvm & rbenv是一种命令行工具,可让您轻松地安装,管理和使用多个Ruby环境。
  • 这两个工具本质都是 PATH 上做手脚,一个在执行前,一个在执行中。

如果你不需要维护特定版本的 Ruby 项目,那么只需要装一个比较新的 Ruby 版本 就行了。

// 查看ruby安装的版本列表,可以使用rvm管理ruby版本
$ rvm list
// 显示当前rvm能够管理的ruby版本,如果rvm版本过低,高版本的ruby是安装不了的
$ rvm list known
// 安装当前rvm能够管理的最新版本ruby
$ rvm install ruby --head
// 也可以使用下面命令,安装最新版ruby
$ brew install ruby

ruby学习

Ruby gem命令
  • 与大多数的编程语言一样,Ruby 也受益于海量的第三方代码库。
  • 这些代码库大部分都以 Gem 形式发布。 RubyGems 是设计用来帮助创建,分 享和安装 这些代码库的。
  • gem search -r/-f <gem>
  • gem install <gem> --version <num>
  • gem list
RubyGems Bundler

Bundler 能够跟踪并安装所需的特定版本的 gem,以此来为 Ruby 项目提供一 致的运行环境。

管理三方库

source 'https://rubygems.org' gem 'rails', '4.1.0.rc2'
gem ‘rack-cache'
gem 'nokogiri', '~> 1.6.1'

// 安装对ruby文本检查的库,如果要安装多个库,需要手动一个个去安装,使用Bundler可以管理多个三方库,Gemfile文件类似podfile文件
$ gem install rubocop

cocoapods模拟了ruby安装gems的过程。Podfile.lock文件里面记录了每次pod install之后安装三方库版本的信息。同样的Gemfile.lock文件记录了每次bundle install之后安装的三方库版本信息。

Ruby调试

// 启动ruby环境
$ irb
irb(main):001:0> puts "Gem1237"   //执行ruby打印语句进行调试
Gem1237
=> nil
irb(main):002:0> print "Gem1234"
Gem1234=> nil
irb(main):003:0> quit()

上面操作只是与ruby进行交互,并没有进行调试,如果执行pod install之后想要调试该怎么做?可以加puts打印输出进行调试,但是真正开发不可能这样一句句输出进行调试,所以就有了下面一些调试工具。

Ruby ruby-debug-ide gem
  • ruby-debug-ide提供了交互环境。和IDE(例如RubyMine,Visual Studio Code或 Eclipse)之间建立通信的协议。“ ruby -debug-ide”将命令从IDE重定向到调试器。然后它将从调试器收到的答案/事件返回给IDE。
Ruby debase
  • debase是针对Ruby 2.0的标准Ruby调试器debug.rb的快速实现。它是通过利用新的 Ruby TracePoint类实现的。核心组件提供了前端可以建立的支持。它提供断点处理, 堆栈信息等。
// 安装调试工具
$ gem install ruby-debug-ide
$ gem install debase

安装好上面两个工具,就可以在VS-Code中进行调试ruby。

cocoapods是ruby的三方代码库,这些三方库都是与ruby版本绑定在一块

版本间的gem库并不通用,比如当前ruby版本是2.6.3,那么切换到2.6.4版本,2.6.3版本的gem库就不能够使用了

$ ruby --version
ruby 2.6.3p62 (2019-04-16 revision 67580) [universal.x86_64-darwin20]
// solargraph库是根据前面ruby版本进行安装的
$ which solargraph
// cocoapods的安装也是通过gem命令安装到指定的ruby版本
$ gem info cocoapods

*** LOCAL GEMS ***

cocoapods (1.10.1, 1.8.4)
    Authors: Eloy Duran, Fabio Pelosin, Kyle Fuller, Samuel Giddins
    Homepage: https://github.com/CocoaPods/CocoaPods
    License: MIT
    Installed at (1.10.1): /Library/Ruby/Gems/2.6.0
                 (1.8.4): /Library/Ruby/Gems/2.6.0

    The Cocoa library package manager.
$ which pod
/usr/local/bin/pod

小结:三方库的安装与ruby版本一一对应,不同版本ruby下的三方库并不能在其他ruby版本中使用

使用VSCode打开01-Ruby学习代码

ruby编写

ruby不能像Xcode那样提示代码,必须借助VSCode相应的插件才能提示方法的编写以及介绍,这个插件是通过本机安装的一个gem,通过这个gem去访问网络才能获得方法的显示。这个gem就是solargraph

Ruby solargraph
  • solargraph是一种语言服务器,为Ruby提供智能感知,代码完成和内联文档。
安装`solargraph`用于代码提示
$ gem install solargraph
接下来我们来分析怎么进行ruby调试?
launch.json
  • 首先要在当前VSCode中创建一个launch.json文件,这个文件可以在VSCode中创建,也可以手动创建(如上图),拖入VSCode之后VSCode会自动读取该文件。launch.json文件控制当前代码编译
  • 在VSCode中执行调试,首先要安装Ruby插件
Ruby插件

Ruby插件用来跟本机安装的Ruby进行沟通

  • 接下来就是安装solargraph,同样跟本机安装的Ruby进行沟通
solargraph插件
  • 最后安装代码纠错插件Error Lens,判断当前代码是否有问题(该插件也可以选择不安装)
Error Lens插件
  • 最后我们来编写launch.json文件

按照json语法规则进行编写

{
  // https://github.com/rubyide/vscode-ruby/wiki/2.-Launching-from-VS-Code#available-vs-code-defined-variables
// 配置跟我们安装的ruby插件进行沟通
  "configurations": [
    {
    // 指定当前调试的名称
    "name": "Debug Ruby Code",
    // 输出调试信息
    "showDebuggerOutput": true,
    // 告诉VS Code要运行什么调试器。
    "type": "Ruby",
    // "launch"允许直接从VS Code启动提供的程序-或"attach"-允许您附加到远程调试会话。
    "request": "launch",
    // rdebug-ide在内运行bundler exec
    "useBundler": true,
    // 始终在入口处停止
    "stopOnEntry": false,
    // "program"的工作目录
    "cwd": "${workspaceRoot}", 
    // 指定调试脚本,调试当前打开的文件"program": "${file}"
    "program": "${file}",
    // 提供program命令参数
    "args": [],
    // 启动程序之前,提供要设置的环境变量
    // vscode shell 跟终端使用的shell环境不同,也就意味中终端安装了指定版本的三方库,在VSCode中并不生效
    "env": {
      "PATH": "/Users/ws/.rvm/gems/ruby-2.7.3/bin:/Users/ws/.rvm/gems/ruby-2.7.3@global/bin:/Users/ws/.rvm/rubies/ruby-2.7.3/bin:/Users/ws/.rvm/bin:/usr/local/opt/llvm@11/bin:/usr/local/opt/sqlite/bin:/usr/local/opt/openssl@1.1/bin:/usr/local/opt/openssl@1.1/bin:/usr/local/opt/ruby/bin:/Users/ws/thirdpartyLib/custom:/Users/ws/.yarn/bin:/Users/ws/.config/yarn/global/node_modules/.bin:/Users/ws/thirdpartyLib/jtool/jtool2:/usr/libexec/java_home:/Users/ws/thirdpartyLib/protobuf37/bin:/Users/ws/.pub-cache/bin:/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin:/Applications/VMware Fusion.app/Contents/Public:/Library/Apple/usr/bin",
      "GEM_HOME": "/Users/ws/.rvm/gems/ruby-2.7.3",
      "GEM_PATH": "/Users/ws/.rvm/gems/ruby-2.7.3:/Users/ws/.rvm/gems/ruby-2.7.3@global",
      "RUBY_VERSION": "ruby-2.7.3"
    }
    }
  ]
}

怎么解决VSCode shell环境与终端shell环境不同,导致终端安装的三方库不能在VSCode中使用的问题?

方案一:进入当前用户根目录 -> .vscode -> extensions -> 对应的ruby目录 -> dist -> server -> shims -> env.bin.zsh.sh

// 修改env.bin.zsh.sh文件前
#!/bin/zsh -i 
export 

// 修改env.bin.zsh.sh文件后
#!/bin/zsh -i -l
export

添加 -l 参数,指定去使用本机上面的shell环境

不推荐方案一,上面路径找起来太过麻烦

方案二:使用上面配置的环境变量

rvm管理我们的ruby是通过path,我们就可以使用env这个命令,给当前VSCode使用的shell环境设置path路径,包括GEM_HOME GEM_PATH RUBY_VERSION等参数

"env": {
      "PATH": "/Users/ws/.rvm/gems/ruby-2.7.3/bin:/Users/ws/.rvm/gems/ruby-2.7.3@global/bin:/Users/ws/.rvm/rubies/ruby-2.7.3/bin:/Users/ws/.rvm/bin:/usr/local/opt/llvm@11/bin:/usr/local/opt/sqlite/bin:/usr/local/opt/openssl@1.1/bin:/usr/local/opt/openssl@1.1/bin:/usr/local/opt/ruby/bin:/Users/ws/thirdpartyLib/custom:/Users/ws/.yarn/bin:/Users/ws/.config/yarn/global/node_modules/.bin:/Users/ws/thirdpartyLib/jtool/jtool2:/usr/libexec/java_home:/Users/ws/thirdpartyLib/protobuf37/bin:/Users/ws/.pub-cache/bin:/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin:/Applications/VMware Fusion.app/Contents/Public:/Library/Apple/usr/bin",
      "GEM_HOME": "/Users/ws/.rvm/gems/ruby-2.7.3",
      "GEM_PATH": "/Users/ws/.rvm/gems/ruby-2.7.3:/Users/ws/.rvm/gems/ruby-2.7.3@global",
      "RUBY_VERSION": "ruby-2.7.3"
    }

// 查看GEM_HOME等路径
$ echo $GEM_HOME
/Users/ws/.rvm/gems/ruby-2.7.3
快速获取Ruby env环境变量参数值

按照VSCode Ruby配置规则,输出env环境变量

printf "\n\"env\": {\n \"PATH\": \"$PATH\",\n \"GEM_HOME\": \"$GEM_HOME\",\n \"GEM_PATH\": \"$GEM_PATH\",\n \"RUBY_VERSION\": \”$RUBY_VERSION\"\n}\n\n"

指定使用ruby-2.7.3版本

获取环境变量env
下面进行ruby代码调试

首先上面所述的插件以及launch.json文件都已安装或配置

vscode中调试ruby
vscode中配置ruby

Code -> Preferences -> Settings,这里举例配置智能提示插件solargraph

配置Command Path
// 获取Command Path路径
$ which solargraph
vscode配置文件

二. Ruby语法

Rudy注释&打印.rb

ruby如果需要多行注释的话,推荐使用单行注释的方式,每一行前面加#

// 单行注释写法
# 单行注释

// 多行注释写法,=begin 和 =end 只能出现在第一行和最后一行,中间是注释内容
=begin

=end

ruby打印方式

// 第一种打印方式,打印结果会自动换行
puts 'ruby --version'

// 第二种打印方式,打印结果不会自动换行
print '1237'

rubu使用字符串的方式

// 第一种方式单引号
print '1237'

// 第二种方式双引号
a = '1234'
puts "Logic #{a}"  //注意 a 是一个变量,如果要想打印a,这里必须用双引号,单引号不会识别

ruby中执行shell的方式

// 使用 反引号 `,这里会打印出ruby的版本号
puts `ruby --version`
Rudy对象&符号&变量.rb
# 万物皆是对象
puts 3.class   //ruby中一个数字也是一个对象  Integer
puts '3'.class  // String
puts nil.class // NilClass

// 识别变量a,也可以使用 %Q,%q 使用的是单引号引用规则,而 %Q 是双引号引用规则
a = '1234'
puts "#{a}"
puts %Q(#{a})   // 1234
puts %q(#{a})   // #{a}

# 在一个双引号括起的字符串内,转义字符会被解析。在一个单引号括起的字符串内,转义字符不会被解析,原样输出。
puts %q(I can \n。)  // I can \n。
puts %(I can \n。)    // 第一行 I can  第二行 。

// 两个变量值相等,可以这样定义
a = b = '1237'

// 单引号内使用单引号转义字符
str = 'Won\'t you read O\'Reilly\'s book?'
puts str  //  Won't you read O'Reilly's book?

// ruby中定义使用变量,实际上是通过symbol(符号) 这种形式去访问,所有底层对象在ruby中都是结构体,ruby中也有符号表 symbol table
// 定义符号 a
:cat
puts :cat.class  // Symbol

// 定义变量c等于:a 符号  # symbol是唯一的,只要名称相同就代表相同的符号
c = :cat
puts c == :cat  // true
puts c == :'cat'  // true

// 符号转字符串, 字符串转符号
puts c.to_s
puts 'cat'.to_sym

// 符号是唯一的,意味着符号的哈希值是相同的
puts c.object_id
puts :cat.object_id

// 打印相同字符串的id,发现每次都不同
puts 'cat'.object_id
puts 'cat'.object_id

// 通过符号找到具体定义的变量或者方法
puts "Hello".method(:class)  //打印出string里面的class方法 #Method:String(Kernel)#(class)>
puts "Hello".method(:class).class  // Method

小结
Ruby Symbol

  • Ruby 是一个强大的面向对象脚本语言,一切皆是对象
  • 在 Ruby 中 Symbol 表示“名字”,比如字符串的名字,标识符的名字。
  • 创建一个 Symbol 对象的方法是在名字或者字符串前面加上冒号:
  • 在 Ruby 中每一个对象都有唯一的对象标识符(Object Identifier)
  • 对于 Symbol 对象,一个名字唯一确定一个 Symbol 对象
  • Ruby 内部一直在使用 Symbol,Ruby内部也存在符号表
  • Symbol 本质上是一个数字,这个数字和创建 Symbol 的名字形成一对一的映射;而String 对象是一个重量级的 用C结构体表示的家伙,因此使用 Symbol 和 String 的开销相差很大。
  • 符号表是一个全局数据结构,它存放了所有 Symbol 的(数字ID,名字)。 Ruby 不会从中删除 Symbol ,因此 当你创建一个 Symbol 对象后,它将一直存在,直到程序结束。
Rudy中的操作符.rb
puts 1 + 1 #=> 2
puts 8 - 1 #=> 7
puts 10 * 2 #=> 20
puts 35 / 5 #=> 7
puts 2**5 #=> 32   // 表示2的5次方
puts 5 % 3 #=> 2

puts 3 & 5 #=> 1
puts 3 | 5 #=> 7
puts 3 ^ 5 #=> 6

// 3.获取对象,3.+表示对象调用+方法,后面(3)表示调用+方法传的参数
puts 3.+(3)      puts 3.+ 3  // 也可以通过空格分隔传递参数

puts !!nil   #=> false
puts !!false #=> false
puts !!0     #=> true
puts !!""    #=> true

# 组合比较运算符
# 返回1,第一个参数大
# 返回0,两个参数相等
# 返回-1,右边参数大
puts 1 <=> 10  // 1通过组合运算符和10进行比较,这里返回 -1

# and 左侧执行成功,继续执行右侧
(1 < 0) and (puts "mm")
# or 左侧执行失败,继续执行右侧
(1 < 0) or (puts "cc")
Rudy中的String.rb
cat = 'cat'
# 默认encode方式utf-8,也可以指定当前ruby文件的encode格式
puts cat.encoding.name
# 非破坏性,指定encode格式,encode名称不会发生改变
newStr = cat.encode!('ISO-8859-1')
puts cat.encoding.name
# 破坏性,指定encode格式,encode名称会发生改变
cat.force_encoding('ISO-8859-1')
puts cat.encoding.name

// 遍历字符串中的每一个字符,||定义每次循环遍历过程中传递的参数,这里打印的是每个字符的ASCII值
newStr.each_byte do |byte|
    puts byte
end
// 简写形式
newStr.each_byte { | byte |
    puts byte
}

# 拼接字符串
puts 'hello ' + 'world' #=> "hello world"
puts 'hello ' + 3.to_s #=> "hello 3"    //Integer对象转字符串类型

# 通过左移<<,拼接一个对象,只要对象能转成字符串就可以
puts 'hello' << ' world'
puts 'hello' << newStr

# 重复输出指定字符串n次
puts 'hello ' * 3 #=> "hello hello hello"

# =~ 返回匹配到到字符的索引(如果没有匹配,则返回nil),两个/表示开启正则
puts 'Cat' =~ /[t]/

# 格式化字符串
puts format('%05d', 123)
puts format("%-5s: %08x #{cat}", 'ID', 44)

# 首字母大写
puts cat.capitalize
# ? !操作符与Swift是不一样的
# ?返回的是一个 布尔值
puts cat.empty?
puts "123" == "123"
# !具有破坏性,改变了对象的结构
puts "123".eql?("123")

# "cat"字符串中通过正则匹配出的字符,使用'b'来替换,注意ruby的语法不能像Xcode那样点进去查看,只能通过安装插件来查看方法说明信息
puts cat.sub(/[a]/, "b")

// 如果看到ruby正常执行,后面报了错,vscode启用了server去跟ruby进行沟通的时候有一定的时差,可以使用sleep来避免
sleep 1

ruby语法文档

Rudy中的分支判断&循环&集合类型.rb
<!-- 数组相关 -->
array = [1, 2, 3, 4, 5] // 也可以使用 Array.new创建新数组

# u数组可以包含多种数据类型
[1, 'hello', false]

# %r() 是写正则表达式的另一种方式。
# %q() 是写单引号字符串的另一种方式(可以是多行,这很有用)
# %Q() 给出双引号字符串
# %x() 是一个shell命令
# %i() 给出一个符号数组(Ruby> = 2.0.0)
# %s()变成foo符号(:foo)
# %w写一个用空格而不是逗号分隔且不带引号的字符串数组
puts %w[1 2 3]

puts array[0] #=> 1
puts array.first #=> 1
puts array[12] #=> nil    // 数组越界不会报错
puts array[-1] #=> 5    // 从后往前取最后一个
puts array.last #=> 5

# 指定 index 和 length...
puts array[2, 3] #=> [3, 4, 5]

# 指定range
puts array[1..3] #=> [2, 3, 4]

# 逆转数组
puts [1, 2, 3].reverse #=> [3,2,1]

# 万物皆是对象
puts array.[] 0  puts array.[](0) // 通过这种方式取数组第一个数据

# 添加到数组
array << 6 #=> [1, 2, 3, 4, 5, 6]
array.push(6) #=> [1, 2, 3, 4, 5, 6]

# 判断数据是否存在?
puts array.include?(1) #=> true   // puts array.include? 1 也可以这样写

<!-- 字典相关 -->
# dictionary
hash = { 'color' => 'green', 'number' => 5 }
hash.keys #=> ['color', 'number']

hash['color'] #=> "green"
hash['number'] #=> 5
#也可以使用symbol符号作为key
hash = { :defcon => 3, :action => true }
hash.keys #=> [:defcon, :action]

hash = { defcon: 3, action: true }
hash.keys #=> [:defcon, :action]

# 是否存在key和value
hash.key?(:defcon) #=> true
hash.value?(3) #=> true

<!-- 分支判断 -->
if true
    puts 'if statement'
  elsif false
    puts 'else if, optional'
  else
    puts 'else, also optional'
end
// 也可以把if放在后面进行条件判断,unless取反
warnings = ['Patronimic is missing', 'Address too short']
puts("Some warnings occurred:\n" + warnings.join("\n"))  if !warnings.empty?
puts("Some warnings occurred:\n" + warnings.join("\n"))  unless warnings.empty?

<!-- 循环 -->
# 在ruby中,for循环不常见,大都使用block闭包
for counter in 1..5
    puts "iteration #{counter}"
end

# block 闭包
(1..5).each do |counter|
    puts "iteration #{counter}"
end
(1..5).each { |counter|
    puts "iteration #{counter}"
}

# 需要index和value同时存在
array.each_with_index do |element, index|
    puts "#{element} is number #{index} in the array"
end
# while循环
counter = 1
while counter <= 5 do
    puts "iteration #{counter}"
    counter += 1
end

#  'map', 'reduce'等
array = [1,2,3,4,5]
#ruby中没有return语句
doubled = array.map { |element|
     element * 2
}

# 转小写
a = ["FOO", "BAR", "BAZ"]
a.map { |s| s.downcase }
# 也可以这样写
# 通过&符号控制对每个元素执行等方法
a.map(&:downcase)

# 转大写
upcased = ['Watch', 'these', 'words', 'get', 'upcased'].map(&:upcase)

# 把所有数字相加
sum = [1, 2, 3, 4, 5].reduce(&:+)
puts sum

# 分支
grade = 'B'

case grade
when 'A'
    puts 'Way to go kiddo'
when 'B'
    puts 'Better luck next time'
when 'C'
    puts 'You can do better'
when 'D'
    puts 'Scraping through'
when 'F'
    puts 'You failed!'
else
    puts 'Alternative grading system, eh?'
end

# 分支和range
grade = 82
case grade
when 90..100
    puts 'Hooray!'
when 80...90
    puts 'OK job'
else
    puts 'You failed!'
end
Rudy中的异常处理.rb
# Exception handling
begin
    # Code here that might raise an exception
    raise NoMemoryError, '内存异常.'    // 抛出异常
  rescue RuntimeError => other_exception_variable  // 捕获异常
    puts 'RuntimeError异常'
  else
    puts '没有异常'
  ensure
    puts '不管有没有异常'
end
Rudy中的方法与闭包.rb
# Methods
# 没有return关键字,传递参数可以使用括号,也可以不用
def double(x)
  x * 2
end
puts double(2) #=> 4
puts double 3 #=> 6
# 调用了两次double方法
puts double double 2

def sum(x, y)
  x + y
end
# 多参数通过,分割
sum 3, 4 #=> 7
puts sum sum(3, 4), 5 #=> 12


# 传递一个block,# yield类似c语言函数指针
def logic
  puts '{'
  yield
  puts '}'
end
logic { puts 'Cat1 1237' }

# Block可以被包装成一个`Proc`对象
# &表示这里传递的是一个`Proc`对象
def guests(&block)
  puts block.class #=> Proc
  puts block.call(4)
end
guests { |n| puts "Cat --#{n}" }

# 传递一组参数
def guess(*arr)
  arr.each { |guest| puts guest }
end
guess %w[Cat Kody cooci]

# 根据数组自动创建对象
a, b, c = ['Cat', 'Kody', 'Cooci']
puts a
puts b
puts c

cat = ["C", "g", "b", "m", "o"]
def get(first, second, third)
  puts "#{first}---#{second}---#{third}"
end
# 通过*获取指定数组,从cat数组中获取前三个元素作为一个子数组给get方法
get(*cat.first(3))

def get1(first, second, third, *other)
  puts "#{first}---#{second}---#{third}"
  puts other.count.to_s   // 打印2
end
get1(*cat)

# 演示破坏性
cat = 'Cat'
puts cat.upcase     // 到这里还没有被破坏
puts cat.upcase!   // 已经被破坏
puts cat   // Cat变成了CAT,已经被破坏
Rudy中的类与继承.rb

下面定义一个ruby类,以及set,get方法

class Logic
  # @@声明类变量
  @@sch = "Login" 
  # @声明成员变量
  @s = "Login"
  # init方法
  def initialize(name, age = 0)
    # 初始化,实例变量
    @name = name
    @age = age
  end
  # setter 
  def name=(name)
    @name = name
  end

  # getter
  def name
    @name 
  @end
end

上面定义比较麻烦,ruby中有自己的set get定义方式

class Logic
  @@sch = 'Cat123'
  def initialize(name, age = 0)
    @name = name
    @age = age
  end
  #自动帮我们生成setter getter方法
  attr_accessor :name
  # 生成getter方法
  attr_reader :name
  # 生成setter方法
  attr_writer :name

  # 定义类方法
  def self.say(n)
    puts n
  end
  # 定义实例方法
  def school 
    @@sch 
  end
end

lg = Logic.new('cat')
puts Logic.say('mm')
lg.name = "Bob"
push lg.name

#  $ 全局变量
$var = "I'm a global var"
puts defined? $var #=> "global-variable"

# 实例变量
@var = "I'm an instance var"
puts defined? @var #=> "instance-variable"

# 类实例变量
@@var = "I'm a class var"
puts defined? @@var #=> "class variable"

# 以大写字母开头的变量是常量。
Var = "I'm a constant"
puts defined? Var #=> "constant"

# 类变量在类及其所有后代之间共享
class Logic
  @@species = 'Cat123'
  @cooci = '123'
  def initialize(name, age = 0)
    @name = name
    @age = age
  end

  attr_accessor :name

  def self.say(_n)
    puts @cooci
  end

  def speec
    puts 'Kody'
  end

  def self.species
    puts @@species
  end
end

# 派生类
class Cat < Logic
end

Cat.species
Logic.species

# 实例变量不共享
class Kody < Logic
end

Logic.say('m')
Kody.say('n')

module ModuleExample
  def foo
    'foo'
  end
end

# Including modules 绑定到类的实例
# Extending modules 绑定到类本身

class Person
  include ModuleExample
end

# Person.foo
puts Person.new.foo

三. Cocoapods调试

上面的配置都是在vscode中进行,其实还需要我们在当前目录配置Gemfile文件,去告诉vscode我们当前项目使用了哪些gem

// Gemfile内容如下
source 'https://rubygems.org'
// 这两个是Gemfile文件必备的
gem 'ruby-debug-ide'
gem 'debase'
// 如果不配置rexml,会报代码库的错误
gem 'rexml'
ruby调试步骤
  • 首先在ruby调试代码目录里面创建Gemfile文件,配置内容如上,给Bundle使用
// 执行下面命令,以安装Gemfile文件中的gem库,执行完成会生成一个 Gemfile.lock文件,gem库都安装在当前ruby的gem目录
$ bundle install
// 也可以安装到当前调试目录,不推荐使用
$ bundle install --local
  • .vscode虚拟目录下配置launch.json文件
cocoapods调试步骤
  • 首先从github下载cocoapods源码
// 查看cocoapods版本
$ pod --version
1.10.1
// 进入下载的cocoapods目录
$ cd /Users/wn/Documents/资料/02-cocoapods调试/CocoaPods
// 指定cocoapods版本号
$ git checkout 1.10.1
HEAD is now at be85d4da1 Release 1.10.1
  • 准备cocoapods生成的工程
  • 创建Gemfile文件,内容如下
source 'https://rubygems.org'

gem 'cocoapods', path: './CocoaPods'
gem 'ruby-debug-ide'
gem 'debase'
  • 通过vscode配置launch.json文件,内容如下
{
  "configurations": [
    {
    "name": "Debug CocoaPods Plugin",
    "showDebuggerOutput": true,
    "type": "Ruby",
    "request": "launch",
    "useBundler": true,
    "cwd": "${workspaceRoot}/TestLibrary", // pod 命令执行的路径
    "program": "${workspaceRoot}/CocoaPods/bin/pod",
    "args": ["install"], // `pod` 命令的参数
    "env": {
      "PATH": "/Users/ws/.rvm/gems/ruby-2.6.0/bin:/Users/ws/.rvm/gems/ruby-2.6.0@global/bin:/Users/ws/.rvm/rubies/ruby-2.6.0/bin:/Users/ws/.rvm/bin:/usr/local/opt/llvm@11/bin:/usr/local/opt/sqlite/bin:/usr/local/opt/openssl@1.1/bin:/usr/local/opt/openssl@1.1/bin:/usr/local/opt/ruby/bin:/Users/ws/thirdpartyLib/custom:/Users/ws/.yarn/bin:/Users/ws/.config/yarn/global/node_modules/.bin:/Users/ws/thirdpartyLib/jtool/jtool2:/usr/libexec/java_home:/Users/ws/thirdpartyLib/protobuf37/bin:/Users/ws/.pub-cache/bin:/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin:/Applications/VMware Fusion.app/Contents/Public:/Library/Apple/usr/bin",
      "GEM_HOME": "/Users/ws/.rvm/gems/ruby-2.6.0",
      "GEM_PATH": "/Users/ws/.rvm/gems/ruby-2.6.0:/Users/ws/.rvm/gems/ruby-2.6.0@global",
      "RUBY_VERSION": "ruby-2.6.0"
    }
    }
  ]
}
整个工程目录
  • 整个工程拖入vscode中进行查看
pod install 实际执行的文件

这个时候就可以在install.rb文件内打断点进行调试,查看pod执行的过程以及打印信息

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,271评论 5 476
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,275评论 2 380
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,151评论 0 336
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,550评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,553评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,559评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,924评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,580评论 0 257
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,826评论 1 297
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,578评论 2 320
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,661评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,363评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,940评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,926评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,156评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,872评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,391评论 2 342

推荐阅读更多精彩内容