ruby 状态转移

Ruby语言的网络编程 Ruby是一种动态、面向对象、简单易读且具有强大功能的编程语言。它的易用性和优雅的语法使得开发者能够快速构建出高效的应用程序。网络编程是Ruby语言应用中非常重要的一部分,涵盖了从简单的网络请求到复杂的服务器开发等多个方面。本文将深入探讨Ruby语言在网络编程中的应用,包括基础知识、常用库、网络协议、以及实际案例等内容。 阅读详情

0. 引言

      昨天遇到一个问题,就是关于对象状态转移的问题,我姑且这样命名吧。简要描述一下就是:对于一个人,他有进食,帮助他人,恋爱等功能,但是这些功能是有先后顺序的,对于刚出生的人,他要先学会进食,然后随着他的成长,他逐渐学会帮助他人,在这个过程中他学会了爱与被爱,当他遇到一个合适的女孩,他就坠入了爱河。整个过程反映到程序上就是,必须按照下面的顺序调用方法:
man=Human.new
man.feed
man.fall_in_love   # Error
man.help_people
man.fall_in_love

     如果你调用某个功能时没有完成前面的事情,就像上面的例子这样,一个人尚未学会帮助他人的人,我们是不希望他去恋爱的,这样一个不懂得互助互爱的人怎么可能珍惜自己的爱人呢?
     所以,对象状态转移就是:某个对象随着状态转移获得调用新方法的能力或权限,未达到某个状态前无法调用该状态下的方法。

1. 目标

      仔细想想,其实这类问题出现还是比较普遍的,比如一个浏览器处理类,它必须要在登陆操作后才允许执行修改个人信息。所以,有必要为了这类问题思考一个解决方法。那么,首先要明确的是,我想要怎样实现这样一个功能。为每个类去实现一个这样的状态转移显然不是ruby way。所以,我觉得对于我自己,我希望这样处理一下我的Human类之后,我就能像引言中那样直接使用状态转移提供的功能:
class Human
	include State
	def feed
		puts"feed myself"
	end
	def protect_env
		puts "protect environment"
	end
	def help_people
		puts "help other people"
	end
	def fall_in_love
		puts "love someone"
	end
	define_chain :feed,[:protect_env,:help_people],:fall_in_love
end
      如代码所示,我希望在我使用的类中包含一个State模块,然后用define_chain定义一个方法链,那么方法链中的方法,必须要在前一个方法调用过之后才可以被调用,否则就会抛出异常。另外,在定义方法链的define_chain中,我希望可以包含列表,列表中的方法需要至少被调用一种才能执行方法链的后续调用。
      好吧,这样看起来,似乎是像模像样的ruby解决方法了,那么,下面就看看如何来实现这个State模块。

2. 环绕别名

     首先,我们肯定需要在define_chain方法上做文章。该方法实际完成状态转移方法链的定义,那么问题的关键是:我知道了这一串方法,怎么样保证在调用下一个方法前,明确上一个方法是否被调用了呢?很显然,我们需要一个变量来保存状态,在每次调用方法前检查是否能够调用当前方法,如果能够,则在调用完成之后更新状态。那么怎么做呢?总不能要求编写Human类的程序员在每个方法调用前先检查一下状态,在调用完成后再更新状态吧,那显然是会被鄙视的。实际上,作为一个ruby程序员,每个人都需要会一点点魔法,这次的魔法就是环绕别名。
    假如,对于某个方法名method,我们可以这样环绕起来:
define_method "#{method}_in_chain" do |*params,&block|
	validate_state_for method.to_sym
	self.send "#{method}_out_chain",*params,&block
	update_state_for method.to_sym
	end
alias_method "#{method}_out_chain",method
alias_method method,"#{method}_in_chain"
     这部分代码就是define_chain方法的主体,这样,在定义了状态转移方法链之后,直接调用在方法链中的方法,就会自动使用validate_state_for方法检查方法是否可以被调用,在完成调用后使用update_state_for方法更新状态。
   然后我们去实现validate_state_for和update_state_for方法,这两个方法实现很简单,后面再说,我们的State模块看起来基本是这样的:
module State
	def define_chain(*args)
	end

	def validate_state_for(method)
	end
	
	def update_state_for(method)
	end
end


    好吧,问题的最关键部分解决了,但还是有一些细节,不要小看细节,它决定成败。

3. 类扩展混入

   显然,我们的define_chain方法必须作为类方法存在,这很简单,可以使用扩展混入。即
class Human
  extend State
