标签: ruby

Ruby中的方法:对象与否?

受到这种讨论的启发,经过一些谷歌搜索后,我无法找到关于Ruby方法的一个非常简单的问题的答案:方法对象与否?

这里那里有不同的意见,我真的想听听,比方说,深入解释.

我知道Object#method方法,它接受一个方法名称并返回一个Method实例,但另一方面,你可以用块做类似的事情来使它们成为Proc实例,而块不是对象,所以是什么使得方法有什么不同?

ruby methods language-features object

43
推荐指数
3
解决办法
9538
查看次数

为什么Matz默认在Ruby中选择使Strings变为可变?

这与此问题相反:为什么字符串在Java和.NET中不可变?

这种选择是否仅仅因为操作(追加等)在可变字符串上有效,或者是否有其他原因而在Ruby中进行?

(如果它只是效率,那似乎很奇怪,因为Ruby的设计似乎不会高度重视促进有效的实施.)

ruby string language-design mutable immutability

43
推荐指数
2
解决办法
6224
查看次数

我如何要求特定版本的红宝石宝石?

具体来说,红宝石oci8宝石.我安装了1.0.7和2.0.4.我想要1.0.7.

我可以只需要oci8,但我没有得到我想要的版本.

irb(main):001:0> require 'oci8'
=> true
irb(main):002:0> OCI8::VERSION
=> "2.0.4"
Run Code Online (Sandbox Code Playgroud)

我可以要求使用文件的完整路径,它可以工作,但不会是可移植的:

irb(main):001:0> require 'C:\Ruby\lib\ruby\gems\1.8\gems\ruby-oci8-1.0.7-x86-mswin32-60\lib\oci8'
=> true
irb(main):002:0> OCI8::VERSION
=> "1.0.7"
Run Code Online (Sandbox Code Playgroud)

我可以使用gem命令来询问我想要的版本,但它似乎没有实际加载库:

irb(main):001:0> gem 'ruby-oci8', :lib=>'oci8', :version=>'=1.0.7'
=> true
irb(main):002:0> OCI8::VERSION
NameError: uninitialized constant OCI8
    from (irb):2
Run Code Online (Sandbox Code Playgroud)

如果加载库,我肯定会支持这种最后的方法,而不仅仅是确认它存在于我的系统中.我错过了什么?

ruby gem version oci8

43
推荐指数
1
解决办法
3万
查看次数

Rebase Rails在长期运行的项目中进行迁移

我在字典中的意思是"变基",而不是git定义......

我有一个大型的,长期运行的Rails项目,大约有250次迁移,所以要管理所有这些项目变得笨拙.

也就是说,我确实需要一个基础来运行测试时清除和重建我的数据库.因此,这些数据非常重要.

是否有任何策略可以说,将模式转储到设定点 - 归档所有旧迁移并重新开始新的迁移.

显然我可以使用rake schema:dump - 但实际上我需要一种方法db:migrate将首先加载模式然后开始运行其余的迁移.

我想继续使用迁移,因为它们在开发中非常有用,但是,我无法回溯并编辑2007年的迁移,因此保留它似乎很愚蠢.

ruby database migration ruby-on-rails

43
推荐指数
2
解决办法
8776
查看次数

object_id赋值如何工作?

我正在玩Ruby,.object_id并注意到,在irb的几个连续会话中,我得到了相同的结果:

false.object_id // 0
true.object_id // 2
nil.object_id // 4
100.object_id // 201
Run Code Online (Sandbox Code Playgroud)

实际上,每个整数的object_id似乎都是((value*2)+ 1).

另一方面,在退出并重新运行irb之后,给定字符串的object_id永远不会相同.

这为我提出了几个问题:

  1. 是否有已知的方案object_id确定某些s?其他人基本上是随机的
  2. true,false和nil的id不是顺序的.有没有办法询问给定id表示的对象是什么?(我很好奇其他一位数和ids的关系.)
  3. 你可以(不是你应该)编写模糊的Ruby,你使用已知的对象id引用对象而不命名它们,比如"id 201的对象+ id为19的对象"意味着"100 + 9"?

更新

