惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

Forbes - Security
Forbes - Security
L
Lohrmann on Cybersecurity
Simon Willison's Weblog
Simon Willison's Weblog
P
Proofpoint News Feed
P
Privacy International News Feed
The Hacker News
The Hacker News
AWS News Blog
AWS News Blog
S
Securelist
P
Proofpoint News Feed
Recent Announcements
Recent Announcements
GbyAI
GbyAI
B
Blog RSS Feed
A
About on SuperTechFans
C
CXSECURITY Database RSS Feed - CXSecurity.com
Y
Y Combinator Blog
Microsoft Azure Blog
Microsoft Azure Blog
H
Hackread – Cybersecurity News, Data Breaches, AI and More
Cyberwarzone
Cyberwarzone
I
Intezer
T
Tor Project blog
T
The Blog of Author Tim Ferriss
The GitHub Blog
The GitHub Blog
云风的 BLOG
云风的 BLOG
Recorded Future
Recorded Future
aimingoo的专栏
aimingoo的专栏
Cisco Talos Blog
Cisco Talos Blog
Cyber Security Advisories - MS-ISAC
Cyber Security Advisories - MS-ISAC
钛媒体:引领未来商业与生活新知
钛媒体:引领未来商业与生活新知
W
WeLiveSecurity
D
DataBreaches.Net
U
Unit 42
Project Zero
Project Zero
Martin Fowler
Martin Fowler
V
V2EX
The Last Watchdog
The Last Watchdog
Security Archives - TechRepublic
Security Archives - TechRepublic
C
Cisco Blogs
Threat Intelligence Blog | Flashpoint
Threat Intelligence Blog | Flashpoint
K
KPMG report finds enterprise disconnect between AI and its ROI | CIO
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
V2EX - 技术
V2EX - 技术
Hacker News - Newest:
Hacker News - Newest: "LLM"
T
Threat Research - Cisco Blogs
cs.CV updates on arXiv.org
cs.CV updates on arXiv.org
T
Tenable Blog
F
Full Disclosure
T
The Exploit Database - CXSecurity.com
H
Heimdal Security Blog
Latest news
Latest news
Webroot Blog
Webroot Blog

Ruby

一個用 DIDComm 實現服務器間通信的 Rails demo - V2EX RubyConf China 2024 参会报告 - Day 1 - V2EX 有对 Ruby 感兴趣的吗? - V2EX MRuby Devkit 一个简单的脚手架,帮助你像 Go 一样把 Ruby 编译成可执行二进制文件 - V2EX 使用 Ruby-build 在 MacOS 上 编译 Portable Ruby - V2EX [翻译] Async Ruby(异步 Ruby) - V2EX [翻译] Ruby Fiber Scheduler - V2EX Ruby 3.2.0 发布 - V2EX Ruby on Mac - V2EX 用 100 行 Ruby 代码模拟 JavaScript 的 Eventloop - V2EX 管窥蠡测从思考游戏到实现 2048 - V2EX 用 Ruby 讲从创业到 996 公司的故事(戏说 master-worker 模式) - V2EX 《Ruby 设计模式》笔记 - V2EX Ruby 标准库有趣部分摘要 - V2EX 并行并发进程线程协程 GIL 概念简明解释笔记(Ruby 举例) - V2EX Sinatra 的 app 模板,提供一些胶水代码支持类似 Rails 的体验 - V2EX Ruby 的方法查找再往前一步 - V2EX 有在深圳至简天成的吗? 求加微信 - V2EX Ruby 3.0.0 Released - V2EX 新建了个 ruby 中文讨论群 - V2EX Language Hopping, Ruby 为什么不火,一点瞎想 - V2EX ruby,一代优秀语言就这样陨落了吗? - V2EX ruby 的 "a" 和 :a 能转换吗 - V2EX 求大佬帮安装一个 mastodon,有偿! - V2EX notepad++ ssh 一些个小坑 - V2EX 有什么好的方法/IDE 阅读 Gem 库的源码? - V2EX 问一个 ruby 的问题 - V2EX 用 discourse 搭了个论坛 求测试 - V2EX 找小伙伴一起开发和完善一个 Ruby 增量代码覆盖率统计工具 - V2EX 都在说抑郁,我们学一下 ruby 吧,一门让你快乐的语言 - V2EX ruby2.6 的 jit 大家感觉怎么样? - V2EX 在 one-liner 文本处理方面, ruby 比 perl 要逊色吗? - V2EX 使用 ruby 写了一个周报系统 - V2EX ruby 的 devkit 安装 - V2EX 总听人说 ruby 代码写起来很爽,有多爽?怎么个爽法? - V2EX RubyGems 注册不了的? - V2EX Ruby 破环方法为什么比非破坏方法慢一些? - V2EX Ruby Conference 2017 AU - V2EX ruby 这么优雅的语言,怎么没有像 python 这样流行开来? - V2EX Ruby 中 Singleton 方法的另一种理解方式 - V2EX 需要学习 ruby,想问现在 ruby 的主流版本是多少? - V2EX Ruby 的内存占用极限? Ruby 写了一个命令行火车票查看器 - V2EX 有谁用过 Ruby 写的比特币交易平台 Peatio,admin 面板进不去,求教啊啊啊啊啊啊啊 - V2EX 和隔壁的 python 比起来,这节点好冷清 阿里云 OSS Ruby SDK 开发手记 - V2EX 淘宝 RubyGems 镜像有段时间没同步了 - V2EX 为什么 Ruby 给人一种「只有 Rails」的印象?
Sinatra 源码分析 (一):set 系统工作原理 - V2EX
Mark24 · 2022-02-14 · via Ruby

