如何设置一个基本的 Ruby 项目?

我想创建一个有10 ~ 20个类/文件的小型 Ruby 项目。我需要一些 gems,我想使用 RSpec 作为测试框架。

我可能想建立一个宝石以后,但这是不确定的。

是否有一些如何或指南,告诉我如何建立我的项目的基本结构?

我的问题是:

  • 我把所有的自定义错误/异常放在哪里?
  • 对于命名 lib、 bin、 src 等目录是否有一些约定?
  • 测试数据或文档放在哪里?
  • 我在哪里需要我的所有文件,以便在我的项目中访问它们?

我知道我可以从头开始做任何事情,但是我需要一些指导。有一些很好的宝石,我可以复制,但我不确定我真正需要什么,我可以删除。

我看了 http://gembundler.com/,但在设置好 Bundler 之后就停止了。

53589 次浏览

Here are the conventions I have most often seen (assuming your project's name is "foo"):

  • /lib/foo.rb - Defines the top-level namespace of the project and its version; requires needed files.
  • /lib/foo/ - Contains all classes for your project, including error-related classes.
  • /test/ - Contains tests for your project.
  • /spec/ - Contains the specs for your project.
  • /bin/ - If your project depends on binaries (JAR files, etc.), they usually go in there.

Inside lib/, the convention is usually to create a folder for each sub-namespace inside your top-level namespace. For example, the class Foo::Bar::Baz is usually found under /lib/foo/bar/baz.rb.

Some people like to create a /lib/foo/version.rb file just to set the Foo::VERSION constant, but very often I have seen this defined in the /lib/foo.rb file.

Also, if you are creating a gem, you will need the following files:

  • /Rakefile - Defines rake tasks (such as tasks for testing, building and pushing the gem).
  • /Gemfile - Defines the source of the gem (among other possible things).
  • /foo.gemspec - Describes your gem and provides a list of dependencies.

To get a good start, you can use the bundle gem command and rspec --init.

~/code $ bundle gem my_lib
create  my_lib/Gemfile
create  my_lib/Rakefile
create  my_lib/LICENSE.txt
create  my_lib/README.md
create  my_lib/.gitignore
create  my_lib/my_lib.gemspec
create  my_lib/lib/my_lib.rb
create  my_lib/lib/my_lib/version.rb
Initializating git repo in /Users/john/code/my_lib
~/code $ cd my_lib/
~/code/my_lib $ git commit -m "Empty project"
~/code/my_lib $ rspec --init
The --configure option no longer needs any arguments, so true was ignored.
create   spec/spec_helper.rb
create   .rspec
  • code goes in lib
  • specs go in spec
  • test data or documents go in spec/fixtures/
  • Require all your ruby files in lib/my_lib.rb. You can define your exceptions in that file, too, or in their own files -- according to your own preference.
  • C source files go in ext/my_lib
  • shell scripts and executables go in bin

When in doubt, just look at how other gems are laid out.


Further information:

You should add rspec as a development dependency in your gemspec to make things easier for other developers

  1. Edit my_lib.gemspec, adding gem.add_development_dependency 'rspec' and gem.add_development_dependency 'rake' near the bottom.
  2. Add Bundler.setup and require 'my_lib' to the top of spec/spec_helper.rb to ensure your gem dependencies are loaded when you run your specs.
  3. Add require "rspec/core/rake_task" and task :default => :spec to your Rakefile, so that running rake will run your specs.

While you're working on your newest creation, guard-rspec can save you time and hassle by automatically running your specs as files change, alerting you to spec failures.

~/code/my_lib $ git add spec/spec_helper.rb
~/code/my_lib $ git commit -am "Add RSpec"
~/code/my_lib $ vim my_lib.gemspec # add guard development dependency
~/code/my_lib $ bundle
~/code/my_lib $ bundle exec guard init
~/code/my_lib $ vim Guardfile # Remove the sections below the top one
~/code/my_lib $ git add Guardfile
~/code/my_lib $ git commit -am "Add Guard"

After you're happy with your creation, push it up to github

# create a github repository for your gem, then push it up
~/code/my_lib $ curl -u myusername https://api.github.com/user/repos -d '{"name":"my_lib"}'
~/code/my_lib $ git remote add origin git@github.com:myusername/my_lib.git
~/code/my_lib $ git push

Then, when you're ready to release your gem on Rubygems.org, run rake release, which will walk you through the steps.

~/code/my_lib $ rake release

Further References

There are some nice guides at rubygems.org that will introduce you to the conventions and the reasoning behind some of them. In general, the Rubygems naming and directory conventions are followed by most Ruby developers.

I would only create custom exception classes if I wasn't able to find any class in the standard library fits the error description. Nest your error class under the class or module that raises it:

class Parser::Error < RuntimeError; end


begin
Parser.new(:invalid).parse!
rescue Parser::Error => e
puts e.message
end

Unit tests go either into /test, if you're using Test::Unit, or into /spec if you're using RSpec. I recommend the latter.

Bundler is a great way to manage your load path. It will automatically set up your environment with only the dependencies specified on the Gemfile and optionally the gemspec. It also allows you to easily require your code without making it a gem.

However, since you might bundle your code in a gem in the future, I recommend investigating how to create gem specifications. You should write your specification manually. Don't use some tool to automagically generate it - they are, in my opinion, brute force approaches that needlessly duplicate information and wreak havoc when used with source control.

I created a gem which you may find useful. Given a gemspec file, it defines many useful Rake tasks for working with your gem, which include tasks for building, installing and releasing your gem to rubygems and git repository with automatic version tagging. It also provides an easy way to load your code in a irb or pry session.

# Rakefile
require 'rookie'


# Run `rake -T` for the complete task list
Rookie::Tasks.new('your_gem.gemspec').define_tasks!

There're some guides on the internet about how to structure a Ruby project. Besides, I think the best way to solve this is heading over github and looking for some famous Ruby project, and check "their" structures.

Besides general ruby gem requirements, I recommend the following tools for better workflow:

  • editorconfig , helps developers define and maintain consistent coding styles between different editors and IDEs.
  • rubocop , static code analyzer for ruby, the defac to linter in ruby community.
  • guard , together with a bunch of plugins, you can run any commands as you like when code changes, automatically.
  • rake , the universal driver for various project tasks, such as:
    • package: build gem package
    • clean: clean generated files
    • test: run test
  • yard , popular ruby documentation tool.

And besides all of the above tools, their're some online service for ruby project:

And you can even genearate badges via http://shields.io/ for your open source project.

That's my experience, hope it helps for some one.