使用Andrew Grimm的建议,我尝试发现其他"低id"对象,但发现:

  • 在这个序列中似乎没有任何更多的偶数对象 - ids 6,8,10等不指向任何东西.
  • 正如我之前的实验所暗示的那样,所有奇数编号的id都属于数字.具体地,id 1指向数字0,3指向1,5指向2,依此类推.

ruby internals

43
推荐指数
2
解决办法
1万
查看次数

rbenv:没有宝石的幸存

TL; DR

  • 不要打扰宝石; 可以同时安装多个版本的gem.
  • 必要时,使用$ gem-based-binary _version_ args表示法指定要执行的版本.
  • 使用bundle exec指定版本的Gemfile时使用.
gem install rails -v 3.2.13
rails _3.2.13_ new Project2
cd Project2
bundle exec rails server
Run Code Online (Sandbox Code Playgroud)

更新时间: 2015-06-04

我三年前写过这个问题.部分地,它是基于错误的假设,部分情况从那时起发生了变化.感谢@indirect的原始答案,我想提请注意@kelvin的更新(不太热烈)的答案,如上所述.

我的错误假设:一次只能安装一个gem的单个版本,因此需要gemsets来隔离命名空间.不对.可以同时安装多个版本的gem.从命令行调用时将使用最新的一个,除非您有一个Gemfile指定版本约束并通过命令调用命令bundle exec,或指定版本作为其第一个参数.

另请参阅如何从命令行调用旧版本的gem?re:下划线版本表示法.


原始问题:

我有多个项目正在使用不同版本的Rails.我有一个工作流程(如下所述),用于使用特定版本的rails创建项目,并保持项目彼此隔离.我想尝试其他工作流程,特别是使用rbenv而不是RVM,但目前尚不清楚如何这样做.

问题:当使用rbenvbundler而不是rbenv-gemset或rvm 时,创建多个rails项目 的最佳当前实践是什么,每个项目使用不同版本的rails .

用例: 我有两个rails项目,名为ProjectA和ProjectB.ProjectA是使用一个版本的rails("RailsA")开发的,而ProjectB使用不同的版本("RailsB").如何安装两个版本?

GEMSETS方法: 当我第一次开始使用Rails开发时,我使用了RVM.除了支持多个并发安装的ruby之外,RVM还支持具有多个命名宝石集.每个项目都有自己独立的宝石集合(包括rails本身),称为gemset:

rvm gemset create RailsA
rvm gemset use RailsA
# RailsA.  Note: My question is not version-specific.
gem install rails --version …
Run Code Online (Sandbox Code Playgroud)

ruby rubygems ruby-on-rails bundler rbenv

43
推荐指数
3
解决办法
1万
查看次数

查找两个数组之间的共同值

如果我想比较两个数组,并创建一个插值输出字符串,如果从数组的数组变量y中存在x我怎么能获得每个匹配元素的输出?

这就是我的尝试但却没有得到结果.

x = [1, 2, 4]
y = [5, 2, 4]
x.each do |num|
  puts " The number #{num} is in the array" if x.include?(y.each)
end #=> [1, 2, 4]
Run Code Online (Sandbox Code Playgroud)

ruby

43
推荐指数
2
解决办法
3万
查看次数

测试:如何在不降低速度的情况下专注于行为而非实施?

似乎有两种完全不同的测试方法,我想引用它们.

问题是,这些意见是在5年前(2007年)提出的,我感兴趣的是,从那以后发生了什么变化以及我应该走哪条路.

Brandon Keepers:

理论是测试应该与实现无关.这导致较少的脆弱测试并且实际测试结果(或行为).

使用RSpec,我觉得完全模拟模型来测试控制器的常见方法最终会迫使您过多地研究控制器的实现.

这本身并不算太糟糕,但问题在于它与控制器过多地对齐以决定模型的使用方式.如果我的控制器调用Thing.new,为什么重要?如果我的控制器决定采取Thing.create怎么办?和救援路线?如果我的模型有一个特殊的初始化方法,比如Thing.build_with_foo怎么办?如果我改变实现,我的行为规范不应该失败.

当您拥有嵌套资源并为每个控制器创建多个模型时,此问题会变得更糟.我的一些设置方法最终会长达15行或更长,而且非常脆弱.