我的 BLOG

前言

大家好,我是 MARK24 。可以叫我 MARK 。这是我研究 Sinatra 的笔记。

阅读过程大约 10 分钟。

基于 Sinatra 2.1.0 进行讨论

Sinatra v2.1.0 Fork 代码地址

set 系统可以让 Sinatra 在自身自由的定义 设置相关的变量。

比如定义模板所在:

set :views, settings.root + '/templates'

定义 session secret:

set :session_secret, ENV.fetch('SESSION_SECRET') { SecureRandom.hex(64) }

等等,非常自由且灵活。

set 系统这部分的源码恰巧是可以简单修改之后独立工作的。摘要如下:

# https://github.com/Mark24Code/sinatra-code-review/blob/master/lib/sinatra/base.rb#L1267


def define_singleton(name, content = Proc.new)
  singleton_class.class_eval do
    undef_method(name) if method_defined? name
    String === content ? class_eval("def #{name}() #{content}; end") : define_method(name, &content)
  end
end


def set(option, value = (not_set = true), ignore_setter = false, &block)
  raise ArgumentError if block and !not_set
  value, not_set = block, false if block

  if not_set
    raise ArgumentError unless option.respond_to?(:each)
    option.each { |k,v| set(k, v) }
    return self
  end

  if respond_to?("#{option}=") and not ignore_setter
    return __send__("#{option}=", value)
  end

  setter = proc { |val| set option, val, true }
  getter = proc { value }

  case value
  when Proc
    getter = value
  when Symbol, Integer, FalseClass, TrueClass, NilClass
    getter = value.inspect
  when Hash
    setter = proc do |val|
      val = value.merge val if Hash === val
      set option, val, true
    end
  end

  define_singleton("#{option}=", setter)
  define_singleton(option, getter)
  # 原始代码放在一个类中, 如果我们想放在单文件执行,需要 改写为 `self.class.method_defined?` 调用到方法
  # define_singleton("#{option}?", "!!#{option}") unless method_defined? "#{option}?"
  define_singleton("#{option}?", "!!#{option}") unless self.class.method_defined? "#{option}?"
  self
end

set 源码分析

Sinatra 内部实现了一套 配置系统,基于一个 DSL 语法 set 。 这是 Sinatra Class 部分初始化之后唯一的初始化的 DSL 。Sinatra 没有做很多复杂的前置工作。

一致很让我疑惑的是,这里的 getter 、setter 。我们传统理解的 是这样工作的:


class Sample
  def initialize()
    @name
  end

  # getter
  def name
    @name
  end

  # setter
  def name=(new_name)
    @name = new_name
  end
end

但是 Sinatra 这里似乎是一个循环一样的,你会发现他的 setter 永远在调用 set 这是为什么呢?我一度非常迷惑。

setter = proc { |val| set option, val, true }

我刚开始进入这段是百思不得其解。但事实证明我格局小了。这部分其实根本不是传统的 setter, 我们观察传统的 setter 他的问题是必须要以一个实例变量为依托。所以他才必须写成这样。 如果是下面这样呢?

class Sample

  # getter
  def name
    "new value"
  end

  # setter
  def name=(new_name)
    # setter 的逻辑,就是覆盖式定义一个 新的 直接返回新值的 getter
    re_define_name_getter(new_name)
  end
end

直接伪代码,我们每次调用 setter ,setter 的任务不是去修改一个 中间值,而是每次去重新定义 新的 getter 方法,定义的时候就塞入新的值。

这样依然保持了 getter 的功能!豁然开朗!

Sinatra 的 set 系统就是这样工作的,不论是 set 函数定义本身,还是 set 内部调用的 set ,还是用户最终在外部书写 set xxx, new_value 最终殊途同归的进入 set option, value, true 然后都会走到最后一部分,重新定义三个方法。

  define_singleton("#{option}=", setter)
  define_singleton(option, getter)
  define_singleton("#{option}?", "!!#{option}") unless method_defined? "#{option}?"

setter 方法的作用就是调用 set 自身,这样只要被调用,时间上可以完成了一种循环。闭环调用(原谅我用了闭环这个词 :P ) getter 方法 是以新的值直接返回,respond_to 方法同理,以新值计算返回。

补充

1.定义处有趣的写法 value = (not_set = true)

def set(option, value = (not_set = true), ignore_setter = false, &block)
  # ....
end

可以通过实验证实这种写法的特点是:

如果 value 赋值 比如是 99 ,那么 value = 99, not_set = nil

如果 value 没有赋值, 那么 value = not_set = true

这里主要是没有赋值,not_set 开始发挥逻辑上的作用。

我的 BLOG