end

   但问题来了,我只希望define_chain被作为类方法混入,而validate_state_for和update_state_for方法仍然需要作为类实例方法。那么直接混入肯定就不行了,这时就需要使用ruby另一个魔法了——类扩展混入,将部分方法作为类方法混入,部分方法作为实例方法混入。这种魔法使用了included钩子。
module State
	def self.included(base)
		base.extend StateMaker
	end
	module StateMaker
		def define_chain(*args)
		end
	end
	def validate_state_for(method)
	end
	def update_state_for(method)
	end
end

     现在,在使用下面的方法混入,就获得了我想要的效果。我能够用类方法define_chain定义状态方法链,也能够实例化Human对象调用它的validate_state_for实例方法。
class Human
  include State
end
    

4. 最后一步,实现

     我们的State状态转移模块的结构就是这样了,那么下面就需要具体实现了。
    状态判断逻辑非常简单:按照状态方法链的定义,从左到右从0开始编号,而对象状态也从0开始,仅到当前状态大于等于方法编号时,才允许调用该方法。
     状态更新逻辑:仅当状态方法编号等于当前对象状态时,才更新状态,即将状态值加1。
     这就是State模块的实例方法实现:
module State
	def validate_state_for(method)
		raise "State is too low to execute #{method}" unless min_state_for(method) <= state
	end
	def min_state_for(method)
		self.class.state_chain.find_index{|k,v| v.include? method}
	end
	def update_state_for(method)
		@_state_from_object_monitor_+=1 if min_state_for(method) == state
	end
	def reset_state
		@_state_from_object_monitor_=0
	end
	def state
		@_state_from_object_monitor_=0 unless @_state_from_object_monitor_
		@_state_from_object_monitor_
	end
end

    该模块还提供了reset_state方法重置状态值。另外,min_state_for方法用于获取调用某个方法的最低状态值,该方法中实际上也使用了ruby一点点小魔法,类实例变量,state_chain是一个类方法,它获取了是我们定义的状态转移方法链的一个hash表,该表是一个类实例变量,这个hash具体结构马上就会看到。
    下面就是State::StateMaker的的define_chain方法的实现:
module State
	module StateMaker
		def define_chain(*args)
			args.map{|x| x}
			args.flatten.each do |method|
				define_method "#{method}_in_chain" do |*params,&block|
					validate_state_for method.to_sym
					self.send "#{method}_out_chain",*params,&block
					update_state_for method.to_sym
					nil
				end
				alias_method "#{method}_out_chain",method
				alias_method method,"#{method}_in_chain"
			end
			@chain_methods=args.each_with_index.inject({}) do |memo,(v,index)|
				memo[index]=v.class==Symbol ? [v] : v
				memo
			end
			nil
		end
		
		def state_chain
			@chain_methods
		end
	end
end

      define_chain方法的前半部分使用环绕别名来包裹特定方法,后半部分就是生成方法链的hash表,生成的hash表被保存在实例变量@chain_methods中,由于define_chain被作为类方法混入,所以它自然也成为了混入类的类实例变量,注意,尽量多使用类实例变量而不要使用类变量。而state_chain方法也同时混入成为类方法,该方法纯粹就是用来获取类实例变量chain_methods的。如1.目标中的方法链生成的hash表的结构是:
{0=>[:feed], 1=>[:protect_env, :help_people], 2=>[:fall_in_love]}

5. 结尾

       现在,整个状态转移方法调用就完成了,可以像引言中那样去使用了。不过,这仅仅是个开始,ruby的原则就是DRY,还有细节的地方需要完善修改,比如用ruby2.0就可以更漂亮地完成环绕别名等等。

6. 附录

     下面是State模块完整代码,供参考。
module State
	def self.included(base)
		base.extend StateMaker
	end
	module StateMaker
		def define_chain(*args)
			args.map{|x| x}
			args.flatten.each do |method|
				define_method "#{method}_in_chain" do |*params,&block|
					validate_state_for method.to_sym
					result=self.send "#{method}_out_chain",*params,&block
					update_state_for method.to_sym
					result
				end
				alias_method "#{method}_out_chain",method
				alias_method method,"#{method}_in_chain"
			end
			@chain_methods=args.each_with_index.inject({}) do |memo,(v,index)|
				memo[index]=v.class==Symbol ? [v] : v
				memo
			end
			nil
		end
		def state_chain
			@chain_methods
		end
	end
	def validate_state_for(method)
		raise "State is too low to execute #{method}" unless min_state_for(method) <= state
	end
	def min_state_for(method)
		self.class.state_chain.find_index{|k,v| v.include? method}
	end
	def update_state_for(method)
		@_state_from_object_monitor_+=1 if min_state_for(method) == state
	end
	def reset_state
		@_state_from_object_monitor_=0
	end
	def state
		@_state_from_object_monitor_=0 unless @_state_from_object_monitor_
		@_state_from_object_monitor_
	end