RSpec的目的是将您的控制器逻辑与模型完全隔离,理论上听起来不错,但几乎与Rails等集成堆栈相反.特别是如果你练习瘦的控制器/胖模型规则,控制器中的逻辑量变得非常小,并且设置变得很大.

那么BDD想做什么呢?退后一步,我真正想要测试的行为不是我的控制器调用Thing.new,而是给定参数X,它会创建一个新东西并重定向到它.

大卫切林斯基:

这都是权衡利弊.

AR选择继承而非委托的事实使我们处于测试绑定中 - 我们必须与数据库耦合或者我们必须更加密切地与实现相关联.我们接受这种设计选择,因为我们在表现力和干燥方面获益.

在应对困境时,我选择了更快的测试,但代价是更脆弱.你选择较少的脆弱测试,但代价是它们的运行速度稍慢.无论哪种方式,这都是一种权衡.

在实践中,我每天运行数百次(如果不是数千次)测试(我使用自动测试并采取非常精细的步骤)并且我改变我是否使用"新"或"创建"几乎从不.同样由于细化步骤,出现的新模型起初非常不稳定.valid_thing_attrs方法可以最大限度地减少这种痛苦,但它仍然意味着每个新的必填字段意味着我必须更改valid_thing_attrs.

但是如果你的方法在实践中对你有用,那就好了!事实上,我强烈建议您发布一个带有生成器的插件,这些插件可以按您喜欢的方式生成示例.我相信很多人都会从中受益.

瑞恩贝茨:

出于好奇,您在测试/规格中多久使用一次模拟?也许我做错了什么,但我发现它严重限制.自从一个月前切换到rSpec以来,我一直在他们推荐的文档中,控制器和视图层根本没有访问数据库,模型完全被模拟了.这为你提供了一个很好的速度提升并使一些事情变得更容易,但我发现这样做的缺点远远超过了职业选手.自从使用嘲笑以来,我的规格变成了维护噩梦.规范旨在测试行为,而不是实现.我不在乎是否调用了一个方法我只是想确保结果输出是正确的.因为mocking使得规范对于实现很挑剔,所以它使得简单的重构(不改变行为)不可能做到,而不必经常回去并"修复"规范.我非常鄙视规范/测试应涵盖的内容.测试应该只在应用程序中断时中断.这就是为什么我几乎不测试视图层的原因之一,因为我发现它太僵硬了.在视图中更改小东西时,它通常会导致测试中断,而不会破坏应用程序.我发现嘲笑有同样的问题.最重要的是,我今天才意识到,嘲笑/抄袭一个类方法(有时)会在规范之间徘徊.规格应该是自包含的,不受其他规格的影响.这打破了这个规则并导致棘手的错误.我从这一切中学到了什么?在使用模拟的地方要小心.Stubbing并不是那么糟糕,但仍有一些相同的问题.

我花了几个小时从我的规格中删除了几乎所有的模拟.我还使用控制器规范中的"integrate_views"将控制器和视图规范合并为一个.我还为每个控制器规范加载所有灯具,因此有一些测试数据可以填充视图.最终的结果?我的规格更短,更简单,更一致,更不僵硬,并且他们一起测试整个堆栈(模型,视图,控制器),因此没有错误可以穿过裂缝.我不是说这对每个人来说都是"正确"的方式.如果您的项目需要一个非常严格的规范案例,那么它可能不适合您,但在我的情况下,这比使用模拟之前的世界更好.我仍然认为存根是一个很好的解决方案,所以我仍然这样做.

ruby unit-testing rspec ruby-on-rails

43
推荐指数
3
解决办法
3545
查看次数

您的模型创建后FactoryGirl可以生成工厂吗?

当您在dev和Gemfile中的测试块中包含factory_girl_rails gem时,rails会在生成模型时自动生成工厂.

生成模型后有没有办法生成工厂?


Eduardo Santana的答案应该是正确的

ruby ruby-on-rails factory-bot

43
推荐指数
4
解决办法
2万
查看次数

将哈希转换为结构

如何将哈希转换为ruby中的结构?

鉴于这种:

h = { :a => 1, :b => 2 }
Run Code Online (Sandbox Code Playgroud)

我想要一个结构,这样:

s.a == 1
s.b == 2
Run Code Online (Sandbox Code Playgroud)

ruby

43
推荐指数
6
解决办法
2万
查看次数