我正在使用 GitHub Wiki 页面记录一个项目,现在我想将 MySQL 数据库架构导出为 Markdown 格式。有没有办法将 CLI 输出转换为 GitHub Wiki md?理想地作为表。
我的输出如下所示:

最佳答案
这段代码比较长。我道歉。它由两个存储过程组成。仅运行第一个您可能会感到满意。第二个使用第一个的输出(表中第一个左侧的数据)。您可能还希望将代码合二为一。但我把它们分开了。第二个存储过程产生的输出类似于 describe myTable .但它会为您需要此类输出的数据库中的所有表执行此操作。
您可以通过传递一个参数(字符串)供数据库报告来使用它。
我创建了一个单独的数据库,并且代码按名称显式引用了该数据库中的表。所以如果你有 EXECUTE此存储过程的特权,您可以从任何当前数据库运行它。因此,作为一个简单的测试,不要将报告数据库设置为您当前的数据库,而只需按名称(用报告数据库名称限定)调用存储过程。这都显示在下面的测试块中。
两个存储过程
CREATE SCHEMA Reporting101a; -- See **Note1**
DROP PROCEDURE IF EXISTS `Reporting101a`.`describeTables_v2a`;
DELIMITER $$
CREATE DEFINER=`root`@`localhost` PROCEDURE `Reporting101a`.`describeTables_v2a`(
IN dbName varchar(100), -- the dbname to report table structures
OUT theSession int, -- OUT parameter for session# assigned
IN deleteSessionRows BOOL, -- true for delete rows when done from main reporting table for this session#
IN callTheSecondStoredProc BOOL -- TRUE = output is from Pretty output in Second Stored Proc. FALSE= not so pretty output
)
BEGIN
DECLARE thisTable CHAR(100);
DROP TEMPORARY TABLE IF EXISTS Reporting101a.tOutput;
CREATE TEMPORARY TABLE Reporting101a.tOutput
( id int auto_increment primary key,
tblName varchar(100) not null,
ordVal int not null,
cField varchar(100) not null,
cType varchar(100) not null,
cNull varchar(100) not null,
cKey varchar(100) not null,
cDefault varchar(100) null,
cExtra varchar(100) null
);
DROP TEMPORARY TABLE IF EXISTS Reporting101a.tOutput2;
CREATE TEMPORARY TABLE Reporting101a.tOutput2
( tblName varchar(100) primary key,
colCount int not null,
cFieldMaxLen int not null,
cTypeMaxLen int not null,
cNullMaxLen int not null,
cKeyMaxLen int not null,
cDefaultMaxLen int not null,
cExtraMaxLen int not null
);
INSERT Reporting101a.tOutput(tblName,ordVal,cField,cType,cNull,cKey,cDefault,cExtra)
SELECT TABLE_NAME,ORDINAL_POSITION,COLUMN_NAME AS Field, COLUMN_TYPE AS TYPE, RPAD(IS_NULLABLE,4,' ') AS 'Null',
RPAD(COLUMN_KEY,3,' ') AS 'Key',RPAD(COLUMN_DEFAULT,7,' ') AS 'DEFAULT',EXTRA AS Extra
FROM information_schema.columns WHERE table_schema = dbName ORDER BY table_name,ordinal_position;
-- select * from information_schema.columns WHERE table_schema = '57security' order by table_name,ordinal_position;
UPDATE Reporting101a.tOutput
SET cExtra=' '
WHERE cExtra='';
UPDATE Reporting101a.tOutput
SET cField=RPAD(cField,5,' ')
WHERE LENGTH(cField)<5;
INSERT Reporting101a.tOutput2(tblName,colCount,cFieldMaxLen,cTypeMaxLen,cNullMaxLen,cKeyMaxLen,cDefaultMaxLen,cExtraMaxLen)
SELECT tblName,COUNT(*),0,0,0,0,0,0
FROM Reporting101a.tOutput
GROUP BY tblName;
UPDATE tOutput2 t2
JOIN
( SELECT tblName,MAX(LENGTH(cField)) AS mField,MAX(LENGTH(cType)) AS mType,MAX(LENGTH(cNull)) AS mNull,
IFNULL(MAX(LENGTH(cKey)),0) AS mKey,IFNULL(MAX(LENGTH(cDefault)),0) AS mDefault,IFNULL(MAX(LENGTH(cExtra)),0) AS mExtra
FROM Reporting101a.tOutput
GROUP BY tblName
) x
ON x.tblName=t2.tblName
SET t2.cFieldMaxLen=x.mField,t2.cTypeMaxLen=x.mType,cNullMaxLen=x.mNull,
cKeyMaxLen=x.mKey,cDefaultMaxLen=x.mDefault,cExtraMaxLen=x.mExtra;
-- DROP TABLE Reporting101a.reportDataDefsSession; -- useful for quick change of structure of table
-- note, keep above drop call remmed out ! Just use it for quick tweaks to structure
CREATE TABLE IF NOT EXISTS Reporting101a.reportDataDefsSession
( -- for the sole purpose of safe session auto_inc usage
-- Please don't delete unless you want the sessions to experience aberant behavior
sessionId INT AUTO_INCREMENT PRIMARY KEY,
dummy CHAR(1) NOT NULL,
creationDT datetime not null
);
CREATE TABLE IF NOT EXISTS Reporting101a.reportDataDefs
( sessionId INT NOT NULL,
tblName VARCHAR(100) NOT NULL, -- Tablename
ordVal INT NOT NULL, -- the "position number" of the Column
cField VARCHAR(100) NOT NULL, -- The Column
cType VARCHAR(100) NOT NULL, -- Datatype
cNull VARCHAR(100) NOT NULL, -- Nullability
cKey VARCHAR(100) NOT NULL, -- Key info
cDefault VARCHAR(100) NULL, -- Default value
cExtra VARCHAR(100) NULL, -- Extra output
colCount INT NOT NULL, -- the columns here and below are de-normalize data
cFieldMaxLen INT NOT NULL,
cTypeMaxLen INT NOT NULL,
cNullMaxLen INT NOT NULL,
cKeyMaxLen INT NOT NULL,
cDefaultMaxLen INT NOT NULL,
cExtraMaxLen INT NOT NULL
);
-- For lack of a better notion, we are calling calls "sessions". The programmer calls the
-- First Stored Proc, and we call that a session after we get a unique next incrementing number.
-- That number is the session #. House all output with that as a column value. This allows us to
-- move between stored procs, have safe output, have historical snapshots, and retain the data
-- via a session # for later use, whatever use.
INSERT Reporting101a.reportDataDefsSession(dummy,creationDT) VALUES ('X',now());
SET @mySession=LAST_INSERT_ID(); -- there it is, our session # (read the above paragraph)
INSERT Reporting101a.reportDataDefs(sessionId,tblName,ordVal,cField,cType,cNull,cKey,cDefault,cExtra,
colCount,cFieldMaxLen,cTypeMaxLen,cNullMaxLen,cKeyMaxLen,cDefaultMaxLen,cExtraMaxLen)
SELECT @mySession,t1.tblName,t1.ordVal,t1.cField,t1.cType,t1.cNull,t1.cKey,t1.cDefault,t1.cExtra,
t2.colCount,t2.cFieldMaxLen,t2.cTypeMaxLen,t2.cNullMaxLen,t2.cKeyMaxLen,t2.cDefaultMaxLen,t2.cExtraMaxLen
FROM Reporting101a.tOutput t1
JOIN Reporting101a.tOutput2 t2
ON t2.tblName=t1.tblName
ORDER BY t1.tblName,t1.id;
DROP TEMPORARY TABLE Reporting101a.tOutput;
DROP TEMPORARY TABLE Reporting101a.tOutput2;
SET theSession=@mySession; -- the OUT var that came in as a parameter
-- ***************************************************************************
-- ***************************************************************************
-- Label "Some_Sort_of_Output":
IF callTheSecondStoredProc=TRUE THEN
-- The caller says to call the second stored proc (for Pretty Printing)
-- This will generate output similar to `DESCRIBE myTable`
-- But remember, it will do it for EVERY table in referenced database
CALL Reporting101a.`Print_Tables_Like_Describe`(@mySession);
-- The above call just gave you output.
ELSE
-- The caller chose to not auto call the Pretty Printing second stored procedure.
-- Note, the caller can easily call it right after using the OUT parameter.
-- So our output will be a resultset of out reportDataDefs table for this session #
SELECT *
FROM Reporting101a.reportDataDefs
WHERE sessionId=@mySession
ORDER BY tblName,ordVal;
END IF;
-- ***************************************************************************
-- ***************************************************************************
IF deleteSessionRows=TRUE THEN
-- The caller says output rows are NOT needed at this point. Delete them.
-- Note, if this boolean comes in TRUE, you can't call Pretty Printing
-- second stored procedure with the session # because the data is gone.
--
-- Regardless, you are getting something back from "Some_Sort_of_Output" above.
DELETE FROM Reporting101a.reportDataDefs
WHERE sessionId=@mySession;
END IF;
END$$
DELIMITER ;
DROP PROCEDURE IF EXISTS `Reporting101a`.`Print_Tables_Like_Describe`;
DELIMITER $$
CREATE DEFINER=`root`@`localhost` PROCEDURE `Reporting101a`.`Print_Tables_Like_Describe`(
pSessionId INT
)
BEGIN
DECLARE done INT DEFAULT FALSE;
DECLARE curTable VARCHAR(100) DEFAULT '';
DECLARE bFirst BOOL DEFAULT TRUE;
DECLARE lv_tblName,lv_cField,lv_cType,lv_cNull,lv_cKey,lv_cDefault,lv_cExtra VARCHAR(100);
DECLARE lv_ordVal,lv_colCount,lv_cFieldMaxLen,lv_cTypeMaxLen,lv_cNullMaxLen,lv_cKeyMaxLen,lv_cDefaultMaxLen,lv_cExtraMaxLen INT;
DECLARE cur1 CURSOR FOR SELECT tblName,ordVal,cField,cType,cNull,cKey,cDefault,cExtra,
colCount,cFieldMaxLen,cTypeMaxLen,cNullMaxLen,cKeyMaxLen,cDefaultMaxLen,cExtraMaxLen
FROM Reporting101a.reportDataDefs
WHERE sessionId=pSessionId
ORDER BY tblName,ordVal;
DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = TRUE;
-- Please note in the above, CURSOR stuff must come last else "Error 1337: Variable or condition decl aft curs"
CREATE TABLE IF NOT EXISTS Reporting101a.reportOutput
( lineNum INT AUTO_INCREMENT PRIMARY KEY,
sessionId INT NOT NULL,
lineOut varchar(100) NOT NULL
);
-- INSERT Reporting101a.reportOutput(sessionId,lineOut)
-- SELECT
-- SET curTable='';
DELETE FROM Reporting101a.reportOutput
WHERE sessionId=pSessionId;
OPEN cur1;
read_loop: LOOP
FETCH cur1 INTO lv_tblName,lv_ordVal,lv_cField,lv_cType,lv_cNull,lv_cKey,lv_cDefault,lv_cExtra,
lv_colCount,lv_cFieldMaxLen,lv_cTypeMaxLen,lv_cNullMaxLen,lv_cKeyMaxLen,lv_cDefaultMaxLen,lv_cExtraMaxLen ;
IF done THEN
LEAVE read_loop;
END IF;
IF lv_tblName<>curTable THEN
IF bFirst=FALSE THEN
INSERT Reporting101a.reportOutput(sessionId,lineOut)
SELECT pSessionId,'';
ELSE
SET bFirst=FALSE;
END IF;
INSERT Reporting101a.reportOutput(sessionId,lineOut)
SELECT pSessionId,lv_tblName;
INSERT Reporting101a.reportOutput(sessionId,lineOut)
SELECT pSessionId,CONCAT('+-',
REPEAT('-',GREATEST(5,lv_cFieldMaxLen)), '-+-',
REPEAT('-',GREATEST(4,lv_cTypeMaxLen)), '-+-',
REPEAT('-',GREATEST(4,lv_cNullMaxLen)), '-+-',
REPEAT('-',GREATEST(3,lv_cKeyMaxLen)), '-+-',
REPEAT('-',GREATEST(7,lv_cDefaultMaxLen)), '-+-',
REPEAT('-',GREATEST(5,lv_cExtraMaxLen)), '-+');
SET @dashLineNumRow=LAST_INSERT_ID();
INSERT Reporting101a.reportOutput(sessionId,lineOut)
SELECT pSessionId,CONCAT('| ',
'Field',
REPEAT(' ',GREATEST(0,lv_cFieldMaxLen-5)), ' | ',
'Type',
REPEAT(' ',GREATEST(0,lv_cTypeMaxLen-4)), ' | ',
'Null',
REPEAT(' ',GREATEST(0,lv_cNullMaxLen-4)), ' | ',
'Key',
REPEAT(' ',GREATEST(0,lv_cKeyMaxLen-3)), ' | ',
'Default',
REPEAT(' ',GREATEST(0,lv_cDefaultMaxLen-7)), ' | ',
'Extra',
REPEAT(' ',GREATEST(0,lv_cExtraMaxLen-5)), ' |');
INSERT Reporting101a.reportOutput(sessionId,lineOut)
SELECT pSessionId,lineOut
FROM Reporting101a.reportOutput
WHERE lineNum=@dashLineNumRow;
-- SELECT * FROM Reporting101a.reportDataDefs WHERE sessionId=24;
SET curTable=lv_tblName;
END IF;
INSERT Reporting101a.reportOutput(sessionId,lineOut)
SELECT pSessionId,
CONCAT('| ',
COALESCE(lv_cField,''),
COALESCE(REPEAT(' ',GREATEST(0,lv_cFieldMaxLen-LENGTH(lv_cField))),''),' | ',
COALESCE(lv_cType,''),
COALESCE(REPEAT(' ',GREATEST(0,lv_cTypeMaxLen-LENGTH(lv_cType))),''),' | ',
COALESCE(lv_cNull,''),
COALESCE(REPEAT(' ',GREATEST(0,lv_cNullMaxLen-LENGTH(lv_cNull))),''),' | ',
COALESCE(lv_cKey,' '),
COALESCE(REPEAT(' ',GREATEST(0,lv_cKeyMaxLen-LENGTH(lv_cKey))),''),' | ',
COALESCE(lv_cDefault,' '),
COALESCE(REPEAT(' ',GREATEST(0,lv_cDefaultMaxLen-LENGTH(lv_cDefault))),''),' | ',
COALESCE(lv_cExtra,' '),
COALESCE(REPEAT(' ',GREATEST(0,lv_cExtraMaxLen-LENGTH(lv_cExtra))),''),' |');
INSERT Reporting101a.reportOutput(sessionId,lineOut)
SELECT pSessionId,lineOut
FROM Reporting101a.reportOutput
WHERE lineNum=@dashLineNumRow;
END LOOP;
CLOSE cur1;
select lineOut as '' from Reporting101a.reportOutput where sessionId=pSessionId order by lineNum;
END$$
DELIMITER ;
-- See **Note2**
SET @theOutVar =-1; -- A variable used as the OUT variable below
-- See **Note3**
-- Note: with `TRUE` as the 4th parameter, this is a one call deal. Meaning, you are done.
call Reporting101a.describeTables_v2a('stackoverflow',@theOutVar,false,true);
-- See **Note4**
-- Primarily used if the 4th parameter above is false
call Reporting101a.Print_Tables_Like_Describe(@theOutVar); -- loads data for prettier results in chunk format.
+--------------------------------------------------------------------------------------------+
| |
+--------------------------------------------------------------------------------------------+
| course |
| +------------+--------------+------+-----+---------+----------------+ |
| | Field | Type | Null | Key | Default | Extra | |
| +------------+--------------+------+-----+---------+----------------+ |
| | courseId | int(11) | NO | PRI | | auto_increment | |
| +------------+--------------+------+-----+---------+----------------+ |
| | deptId | int(11) | NO | MUL | | | |
| +------------+--------------+------+-----+---------+----------------+ |
| | courseName | varchar(100) | NO | | | | |
| +------------+--------------+------+-----+---------+----------------+ |
| |
| dept |
| +----------+--------------+------+-----+---------+----------------+ |
| | Field | Type | Null | Key | Default | Extra | |
| +----------+--------------+------+-----+---------+----------------+ |
| | deptId | int(11) | NO | PRI | | auto_increment | |
| +----------+--------------+------+-----+---------+----------------+ |
| | deptName | varchar(100) | NO | | | | |
| +----------+--------------+------+-----+---------+----------------+ |
| |
| scjunction |
| +------------+---------+------+-----+---------+----------------+ |
| | Field | Type | Null | Key | Default | Extra | |
| +------------+---------+------+-----+---------+----------------+ |
| | id | int(11) | NO | PRI | | auto_increment | |
| +------------+---------+------+-----+---------+----------------+ |
| | studentId | int(11) | NO | MUL | | | |
| +------------+---------+------+-----+---------+----------------+ |
| | courseId | int(11) | NO | MUL | | | |
| +------------+---------+------+-----+---------+----------------+ |
| | term | int(11) | NO | | | | |
| +------------+---------+------+-----+---------+----------------+ |
| | attendance | int(11) | NO | | | | |
| +------------+---------+------+-----+---------+----------------+ |
| | grade | int(11) | NO | | | | |
| +------------+---------+------+-----+---------+----------------+ |
| |
| student |
| +-----------+--------------+------+-----+---------+----------------+ |
| | Field | Type | Null | Key | Default | Extra | |
| +-----------+--------------+------+-----+---------+----------------+ |
| | studentId | int(11) | NO | PRI | | auto_increment | |
| +-----------+--------------+------+-----+---------+----------------+ |
| | fullName | varchar(100) | NO | | | | |
| +-----------+--------------+------+-----+---------+----------------+ |
| |
| testtable |
| +-----------------------------------------+---------------+------+-----+---------+-------+ |
| | Field | Type | Null | Key | Default | Extra | |
| +-----------------------------------------+---------------+------+-----+---------+-------+ |
| | noPKhere | int(11) | NO | | | | |
| +-----------------------------------------+---------------+------+-----+---------+-------+ |
| | veryLongColumnName_And_Then.Some_%_More | decimal(12,2) | YES | | | | |
| +-----------------------------------------+---------------+------+-----+---------+-------+ |
| | limit | int(11) | NO | | | | |
| +-----------------------------------------+---------------+------+-----+---------+-------+ |
| |
| testtable2 |
| +-------+---------+------+-----+---------+-------+ |
| | Field | Type | Null | Key | Default | Extra | |
| +-------+---------+------+-----+---------+-------+ |
| | id | int(11) | NO | PRI | | | |
| +-------+---------+------+-----+---------+-------+ |
+--------------------------------------------------------------------------------------------+
Reporting101a 的数据库创建用于容纳两个存储过程和一些支持表。这些例程通过调用存储过程开始,该存储过程引用要使用字符串报告的数据库。INFORMATION_SCHEMA 访问产生输出的数据。以只读安全的方式访问数据库。因此,不会触及正在报告的数据库。reportDataDefsSession - 用于获取 session 的简单表# reportDataDefs - 从 INFORMATION_SCHEMA 返回的数据并按摩了一下。它是基于 session 的。 reportOutput - 用于打印打印的表,如 MySQL 的 DESCRIBE .它只是一个将输出放在一起的表格。它是基于 session 的。 INT变量包含为 OUT参数目标,写入并允许您在第一个存储过程准备数据后插入其他代码。它代表一个 session #,它隔离输出以供以后报告。Cursor DECLARE 在第二个存储过程的顶部。和 DECLARE s 必须出现在存储过程的顶部。所以我双手被绑,走上了这条路。describe myTable INT OUT保持 session 的参数 # describe 的 pretty-print 存储过程吗? - 类似的输出。如果您决定将参数 4 传递为 FALSE ,那么您的输出可能类似于: 
关于mysql - 将 MySQL 模式转换为 Github Wiki?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38665946/
我的目标是转换表单输入,例如“100兆字节”或“1GB”,并将其转换为我可以存储在数据库中的文件大小(以千字节为单位)。目前,我有这个:defquota_convert@regex=/([0-9]+)(.*)s/@sizes=%w{kilobytemegabytegigabyte}m=self.quota.match(@regex)if@sizes.include?m[2]eval("self.quota=#{m[1]}.#{m[2]}")endend这有效,但前提是输入是倍数(“gigabytes”,而不是“gigabyte”)并且由于使用了eval看起来疯狂不安全。所以,功能正常,
我有一个模型:classItem项目有一个属性“商店”基于存储的值,我希望Item对象对特定方法具有不同的行为。Rails中是否有针对此的通用设计模式?如果方法中没有大的if-else语句,这是如何干净利落地完成的? 最佳答案 通常通过Single-TableInheritance. 关于ruby-on-rails-Rails-子类化模型的设计模式是什么?,我们在StackOverflow上找到一个类似的问题: https://stackoverflow.co
我想将html转换为纯文本。不过,我不想只删除标签,我想智能地保留尽可能多的格式。为插入换行符标签,检测段落并格式化它们等。输入非常简单,通常是格式良好的html(不是整个文档,只是一堆内容,通常没有anchor或图像)。我可以将几个正则表达式放在一起,让我达到80%,但我认为可能有一些现有的解决方案更智能。 最佳答案 首先,不要尝试为此使用正则表达式。很有可能你会想出一个脆弱/脆弱的解决方案,它会随着HTML的变化而崩溃,或者很难管理和维护。您可以使用Nokogiri快速解析HTML并提取文本:require'nokogiri'h
我主要使用Ruby来执行此操作,但到目前为止我的攻击计划如下:使用gemsrdf、rdf-rdfa和rdf-microdata或mida来解析给定任何URI的数据。我认为最好映射到像schema.org这样的统一模式,例如使用这个yaml文件,它试图描述数据词汇表和opengraph到schema.org之间的转换:#SchemaXtoschema.orgconversion#data-vocabularyDV:name:namestreet-address:streetAddressregion:addressRegionlocality:addressLocalityphoto:i
我需要读入一个包含数字列表的文件。此代码读取文件并将其放入二维数组中。现在我需要获取数组中所有数字的平均值,但我需要将数组的内容更改为int。有什么想法可以将to_i方法放在哪里吗?ClassTerraindefinitializefile_name@input=IO.readlines(file_name)#readinfile@size=@input[0].to_i@land=[@size]x=1whilex 最佳答案 只需将数组映射为整数:@land边注如果你想得到一条线的平均值,你可以这样做:values=@input[x]
这道题是thisquestion的逆题.给定一个散列,每个键都有一个数组,例如{[:a,:b,:c]=>1,[:a,:b,:d]=>2,[:a,:e]=>3,[:f]=>4,}将其转换为嵌套哈希的最佳方法是什么{:a=>{:b=>{:c=>1,:d=>2},:e=>3,},:f=>4,} 最佳答案 这是一个迭代的解决方案,递归的解决方案留给读者作为练习:defconvert(h={})ret={}h.eachdo|k,v|node=retk[0..-2].each{|x|node[x]||={};node=node[x]}node[
鉴于我有以下迁移:Sequel.migrationdoupdoalter_table:usersdoadd_column:is_admin,:default=>falseend#SequelrunsaDESCRIBEtablestatement,whenthemodelisloaded.#Atthispoint,itdoesnotknowthatusershaveais_adminflag.#Soitfails.@user=User.find(:email=>"admin@fancy-startup.example")@user.is_admin=true@user.save!ende
我正在使用Rails构建一个简单的聊天应用程序。当用户输入url时,我希望将其输出为html链接(即“url”)。我想知道在Ruby中是否有任何库或众所周知的方法可以做到这一点。如果没有,我有一些不错的正则表达式示例代码可以使用... 最佳答案 查看auto_linkRails提供的辅助方法。这会将所有URL和电子邮件地址变成可点击的链接(htmlanchor标记)。这是文档中的代码示例。auto_link("Gotohttp://www.rubyonrails.organdsayhellotodavid@loudthinking.
给定一个复杂的对象层次结构,幸运的是它不包含循环引用,我如何实现支持各种格式的序列化?我不是来讨论实际实现的。相反,我正在寻找可能会派上用场的设计模式提示。更准确地说:我正在使用Ruby,我想解析XML和JSON数据以构建复杂的对象层次结构。此外,应该可以将该层次结构序列化为JSON、XML和可能的HTML。我可以为此使用Builder模式吗?在任何提到的情况下,我都有某种结构化数据-无论是在内存中还是文本中-我想用它来构建其他东西。我认为将序列化逻辑与实际业务逻辑分开会很好,这样我以后就可以轻松支持多种XML格式。 最佳答案 我最
我收到格式为的回复#我需要将其转换为哈希值(针对活跃商家)。目前我正在遍历变量并执行此操作:response.instance_variables.eachdo|r|my_hash.merge!(r.to_s.delete("@").intern=>response.instance_eval(r.to_s.delete("@")))end这有效,它将生成{:first="charlie",:last=>"kelly"},但它似乎有点hacky和不稳定。有更好的方法吗?编辑:我刚刚意识到我可以使用instance_variable_get作为该等式的第二部分,但这仍然是主要问题。