end


框架设计原理与实战:Ruby on Rails框架的CRUD操作 1.背景介绍 Ruby on Rails是一个基于MVC(Model-View-Controller)模式的Web开发框架。它由Ruby语言编写,支持RESTful HTTP API。Rails采用了简洁而独特的语法,使得开发者可以快速上手。Ruby on Rails框架提供了一系列工具方法帮助开发者快速构建功能完备、可维护的应用。例如,可以创建脚手架 阅读详情

相关推荐

框架设计原理与实战:从Ruby on Rails到Django

作者:禅与计算机程序设计艺术 1.背景介绍 Ruby on Rails 简介 Rails是一个开源的Web开发框架,基于Ruby语言构建,其核心思想是约定优于配置,其本质就是一个MVC(Model-View-Controller)模式的W

AI天才研究院 285

ruby中argv_了解Ruby中的代表性状态转移(REST)

代表性状态转移(REST)是基于Web的通信的体系结构样式,它允许客户端以独特的方式与服务器进行通信。 特别是,REST将给定服务器内的资源表示为统一资源标识符(URI),从而简化了超文本传输​​协议(HTTP)上REST体系结构的实现。 让我们首先介绍REST和HTTP背后的思想。 然后,我们将探索数据表示形式,然后以Ruby语言实现一个简单的REST客户端。 HTTP快速入门 让我...

cuxiong8996的博客 820

Ruby编程入门与核心特性全面解析

Ruby 的方法定义看似简洁直观,但其背后隐藏着丰富的语义规则和运行时行为。与其他静态类型语言不同,Ruby 允许极为灵活的参数声明方式,包括默认值、可变长度参数(splat)、关键字参数等,这些特性共同构成了 Ruby 强大的接口表达能力。更重要的是,Ruby 在参数传递过程中采用的是“按引用传递对象”的模型,但这并不意味着所有修改都会影响原始变量——这种微妙的行为差异常常成为新手误解的根源。因此,深入理解参数绑定过程中的对象共享机制,是编写安全、可预测代码的前提。

weixin_42601134的博客 579

用Ruby 写Turing 机

最近在看John E.Hopcroft,Rajeev Motwani,Jeffrey D.Ullman 三巨头写的Introduction to Automata Theory,Language,and Computation,想写一个Turing 机验证一下自己写的状态转移函数对不对。懒得很,网上搜了几个不错的。但Ruby Quiz 上的这个最简单。   

Pope 的废纸篓 1454

【Qt笔记】1.VSCode搭建Qt运行环境

Qt6之后已经抛弃qmake,使用cmake。cmake相对qmake来说只有优点没有缺点。使用VSCode搭建完Qt的运行环境就能开开心心debug了.vscode需要使用的插件:2.Qt tools3.CMakec++插件可以不关注,缺啥都会提醒你.正常安装即可。

没有手牌的博客 2万+

如何在Vitis 2023.1上快速搭建LWIP Echo Server(附YT8521S PHY调试心得)

本文详细介绍了在Vitis 2023.1开发环境下,基于Xilinx MPSoC平台快速搭建LWIP Echo Server的完整实战流程。内容涵盖从Vivado硬件工程配置、Vitis软件工程创建,到关键代码剖析与定制化修改,并重点分享了调试非标准PHY芯片(如YT8521S)的宝贵心得与常见问题排查方法,旨在帮助开发者高效实现FPGA与上位机间的可靠网络通信验证。

weixin_29250403的博客 136

Ruby语言的动态规划

动态规划是一种强大的算法策略,通过将复杂问题转化为简单的子问题,以有效地解决各种优化问题和决策问题。Ruby语言提供了简洁而强大的工具来实现动态规划,使得开发者能够以快速而有效的方式解决实际问题。在本篇文章中,我们探讨了动态规划的基本概念、经典问题及其解决方案,并重点展示了如何在Ruby中实现动态规划,并对空间复杂度进行优化。希望本篇文章能够帮助读者更好地理解动态规划,并将其应用于实际编码当中。

2501_91325030的博客 480

Ubuntu 22.04 安装 IsaacLab 2.1.0

