典型的RSpec单元测试广泛使用嵌套的Ruby块,以便构造代码并利用DSL"魔力"将规范读取为BDD语句:
describe Foo do
context "with a bar" do
before :each do
subject { Foo.new().add_bar }
end
it "looks like a baz" do
expect # etc
Run Code Online (Sandbox Code Playgroud)
在理想规范中,每个示例可以相对较短且精确.然而,似乎通常将外部块增加到100行以上,因为RSpec结构以这种方式工作,并且不需要许多规范示例,每个示例可能具有几行特定设置,以获得describe块,即与所描述的主题的代码相同或更大.
Rubocop最近的一次升级带来了新的规则,即块不应超过25行.我不确定它的基本原理,因为它没有在Ruby样式指南中列出.我可以看到为什么它可能是一件好事,并添加到默认规则集.但是,在升级之后,我们的Rubocop测试会多次失败并显示消息tests/component_spec.rb:151:3: C: Block has too many lines. [68/25]
使用代码度量工具(如Rubocop),我喜欢使用"使用默认值,链接到样式指南,完成工作"的策略.(主要是因为辩论标签与空格和其他细节是浪费时间,IME 永远不会得到解决)这显然是不可能的,我们的两个核心数据质量工具不同意代码布局方法 - 或者至少我是如何解释结果的,我没有看到我们如何编写规范本质上有任何错误.
作为回应,我们只是将Rubocop块大小规则设置为高阈值.但这让我想知道 - 我错过了什么?RSpec是否使用了现在已经失去信誉的代码布局方法,以及我在RSpec测试中减少块大小的合理选择是什么?我可以看到重构代码以避免大块的方法,但它们毫无例外地纯粹是为了满足Rubocop规则的丑陋黑客,例如将所有块分解为辅助函数:
def looks_like_a_baz
it "looks like a baz" do
expect # etc
end
end
def bar_context
context "with a bar" do
before :each do
subject { Foo.new().add_bar }
end …Run Code Online (Sandbox Code Playgroud) 我正在开发一个gem,它目前是纯Ruby,但我也一直在为其中一个功能开发一个更快的C变种.该功能在纯Ruby中可用,但有时很慢.缓慢只会影响一些潜在用户(取决于他们需要哪些功能,以及他们如何使用它们),因此如果无法在目标系统上编译,那么将gem提供给具有Ruby功能的优雅回退是有意义的.
我想在一个gem中维护该功能的Ruby和C变体,并在安装时提供gem的最佳(即最快)体验.这将使我能够从我的一个项目中支持最广泛的潜在用户.它还允许其他人的依赖宝石和项目使用目标系统上最好的可用依赖性,而不是兼容性最低的通用分母版本.
我希望require在运行时回退出现在主lib/foo.rb文件中,就像这样:
begin
require 'foo/foo_extended'
rescue LoadError
require 'foo/ext_bits_as_pure_ruby'
end
Run Code Online (Sandbox Code Playgroud)
但是,我不知道如何让gem安装检查(或尝试和失败)本机扩展支持,以便gem安装正确,无论它是否可以构建'foo_extended'.当我研究如何做到这一点时,我主要发现了几年前的讨论,例如http://permalink.gmane.org/gmane.comp.lang.ruby.gems.devel/1479和http://rubyforge.org/ pipermail/rubygems-developers/2007-November/003220.html暗示Ruby宝石并不真正支持这一功能.最近没有什么,所以我希望SO上的某些人有更多最新的知识?
我的理想解决方案是在尝试构建扩展之前检测目标Ruby不支持(或者可能根本不希望在项目级别)C本机扩展的方法.但是,如果不是太脏,尝试/捕获机制也可以.
这有可能,如果是这样的话怎么样?或者建议发布两个宝石变体(例如foo和foo_ruby),我在搜索时发现,仍然是目前的最佳实践?
我有一个小型的原型子类Grape::API作为机架服务,并Grape::Entity用于呈现我的应用程序的内部对象.
我喜欢Grape::EntityDSL,但我很难找到我应该超越默认的JSON表示,这对我们来说太轻了.我被要求以"jsend或类似"格式生成输出:http://labs.omniti.com/labs/jsend
我完全不确定改变的性质与Grape框架最相符(我想在这里采用最小阻力路径).我应该创建一个自定义的Grape格式化程序(我不知道如何做到这一点),新的机架中间件(我这样做是为了通过SysLog记录API输入/输出 - 但格式化似乎很糟糕,因为我需要解析正文从JSON返回以添加容器级别),或者更改Grape::Entity为例如RABL?
示例代码("app.rb")
require "grape"
require "grape-entity"
class Thing
def initialize llama_name
@llama_name = llama_name
end
attr_reader :llama_name
end
class ThingPresenter < Grape::Entity
expose :llama_name
end
class MainService < Grape::API
prefix 'api'
version 'v2'
format :json
rescue_from :all
resource :thing do
get do
thing = Thing.new 'Henry'
present thing, :with => ThingPresenter
end
end
end
Run Code Online (Sandbox Code Playgroud)
Rackup文件("config.ru")
require File.join(File.dirname(__FILE__), "app")
run MainService
Run Code Online (Sandbox Code Playgroud)
我启动它:
rackup -p 8090 …Run Code Online (Sandbox Code Playgroud) 在我的应用程序中,我有一个名为@appsActiveRecord 的数组,其中包含一个包含应用程序名称,环境等的记录.
我目前正在使用@apps.count数组中的应用程序数量,但我无法计算数组中的应用程序数量environment = 0.
我尝试@apps.count(0)但是没有用,因为每条记录都有多个字段.
我也尝试了类似@apps.count{ |environment| environment = 0}但没有发生的事情.
有什么建议?
我想知道使用MRI ruby(2.0.0)和一些全局变量来制作竞争条件是否容易,但事实证明它并不那么容易.看起来它应该在某些时候失败,但它没有,我已经运行了10分钟.这是我一直试图实现的代码:
def inc(*)
a = $x
a += 1
a *= 3000
a /= 3000
$x = a
end
THREADS = 10
COUNT = 5000
loop do
$x = 1
THREADS.times.map do Thread.new { COUNT.times(&method(:inc)) } end.each(&:join)
break puts "woo hoo!" if $x != THREADS * COUNT + 1
end
puts $x
Run Code Online (Sandbox Code Playgroud)
为什么我无法生成(或检测)预期的竞争条件,并woo hoo!在Ruby MRI 2.0.0中获得输出?
我试图在Mac OS X Lion(XCode 4.3 + OSX GCC Installer + Homebrew)上守卫
错误信息:
Library not loaded: /opt/local/lib/libffi.5.dylib
Run Code Online (Sandbox Code Playgroud)
我没有/opt/local目录,因为我没有使用MacPorts而是使用Homebrew
我试过brew install libffi,这是成功的,但宝石仍然无法正常工作.
我也尝试过卸载并重新安装gem但没有成功.
apple-gcc42安装了OSX 10.9(Mavericks)时也会出现问题.
我也试过告诉gemlibffi的存在如下:
gem install ffi:1.0.7 -- --with-ldflags='-L/usr/local/opt/libffi/lib'
我被要求设计和实现RESTful API,并且一直在研究最佳实践,但到目前为止,只有一个关于资源表示的愚蠢概念.我发现的大多数可用示例似乎都非常关注使用一系列GET来连接结构的API客户端.
我看过:
http://www.restapitutorial.com/media/RESTful_Best_Practices-v1_1.pdf
http://www.youtube.com/watch?v=HW9wWZHWhnI
在其他在线资源(我限于2个链接抱歉不能列出所有).它们都很棒,但并没有真正解决我的设计问题.
大多数最佳实践文档都提出了两件让我看起来有点冲突的事情:
1)REST服务应将数据关系表示为资源之间的链接
2)来自客户端的"PUT"请求应该是完整的表示,形式与服务器上看到的表示形式相同.
从我的观点来看,问题在于链接以及典型资源中的其他一些属性是只读的,因此无法更新.该服务器可以预期它们按原样运行,如果它认为客户端正在尝试更新它们,则会返回错误.事实上,当我查看JSON中表示的典型资源时,其中大部分是逻辑上不能/不应该替换的数据.例如
{
"link": { "rel":"self", "href":"http://example/project/12345" },
"team": {
"link": { "rel":"self", "href":"http://example/project/12345/team" },
"title": "The project team"
},
"title": "The Big Project"
}
Run Code Online (Sandbox Code Playgroud)
在这里,最多只有两个标题文本可以写入该资源上的客户端(团队成员资格可以通过团队链接进行更改).
因此,我是否应该要求PUT完全按原样包含所有"链接"元素,这些元素纯粹是逻辑和只读的(注意在示例中,团队无法重新链接,因为资源将其定义为团队对于项目 - 在这种情况下可以改变,但对于许多具有更严格的集装箱船的资源类型,这不适用)?
是否有标准模式或反模式用于在REST中表示具有许多链接的资源?我没有被要求提供特定的REST变体,例如HATEOAS,尽管我倾向于在可能的情况下瞄准理论上的"正确性".换句话说,如果"官方"REST将期望客户端将整个资源,链接和所有内容投入,那么这可能就是我要做的.
支持GET和PUT的现实世界复杂的非叶子REST资源的一些示例,因此必须处理这个问题,将非常感激.当我搜索时,我得到了很多意见,并且很多例子显示了GET的工作原理...但到目前为止,我还没有看到一个记录良好的示例,显示PUT除了一个简单的叶子资源(即一个不包含任何链接,除了自我引用之外).
我正在为我的毕业最终项目开发一个创业板,而Travis CI的建设却在不断失败.
这是我在特拉维斯的链接:https://travis-ci.org/ricardobond/perpetuus/builds/8709218
构建错误是:
$ bundle exec rake
rake aborted!
Don't know how to build task 'default'
/home/travis/.rvm/gems/ruby-1.9.3-p448/bin/ruby_noexec_wrapper:14:in `eval'
/home/travis/.rvm/gems/ruby-1.9.3-p448/bin/ruby_noexec_wrapper:14:in `<main>'
(See full trace by running task with --trace)
The command "bundle exec rake" exited with 1.
Done. Your build exited with 1.
Run Code Online (Sandbox Code Playgroud)
以下是我的 perpetuus.gemspec
# coding: utf-8
lib = File.expand_path('../lib', __FILE__)
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
require 'perpetuus/version'
Gem::Specification.new do |spec|
spec.name = "perpetuus"
spec.version = Perpetuus::VERSION
spec.authors = ["Ricardo Caldeira"]
spec.email = ["ricardo.nezz@gmail.com"]
spec.description = %q{A continuous …Run Code Online (Sandbox Code Playgroud) 每当我尝试运行程序时,会弹出一个错误,说"条件中的字符串文字(第10行)".我究竟做错了什么?
puts "Welcome to the best calculator there is. Would you like to (a) calculate the area of a geometric shape or (b) calculate the equation of a parabola? Please enter an 'a' or a 'b' to get started."
response = gets.chomp
if response == "a" or "A"
puts "ok."
elsif response == "b" or "B"
puts "awesome."
else
puts "I'm sorry. I did not get that. Please try again."
end
Run Code Online (Sandbox Code Playgroud) 我正在研究一个需要存储大量简单,可扩展数据的数据系统(以及我们在内部开发的一些专业索引,而不是这个问题的一部分).我希望存储数十亿条记录,因此高效的序列化是系统的关键部分.序列化需要快速,节省空间,并且支持多种平台和语言(因为打包和解包这些数据将是客户端组件的责任,而不是存储系统的一部分)
数据类型实际上是具有可选键/值对的散列.键将是小整数(在应用程序层解释).值可以是各种简单数据类型 - String,Integer,Float.
作为一种技术选择,我们选择了MessagePack,并且我正在编写代码来通过Ruby的msgpack-ruby gem 执行数据序列化.
我不需要Ruby的64位Float的精度.即使对于32位的限制,存储的数字也没有任何有意义的精度.所以我想使用MessagePack支持32位浮点值.这肯定存在.但是,Ruby在任何64位系统上的默认行为是将Float序列化为64位:
MessagePack.pack(10.3)
=> "\xCB@$\x99\x99\x99\x99\x99\x9A"
Run Code Online (Sandbox Code Playgroud)
看看MessagePack代码,似乎有一种方法MessagePack::Packer#write_float32,这就是我所期望的:
MessagePack::DefaultFactory.packer.write_float32(10.3).to_s
=> "\xCAA$\xCC\xCD"
Run Code Online (Sandbox Code Playgroud)
...但我找不到设置默认打包器或创建新打包器的方法,在序列化更大的结构时将使用此方法.
作为对我的理解的考验,我尝试了这个:
class Float
def to_msgpack_ext
packer.write_float32(self)
end
def self.from_msgpack_ext s
unpacker.read(s)
end
end
MessagePack::DefaultFactory.register_type(0, Float )
MessagePack.pack(10.3)
=> "\xCB@$\x99\x99\x99\x99\x99\x9A"
Run Code Online (Sandbox Code Playgroud)
没有任何区别...很明显,我对MessagePack中使用的对象模型缺失或误解.我想做什么,我需要做什么?