本文介绍了IsaacLab的完整安装流程:1)创建Python3.10虚拟环境;2)安装PyTorch2.5.1(CUDA11.8);3)升级pip并安装IsaacSim4.5.0;4)克隆IsaacLab仓库;5)运行安装脚本(需接受EULA)。若遇cmake缺失错误,需执行sudo apt安装。安装完成后可通过Ant-v0训练任务验证,成功运行后将显示IsaacSim窗口和训练完成提示。注意:IsaacSim不同版本可共存于不同环境。

weixin_47880303的博客 2223

gem algorithms010 读然后学着写

gem algorithms010 读然后学着写 今天为了弄那个参赛国家接龙的程序,忽然想到,《程序设计实践》上讲了,齐次马尔科夫过程,我想,用ruby也写一次。 因为当时,用C语言感觉相当麻烦,而用awk而无比优雅。可程序并不能解决我的问题。还得再想想。 arr=[] File.open("english2.txt") do |fp| fp.each_line do |line| # ...

woshiyilitongdouzi的博客 126

2️⃣ Coze创建智能体教学(2025年全新版本)

扣子平台提供强大支持,可将智能体轻松集成至各类社交平台,使智能体得以服务更为庞大的用户群体。当下支持集成的平台如下:​1️⃣豆包:作为聚焦 AI 内容创作的平台,非常适合发布充满创意、娱乐性强的智能体。​2️⃣飞书:适合发布用于办公协作的智能体,助力团队提升工作效率。​3️⃣微信:借助公众号或小程序的形式,能够服务海量微信用户。​4️⃣抖音:适合发布与短视频相关的智能体,为用户提供创意与娱乐服务。​

李同学Lino的博客 4576

5、数据计算与处理技巧全解析

本文深入解析了Tableau中的多种数据计算与处理技巧,涵盖LOD计算、日期与字符串处理、计数优化、数据混合限制及自定义总计等核心内容。通过实际案例和流程图,系统讲解了各技巧的应用场景、实现步骤与注意事项,并提供性能优化建议和常见问题解答,帮助用户提升数据分析效率与可视化精度。同时展望了未来数据计算技术的发展趋势,是Tableau用户进阶必备的全面指南。

peach的博客 82

【程序思考】RIA 对于 java 在 web 开发领域是否是一个转机?

 今天看了 dlee 在 csdn  发表的一篇文章  http://blog.youkuaiyun.com/mozilla/archive/2007/07/22/1702365.aspx  。 觉得很有意思。以前我在 javaeye 就看过他的很多文章, 很有见地。 最近他的很多言论都是围绕 rest 的, 把 rest 的地位抬的很高。 我个人倒是觉得 RIA  相对而言对于 web 开发更具革命性一些。

mulder 的程序人生 6675

9、工业数据管理:Historian、ERP、MES与资产模型解析

本文深入解析了工业数据管理中的核心概念与技术,包括Historian数据库、ERP和MES系统以及资产模型。文章详细介绍了Historian数据库的特性、架构分类、数据采集方式及时间序列处理能力,同时探讨了ERP和MES系统的功能与优势,特别是MES在生产执行中的重要作用。资产模型部分结合ISA-95和ISA-88标准,阐述了工业资产的层次化建模方法。此外,文章还分析了各系统之间的协同关系、面临的挑战及应对策略,并展望了未来工业数据管理的发展趋势,如云原生技术、人工智能融合和工业物联网的应用。

pz89012345的博客 144

用ruby写的wikipedia上的维特比算法

维特比算法可以解决隐马尔科夫模型的最可能状态序列问题。 wikipedia上关于维特比算法,提供了一个python的例子,原文地址如下 http://zh.wikipedia.org/wiki/%E7%BB%B4%E7%89%B9%E6%AF%94%E7%AE%97%E6%B3%95 鉴于最近正在学习ruby,就把这个算法从python迁移到ruby,这两个语言的语法很接近,所以,前移过去没...

weixin_30784501的博客 110

基于YOLOv8的野生菌菇检测、识别与分类系统

YOLOv8是YOLO系列模型的最新版本,继承了YOLO系列高效、精确的特点。YOLOv8采用了新的网络架构,并优化了推理速度和检测精度。与传统的目标检测算法(如Faster R-CNN)不同,YOLO模型通过一次前向传播同时完成目标定位与分类,因而具有非常高的计算效率。

YOLO 1284

STM32F407中文手册

STM32f407中文手册 本参考手册面向应用开发人员,提供有关使用 STM32F405xx/07xx、STM32F415xx/17xx、 STM32F42xxx 和 STM32F43xxx 微控制器存储器与外设的完整信息。STM32F405xx/07xx、STM32F415xx/17xx、STM32F42xxx 和 STM32F43xxx 构成一个微 控制器系列,各产品具有不同的存储器大小、封装和外设。有关订购信息以及器件的机械与电气特性,请参见数据手册。有关 ARM Cortex™-M4F 内核的信息,请参见《Cortex™-M4F 技术参考手册》。

Hello 算法动态规划入门:从爬楼梯看暴力搜索、记忆化搜索到状态转移方程

本篇基于 [《Hello 算法》动态规划章节的"初探动态规划"文档](https://link.gitcode.com/i/6068a3f233d484262eaa96991a334f85),以"爬楼梯"这一经典例题为载体,完整还原了从暴力回溯、暴力搜索、记忆化搜索到底至顶动态规划(含空间优化)的渐进式推导过程。读完本文,你将掌握动态规划的三个核心概念——dp 表、初始状态、状态转移方程,并能结合

gitblog_00901的博客 660

efm32 入门.pdf

本PDF共计22页,介绍的是操作驱动API,下载与否自己斟酌。

ruby on rails_使用Ruby on Rails和Action Web Service创建Web服务

Rails是一个Web应用程序框架,其中包括使用Model-View-Control(MVC)模式创建数据库支持的Web应用程序所需的一切。 Action Web Service的最简洁定义是在其README文件中:“ Action Web Service提供了一种使用Rails发布可互操作的Web Service API的方法,而无需花费大量时间来研究协议细节。” 在本文中,您将学习如何安装...

cuxiong8996的博客 476

android 蓝牙通讯demo

android 下蓝牙通讯demo,实现了发现蓝牙,使能蓝牙,通过蓝牙发送消息。

汉书HE8,好用的汇编代码编写工具

汉书HE8,好用的汇编代码编写工具早期编写汇编代码所用功能强大

REST表征状态转移

表征状态转移(英文:Representational State Transfer,简称REST)是Roy Fielding博士在2000年他的博士论文中提出来的一种软件架构风格。 目前在三种主流的Web服务实现方案中,因为REST模式的Web服务与复杂的SOAP和XML-RPC对比来讲明显的更加简洁,越来越多的web服务开始采用REST风格设计和实现。例如,Amazon.com提供接近RE...

weixin_34216036的博客 270

RubyonRails是WebDev最佳选择的5个原因

90年代,日本软件工程师松本幸雄(YukihirioMatsumoto)在努力寻找一种功能强大、易于使用的编程语言后,决定自己开发一种编程语言。那时红宝石1995年首次公开露面。 十年后,当DavidHeinemeierHansson创建了RubyonRails并构建了一个自定义的Web框架来加速这个过程时,这个语言终于得到了发展。 “Rails是我使用过的最深思熟虑的Web开发框架。这是十年来...

Tybyqi的博客 471

obsidian-local-gpt模板语法深度解析:{{=SELECTION=}}与{{=CONTEXT=}}占位符完全指南

**obsidian-local-gpt** 是一款运行在 Obsidian 里的本地 AI 助手插件,支持 Ollama、OpenAI 兼容接口等模型,让你完全离线、隐私无忧地调用大模型。它的最大亮点之一,就是内置了一套简洁的 **Prompt 模板占位符语法**:`{{=SELECTION=}}` 和 `{{=CONTEXT=}}`,可以把"你选中的文字"和"RAG 检索到的上下文"精确插入提

gitblog_00792的博客 1072

Hello 演算法:零錢兌換 II 動態規劃全解析——組合計數、狀態轉移與空間最佳化

本篇技術指南以《Hello 演算法》(hello-algo)繁體中文倉庫中的「零錢兌換 II」為主題,完整拆解「**在硬幣可無限重複選取的前提下,計算湊出目標金額的組合總數**」這一經典完全背包(unbounded knapsack)變體。文章會從問題定義出發,逐步推導二維動態規劃解法、解釋為什麼走訪順序決定「組合」而非「排列」,再給出一維空間最佳化版本,並結合倉庫中的多語言實作與 Python

gitblog_00731的博客 914

rake- Ruby Make

Rake,顾名思义,就是Ruby的Make工具。的

压碎起重机 4162
上一篇: rails-sidekiq
下一篇: 学算法并非和语言无关
qjpcpu
博客等级 码龄15年 59粉丝 106原创
评论 1
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值