Projects
Mega:23.09
rubygem-docile
Sign Up
Log In
Username
Password
Overview
Repositories
Revisions
Requests
Users
Attributes
Meta
Expand all
Collapse all
Changes of Revision 3
View file
_service:tar_scm:rubygem-docile.spec
Changed
@@ -1,7 +1,7 @@ %global gem_name docile Summary: Docile keeps your Ruby DSLs tame and well-behaved Name: rubygem-%{gem_name} -Version: 1.1.5 +Version: 1.4.0 Release: 1 License: MIT URL: https://ms-ati.github.com/docile/ @@ -52,10 +52,14 @@ %doc %{gem_docdir} %doc %{gem_instdir}/HISTORY.md %doc %{gem_instdir}/README.md -%{gem_instdir}/on_what.rb %{gem_instdir}/Rakefile -%{gem_instdir}/spec +%exclude %{_datadir}/gems/gems/%{gem_name}-%{version}/.github/* +%exclude %{_datadir}/gems/gems/%{gem_name}-%{version}/.rubocop.yml +%exclude %{_datadir}/gems/gems/%{gem_name}-%{version}/SECURITY.md %changelog +* Mon Nov 13 2023 Ge Wang <wang__Ge@126.com> - 1.4.0-1 +- update to version 1.4.0 + * Sat Aug 22 2020 liyanan <liyanan32@huawei.com> - 1.1.5-1 - package init
View file
_service
Changed
@@ -2,7 +2,7 @@ <service name="tar_scm"> <param name="url">git@gitee.com:src-openeuler/rubygem-docile.git</param> <param name="scm">git</param> - <param name="revision">openEuler-23.09</param> + <param name="revision">master</param> <param name="exclude">*</param> <param name="extract">*</param> </service>
View file
_service:tar_scm:docile-1.1.5.gem/data/.ruby-gemset
Deleted
@@ -1,1 +0,0 @@ -docile
View file
_service:tar_scm:docile-1.1.5.gem/data/.ruby-version
Deleted
@@ -1,1 +0,0 @@ -ruby-2.1.0
View file
_service:tar_scm:docile-1.1.5.gem/data/.travis.yml
Deleted
@@ -1,21 +0,0 @@ -language: ruby -cache: bundler -rvm: - - ruby-head - - 2.1.2 - - 2.1.1 - - 2.1.0 - - 2.0.0 - - 1.9.3 - - 1.9.2 - - 1.8.7 - - ree - - jruby-head - - jruby-19mode - - jruby-18mode - - rbx-2 -matrix: - allow_failures: - - rvm: ruby-head - - rvm: jruby-head - fast_finish: true
View file
_service:tar_scm:docile-1.1.5.gem/data/on_what.rb
Deleted
@@ -1,14 +0,0 @@ -# NOTE: Very simple tests for what system we are on, extracted for sharing -# between Rakefile, gemspec, and spec_helper. Not for use in actual library. - -def on_travis? - ENV'CI' == 'true' -end - -def on_jruby? - (defined?(RUBY_ENGINE) && 'jruby' == RUBY_ENGINE) -end - -def on_1_8? - RUBY_VERSION.start_with? '1.8' -end \ No newline at end of file
View file
_service:tar_scm:docile-1.1.5.gem/data/spec/docile_spec.rb
Deleted
@@ -1,339 +0,0 @@ -require 'spec_helper' -require 'singleton' - -describe Docile do - - describe '.dsl_eval' do - - context 'when DSL context object is an Array' do - let(:array) { } - let!(:result) { execute_dsl_against_array } - - def execute_dsl_against_array - Docile.dsl_eval(array) do - push 1 - push 2 - pop - push 3 - end - end - - it 'executes the block against the DSL context object' do - expect(array).to eq(1, 3) - end - - it 'returns the DSL object after executing block against it' do - expect(result).to eq(array) - end - - it "doesn't proxy #__id__" do - Docile.dsl_eval(array) { expect(__id__).not_to eq(array.__id__) } - end - - it "raises NoMethodError if the DSL object doesn't implement the method" do - expect { Docile.dsl_eval(array) { no_such_method } }.to raise_error(NoMethodError) - end - end - - Pizza = Struct.new(:cheese, :pepperoni, :bacon, :sauce) - - class PizzaBuilder - def cheese(v=true); @cheese = v; end - def pepperoni(v=true); @pepperoni = v; end - def bacon(v=true); @bacon = v; end - def sauce(v=nil); @sauce = v; end - def build - Pizza.new(!!@cheese, !!@pepperoni, !!@bacon, @sauce) - end - end - - context 'when DSL context object is a Builder pattern' do - let(:builder) { PizzaBuilder.new } - let(:result) { execute_dsl_against_builder_and_call_build } - - def execute_dsl_against_builder_and_call_build - @sauce = :extra - Docile.dsl_eval(builder) do - bacon - cheese - sauce @sauce - end.build - end - - it 'returns correctly built object' do - expect(result).to eq(Pizza.new(true, false, true, :extra)) - end - end - - class InnerDSL - def initialize; @b = 'b'; end - attr_accessor :b - end - - class OuterDSL - def initialize; @a = 'a'; end - attr_accessor :a - - def inner(&block) - Docile.dsl_eval(InnerDSL.new, &block) - end - - def inner_with_params(param, &block) - Docile.dsl_eval(InnerDSL.new, param, :foo, &block) - end - end - - def outer(&block) - Docile.dsl_eval(OuterDSL.new, &block) - end - - context 'when given parameters for the DSL block' do - def parameterized(*args, &block) - Docile.dsl_eval(OuterDSL.new, *args, &block) - end - - it 'passes parameters to the block' do - parameterized(1,2,3) do |x,y,z| - expect(x).to eq(1) - expect(y).to eq(2) - expect(z).to eq(3) - end - end - - it 'finds parameters before methods' do - parameterized(1) { |a| expect(a).to eq(1) } - end - - it 'find outer dsl parameters in inner dsl scope' do - parameterized(1,2,3) do |a,b,c| - inner_with_params(c) do |d,e| - expect(a).to eq(1) - expect(b).to eq(2) - expect(c).to eq(3) - expect(d).to eq(c) - expect(e).to eq(:foo) - end - end - end - end - - class DSLWithNoMethod - def initialize(b); @b = b; end - attr_accessor :b - def push_element - @b.push 1 - end - end - - context 'when DSL have NoMethod error inside' do - it 'raise error from nil' do - Docile.dsl_eval(DSLWithNoMethod.new(nil)) do - expect { push_element }.to raise_error(NoMethodError, /undefined method `push' (for|on) nil:NilClass/) - end - end - end - - context 'when DSL blocks are nested' do - - context 'method lookup' do - it 'finds method of outer dsl in outer dsl scope' do - outer { expect(a).to eq('a') } - end - - it 'finds method of inner dsl in inner dsl scope' do - outer { inner { expect(b).to eq('b') } } - end - - it 'finds method of outer dsl in inner dsl scope' do - outer { inner { expect(a).to eq('a') } } - end - - it "finds method of block's context in outer dsl scope" do - def c; 'c'; end - outer { expect(c).to eq('c') } - end - - it "finds method of block's context in inner dsl scope" do - def c; 'c'; end - outer { inner { expect(c).to eq('c') } } - end - - it 'finds method of outer dsl in preference to block context' do - def a; 'not a'; end - outer { expect(a).to eq('a') } - outer { inner { expect(a).to eq('a') } } - end - end - - context 'local variable lookup' do - it 'finds local variable from block context in outer dsl scope' do - foo = 'foo' - outer { expect(foo).to eq('foo') } - end - - it 'finds local variable from block definition in inner dsl scope' do - bar = 'bar' - outer { inner { expect(bar).to eq('bar') } } - end - end - - context 'instance variable lookup' do - it 'finds instance variable from block definition in outer dsl scope' do - @iv1 = 'iv1'; outer { expect(@iv1).to eq('iv1') } - end - - it "proxies instance variable assignments in block in outer dsl scope back into block's context" do - @iv1 = 'foo'; outer { @iv1 = 'bar' }; expect(@iv1).to eq('bar') - end - - it 'finds instance variable from block definition in inner dsl scope' do - @iv2 = 'iv2'; outer { inner { expect(@iv2).to eq('iv2') } } - end - - it "proxies instance variable assignments in block in inner dsl scope back into block's context" do - @iv2 = 'foo'; outer { inner { @iv2 = 'bar' } }; expect(@iv2).to eq('bar') - end - end - - end - - context 'when DSL context object is a Dispatch pattern' do - class DispatchScope - def params - { :a => 1, :b => 2, :c => 3 } - end - end - - class MessageDispatch - include Singleton - - def initialize - @responders = {} - end - - def add_responder path, &block - @responderspath = block - end - - def dispatch path, request - Docile.dsl_eval(DispatchScope.new, request, &@responderspath) - end - end - - def respond(path, &block) - MessageDispatch.instance.add_responder(path, &block) - end - - def send_request(path, request) - MessageDispatch.instance.dispatch(path, request) - end - - it 'dispatches correctly' do - @first = @second = nil - - respond '/path' do |request| - @first = request - end - - respond '/new_bike' do |bike| - @second = "Got a new #{bike}" - end - - def x(y) ; "Got a #{y}"; end - respond '/third' do |third| - expect(x(third)).to eq('Got a third thing') - end - - fourth = nil - respond '/params' do |arg| - fourth = paramsarg - end - - send_request '/path', 1 - send_request '/new_bike', 'ten speed' - send_request '/third', 'third thing' - send_request '/params', :b - - expect(@first).to eq(1) - expect(@second).to eq('Got a new ten speed') - expect(fourth).to eq(2) - end - - end - - end - - describe '.dsl_eval_immutable' do - - context 'when DSL context object is a frozen String' do - let(:original) { "I'm immutable!".freeze } - let!(:result) { execute_non_mutating_dsl_against_string } - - def execute_non_mutating_dsl_against_string - Docile.dsl_eval_immutable(original) do - reverse - upcase - end - end - - it "doesn't modify the original string" do - expect(original).to eq("I'm immutable!") - end - - it 'chains the commands in the block against the DSL context object' do - expect(result).to eq("!ELBATUMMI M'I") - end - end - - context 'when DSL context object is a number' do - let(:original) { 84.5 } - let!(:result) { execute_non_mutating_dsl_against_number } - - def execute_non_mutating_dsl_against_number - Docile.dsl_eval_immutable(original) do - fdiv(2) - floor - end - end - - it 'chains the commands in the block against the DSL context object' do - expect(result).to eq(42) - end - end - end - -end - -describe Docile::FallbackContextProxy do - - describe '#instance_variables' do - subject { create_fcp_and_set_one_instance_variable.instance_variables } - let(:expected_type_of_names) { type_of_ivar_names_on_this_ruby } - let(:actual_type_of_names) { subject.first.class } - let(:excluded) { Docile::FallbackContextProxy::NON_PROXIED_INSTANCE_VARIABLES } - - def create_fcp_and_set_one_instance_variable - fcp = Docile::FallbackContextProxy.new(nil, nil) - fcp.instance_variable_set(:@foo, 'foo') - fcp - end - - def type_of_ivar_names_on_this_ruby - @a = 1 - instance_variables.first.class - end - - it 'returns proxied instance variables' do - expect(subject.map(&:to_sym)).to include(:@foo) - end - - it "doesn't return non-proxied instance variables" do - expect(subject.map(&:to_sym)).not_to include(*excluded) - end - - it 'preserves the type (String or Symbol) of names on this ruby version' do - expect(actual_type_of_names).to eq(expected_type_of_names) - end - end - -end
View file
_service:tar_scm:docile-1.1.5.gem/data/spec/spec_helper.rb
Deleted
@@ -1,30 +0,0 @@ -require File.expand_path('on_what', File.dirname(File.dirname(__FILE__))) - -begin - require 'simplecov' - require 'coveralls' - - # On Ruby 1.9+ use SimpleCov and publish to Coveralls.io - if !on_1_8? - SimpleCov.formatter = SimpleCov::Formatter::MultiFormatter - SimpleCov::Formatter::HTMLFormatter, - Coveralls::SimpleCov::Formatter - - SimpleCov.start do - add_filter '/spec/' # exclude test code - add_filter '/vendor/' # exclude gems which are vendored on Travis CI - end - - # Remove Docile, which was required by SimpleCov, to require again later - Object.send(:remove_const, :Docile) - $LOADED_FEATURES.reject! { |f| f =~ /\/docile\// } - end -rescue LoadError - warn 'warning: simplecov/coveralls gems not found; skipping coverage' -end - -lib_dir = File.join(File.dirname(File.dirname(__FILE__)), 'lib') -$LOAD_PATH.unshift lib_dir unless $LOAD_PATH.include? lib_dir - -# Require Docile again, now with coverage enabled on 1.9+ -require 'docile'
View file
_service:tar_scm:docile-1.1.5.gem/checksums.yaml.gz -> _service:tar_scm:docile-1.4.0.gem/checksums.yaml.gz
Changed
@@ -1,7 +1,7 @@ --- -SHA1: - metadata.gz: 4df64881f4215d866d038e00f55d5b1ca2a45cb2 - data.tar.gz: 26a8de33f8bf657873666a2754bf09f605334e9d +SHA256: + metadata.gz: f4c79b9041a97cfbf6ee0a6d93a9e98a30cc188918d0916ed6b1321f8ac9dca6 + data.tar.gz: 772048f651fadb4277aaa0cb0b91b45e1b95be9f36b3654a9eb5db1a0bb143ea SHA512: - metadata.gz: 75669d4f578d70ba4c8be7dd6c19676041506e0f9408ba26ea0b1ad7931cf59636ccf36a4363ae709a1476464caba5ca1c429b07233dda7d797d5007f3c0af10 - data.tar.gz: e0e0e7364436ce92f4ab5efc52c2782e5da098d302652ca8698d74bcccc27c695b269c04ced3d224eec1a5b3833ba91c44232a2cc4c55fe061504246a715ef49 + metadata.gz: b4e3e7a9fcc953aed658c154dd6a4e43bc258e0895b6a5457f34a93dbcfd1d13808dc2a7d558b133515af695a9283f276d0f744dc57ed7caeae7394bb1ebe3c1 + data.tar.gz: 218c14f2cf80913d370376415f6c650e6c8d8eebfe8405f4529e820d3b2a46bf656ce45ca22ccb36a4409fffb31f823cea49515e1e21ed5c1584d66e55a9a550
View file
_service:tar_scm:docile-1.4.0.gem/data/.github/dependabot.yml
Added
@@ -0,0 +1,15 @@ +version: 2 + +updates: + + # Maintain dependencies for GitHub Actions + - package-ecosystem: "github-actions" + directory: "/" + schedule: + interval: "daily" + + # Maintain dependencies for Ruby's Bundler + - package-ecosystem: "bundler" + directory: "/" + schedule: + interval: "daily"
View file
_service:tar_scm:docile-1.4.0.gem/data/.github/workflows/main.yml
Added
@@ -0,0 +1,31 @@ +name: Main +on: + push: + branches: + - main + pull_request: + branches: + - main +jobs: + test: + name: 'CI Tests' + strategy: + fail-fast: false + matrix: + os: ubuntu-latest + # Due to https://github.com/actions/runner/issues/849, we have to use quotes for '3.0' + ruby: jruby, truffleruby, 2.5, 2.6, 2.7, '3.0', head + runs-on: ${{ matrix.os }} + steps: + - uses: actions/checkout@v2.3.4 + - uses: ruby/setup-ruby@v1 + with: + ruby-version: ${{ matrix.ruby }} + bundler-cache: true + - run: bundle exec rspec + - uses: codecov/codecov-action@v1.5.0 + with: + name: ${{ matrix.ruby }} + file: ./coverage/coverage.xml + - run: bundle exec rubocop + if: matrix.ruby == '3.0'
View file
_service:tar_scm:docile-1.1.5.gem/data/.gitignore -> _service:tar_scm:docile-1.4.0.gem/data/.gitignore
Changed
@@ -6,4 +6,6 @@ doc .yardoc coverage -vendor \ No newline at end of file +vendor +.ruby-gemset +.ruby-version
View file
_service:tar_scm:docile-1.4.0.gem/data/.rubocop.yml
Added
@@ -0,0 +1,2 @@ +inherit_gem: + panolint: rubocop.yml
View file
_service:tar_scm:docile-1.1.5.gem/data/Gemfile -> _service:tar_scm:docile-1.4.0.gem/data/Gemfile
Changed
@@ -1,4 +1,26 @@ -source 'https://rubygems.org' +# frozen_string_literal: true + +source "https://rubygems.org" + +# CI-only dependencies go here +if ENV"CI" == "true" # rubocop:disable Style/IfUnlessModifier + gem "simplecov-cobertura", require: false, group: "test" +end # Specify gem's dependencies in docile.gemspec gemspec + +group :test do + gem "rspec", "~> 3.10" + gem "simplecov", require: false +end + +# Excluded from CI except on latest MRI Ruby, to reduce compatibility burden +group :checks do + gem "panolint", github: "panorama-ed/panolint", branch: "main" +end + +# Optional, only used locally to release to rubygems.org +group :release, optional: true do + gem "rake" +end
View file
_service:tar_scm:docile-1.1.5.gem/data/HISTORY.md -> _service:tar_scm:docile-1.4.0.gem/data/HISTORY.md
Changed
@@ -1,5 +1,71 @@ # HISTORY +## Unreleased changes(http://github.com/ms-ati/docile/compare/v1.4.0...main) + +## v1.4.0 (May 12, 2021)(http://github.com/ms-ati/docile/compare/v1.3.5...v1.4.0) + + - Special thanks to Matt Schreiber (@tomeon): + - Short-circuit to calling #instance_exec directly on the DSL object (prior to + constructing a proxy object) when the DSL object and block context object are + identical (*Sorry it took over a year to review and merge this!*) + - Renamed default branch from master to main, see: https://github.com/github/renaming + - Temporarily removed YARD doc configuration, to replace after + migration to Github Actions + - Removed support for all EOL Rubies < 2.6 + - Migrated CI from Travis to Github Actions + - Special thanks (again!) to Taichi Ishitani (@taichi-ishitani): + - Use more reliable codecov github action (via simplecov-cobertura) + rather than less reliable codecov gem + - Enable bundle caching in github action setup-ruby + - Added Rubocop, and configured it to run in CI + - Added Dependabot, and configured it to run daily + - Added SECURITY.md for vulnerability reporting policy + +## v1.3.5 (Jan 13, 2021)(http://github.com/ms-ati/docile/compare/v1.3.4...v1.3.5) + + - Special thanks to Jochen Seeber (@jochenseeber): + - Fix remaining delegation on Ruby 2.7 (PR #62) + - Remove support for Ruby 1.8.7 and REE, because they + are no longer runnable on Travis CI(https://travis-ci.community/t/ruby-1-8-7-and-ree-builds-broken-by-ssl-certificate-failure/10866) + - Announce that continued support for any EOL Ruby versions (that is, versions + prior to Ruby 2.5 as of Jan 13 2021) will be decided on **Feb 1, 2021** + based on comments to issue #58(https://github.com/ms-ati/docile/issues/58) + +## v1.3.4 (Dec 22, 2020)(http://github.com/ms-ati/docile/compare/v1.3.3...v1.3.4) + + - Special thanks to Benoit Daloze (@eregon): + - Fix delegation on Ruby 2.7 (issues #45 and #44, PR #52) + +## v1.3.3 (Dec 18, 2020)(http://github.com/ms-ati/docile/compare/v1.3.2...v1.3.3) + + - Special thanks (again!) to Taichi Ishitani (@taichi-ishitani): + - Fix keyword arg warnings on Ruby 2.7 (issue #44, PR #45) + - Filter Docile's source files from backtrace (issue #35, PR #36) + +## v1.3.2 (Jun 12, 2019)(http://github.com/ms-ati/docile/compare/v1.3.1...v1.3.2) + + - Special thanks (again!) to Taichi Ishitani (@taichi-ishitani): + - Fix for DSL object is replaced when #dsl_eval is nested (#33, PR #34) + +## v1.3.1 (May 24, 2018)(http://github.com/ms-ati/docile/compare/v1.3.0...v1.3.1) + + - Special thanks to Taichi Ishitani (@taichi-ishitani): + - Fix for when DSL object is also the block's context (#30) + +## v1.3.0 (Feb 7, 2018)(http://github.com/ms-ati/docile/compare/v1.2.0...v1.3.0) + + - Allow helper methods in block's context to call DSL methods + - Add SemVer release policy explicitly + - Standardize on double-quoted string literals + - Workaround some more Travis CI shenanigans + +## v1.2.0 (Jan 11, 2018)(http://github.com/ms-ati/docile/compare/v1.1.5...v1.2.0) + + - Special thanks to Christina Koller (@cmkoller) + - add DSL evaluation returning *return value of the block* (see `.dsl_eval_with_block_return`) + - add an example to README + - keep travis builds passing on old ruby versions + ## v1.1.5 (Jun 15, 2014)(http://github.com/ms-ati/docile/compare/v1.1.4...v1.1.5) - as much as possible, loosen version restrictions on development dependencies
View file
_service:tar_scm:docile-1.1.5.gem/data/LICENSE -> _service:tar_scm:docile-1.4.0.gem/data/LICENSE
Changed
@@ -1,6 +1,6 @@ The MIT License (MIT) -Copyright (c) 2012-2014 Marc Siegel +Copyright (c) 2012-2021 Marc Siegel Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal
View file
_service:tar_scm:docile-1.1.5.gem/data/README.md -> _service:tar_scm:docile-1.4.0.gem/data/README.md
Changed
@@ -1,11 +1,15 @@ # Docile -!Gem Version(https://badge.fury.io/rb/docile.png)(http://badge.fury.io/rb/docile) -!Build Status(https://travis-ci.org/ms-ati/docile.png)(https://travis-ci.org/ms-ati/docile) -!Dependency Status(https://gemnasium.com/ms-ati/docile.png)(https://gemnasium.com/ms-ati/docile) -!Code Climate(https://codeclimate.com/github/ms-ati/docile.png)(https://codeclimate.com/github/ms-ati/docile) -!Coverage Status(https://coveralls.io/repos/ms-ati/docile/badge.png)(https://coveralls.io/r/ms-ati/docile) -!Inline docs(http://inch-ci.org/github/ms-ati/docile.png)(http://inch-ci.org/github/ms-ati/docile) -!Bitdeli Badge(https://d2weczhvl823v0.cloudfront.net/ms-ati/docile/trend.png)(https://bitdeli.com/free "Bitdeli Badge") + +!Gem Version(https://img.shields.io/gem/v/docile.svg)(https://rubygems.org/gems/docile) +!Gem Downloads(https://img.shields.io/gem/dt/docile.svg)(https://rubygems.org/gems/docile) + +!Join the chat at https://gitter.im/ms-ati/docile(https://badges.gitter.im/Join%20Chat.svg)(https://gitter.im/ms-ati/docile?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) +!Yard Docs(http://img.shields.io/badge/yard-docs-blue.svg)(http://rubydoc.info/github/ms-ati/docile) +!Docs Coverage(http://inch-ci.org/github/ms-ati/docile.png)(http://inch-ci.org/github/ms-ati/docile) + +!Build Status(https://github.com/ms-ati/docile/actions/workflows/main.yml/badge.svg)(https://github.com/ms-ati/docile/actions/workflows/main.yml) +!Code Coverage(https://img.shields.io/codecov/c/github/ms-ati/docile.svg)(https://codecov.io/github/ms-ati/docile) +!Maintainability(https://api.codeclimate.com/v1/badges/79ca631bc123f7b83b34/maintainability)(https://codeclimate.com/github/ms-ati/docile/maintainability) Ruby makes it possible to create very expressive **Domain Specific Languages**, or **DSL**'s for short. However, it requires some deep knowledge and @@ -20,7 +24,7 @@ ## Usage -### Basic +### Basic: Ruby Array(http://ruby-doc.org/core-3.0.0/Array.html) as DSL Let's say that we want to make a DSL for modifying Array objects. Wouldn't it be great if we could just treat the methods of Array as a DSL? @@ -45,7 +49,80 @@ Easy! -### Advanced +### Next step: Allow helper methods to call DSL methods + +What if, in our use of the methods of Array as a DSL, we want to extract +helper methods which in turn call DSL methods? + +```ruby +def pop_sum_and_push(n) + sum = 0 + n.times { sum += pop } + push sum +end + +Docile.dsl_eval() do + push 5 + push 6 + pop_sum_and_push(2) +end +#=> 11 +``` + +Without Docile, you may find this sort of code extraction to be more +challenging. + +### Wait! Can't I do that with just `instance_eval` or `instance_exec`? + +Good question! + +In short: **No**. + +Not if you want the code in the block to be able to refer to anything +the block would normally have access to from the surrounding context. + +Let's be very specific. Docile internally uses `instance_exec` (see execution.rb#26(lib/docile/execution.rb#L26)), adding a small layer to support referencing *local variables*, *instance variables*, and *methods* from the _block's context_ **or** the target _object's context_, interchangeably. This is "**the hard part**", where most folks making a DSL in Ruby throw up their hands. + +For example: + +```ruby +class ContextOfBlock + def example_of_contexts + @block_instance_var = 1 + block_local_var = 2 + + with_array do + push @block_instance_var + push block_local_var + pop + push block_sees_this_method + end + end + + def block_sees_this_method + 3 + end + + def with_array(&block) + { + docile: Docile.dsl_eval(, &block), + instance_eval: (.instance_eval(&block) rescue $!), + instance_exec: (.instance_exec(&block) rescue $!) + } + end +end + +ContextOfBlock.new.example_of_contexts +#=> { + :docile=>1, 3, + :instance_eval=>#<NameError: undefined local variable or method `block_sees_this_method' for nil:Array>, + :instance_exec=>#<NameError: undefined local variable or method `block_sees_this_method' for nil:Array> + } +``` + +As you can see, it won't be possible to call methods or access instance variables defined in the block's context using just the raw `instance_eval` or `instance_exec` methods. And in fact, Docile goes further, making it easy to maintain this support even in multi-layered DSLs. + +### Build a Pizza Mutating (changing) an Array instance is fine, but what usually makes a good DSL is a Builder Pattern2. @@ -83,7 +160,7 @@ Then implement your DSL like this: -``` ruby +```ruby def pizza(&block) Docile.dsl_eval(PizzaBuilder.new, &block).build end @@ -93,6 +170,38 @@ 2: http://stackoverflow.com/questions/328496/when-would-you-use-the-builder-pattern "Builder Pattern" +### Multi-level and Recursive DSLs + +Docile is a very easy way to write a multi-level DSL in Ruby, even for +a recursive data structure such as a tree4: + +```ruby +Person = Struct.new(:name, :mother, :father) + +person { + name 'John Smith' + mother { + name 'Mary Smith' + } + father { + name 'Tom Smith' + mother { + name 'Jane Smith' + } + } +} + +#=> #<struct Person name="John Smith", +# mother=#<struct Person name="Mary Smith", mother=nil, father=nil>, +# father=#<struct Person name="Tom Smith", +# mother=#<struct Person name="Jane Smith", mother=nil, father=nil>, +# father=nil>> +``` + +See the full person tree example4 for details. + +4: https://gist.github.com/ms-ati/2bb17bdf10a430faba98 + ### Block parameters Parameters can be passed to the DSL block. @@ -153,18 +262,18 @@ 3: http://www.sinatrarb.com "Sinatra" -### Functional-Style DSL Objects +### Functional-Style Immutable DSL Objects Sometimes, you want to use an object as a DSL, but it doesn't quite fit the imperative(http://en.wikipedia.org/wiki/Imperative_programming) pattern shown above. Instead of methods like -Array#push(http://www.ruby-doc.org/core-2.0/Array.html#method-i-push), which +Array#push(http://www.ruby-doc.org/core-3.0.0/Array.html#method-i-push), which modifies the object at hand, it has methods like -String#reverse(http://www.ruby-doc.org/core-2.0/String.html#method-i-reverse), +String#reverse(http://www.ruby-doc.org/core-3.0.0/String.html#method-i-reverse), which returns a new object without touching the original. Perhaps it's even -frozen(http://www.ruby-doc.org/core-2.0/Object.html#method-i-freeze) in +frozen(http://www.ruby-doc.org/core-3.0.0/Object.html#method-i-freeze) in order to enforce immutability(http://en.wikipedia.org/wiki/Immutable_object). Wouldn't it be great if we could just treat these methods as a DSL as well? @@ -192,6 +301,33 @@ All set! +### Accessing the block's return value + +Sometimes you might want to access the return value of your provided block, +as opposed to the DSL object itself. In these cases, use +`dsl_eval_with_block_return`. It behaves exactly like `dsl_eval`, but returns +the output from executing the block, rather than the DSL object. + +```ruby +arr = +with_array(arr) do + push "a" + push "b" + push "c" + length +end +#=> 3 + +arr +#=> "a", "b", "c" +``` + +```ruby +def with_array(arr=, &block) + Docile.dsl_eval_with_block_return(arr, &block) +end +``` + ## Features 1. Method lookup falls back from the DSL object to the block's context @@ -215,9 +351,19 @@ ## Status -Works on all ruby versions since 1.8.7(https://github.com/ms-ati/docile/blob/master/.travis.yml), or so Travis CI tells us(https://travis-ci.org/ms-ati/docile). +Works on all currently supported ruby versions(https://github.com/ms-ati/docile/blob/master/.github/workflows/main.yml), +or so Github Actions(https://github.com/ms-ati/docile/actions) +tells us. -Used by some pretty cool gems to implement their DSLs, notably including SimpleCov(https://github.com/colszowka/simplecov). Keep an eye out for new gems using Docile at the Ruby Toolbox(https://www.ruby-toolbox.com/projects/docile). +Used by some pretty cool gems to implement their DSLs, notably including +SimpleCov(https://github.com/colszowka/simplecov). Keep an eye out for new +gems using Docile at the +Ruby Toolbox(https://www.ruby-toolbox.com/projects/docile). + +## Release Policy + +Docile releases follow +Semantic Versioning 2.0.0(https://semver.org/spec/v2.0.0.html). ## Note on Patches/Pull Requests @@ -232,10 +378,33 @@ commit by itself I can ignore when I pull) * Send me a pull request. Bonus points for topic branches. -## Copyright & License +## Releasing -Copyright (c) 2012-2014 Marc Siegel. +To make a new release of `Dile` to +RubyGems(https://rubygems.org/gems/docile), first install the release +dependencies (e.g. `rake`) as follows: -Licensed under the MIT License(http://choosealicense.com/licenses/mit/), see LICENSE(LICENSE) for details. +```shell +bundle config set --local with 'release' +bundle install +``` + +Then carry out these steps: + +1. Update `HISTORY.md`: + - Add an entry for the upcoming version _x.y.z_ + - Move content from _Unreleased_ to the upcoming version _x.y.z_ + - Commit with title `Update HISTORY.md for x.y.z` + +2. Update `lib/docile/version.rb` + - Replace with upcoming version _x.y.z_ + - Commit with title `Bump version to x.y.z` + +3. `bundle exec rake release` + +## Copyright & License +Copyright (c) 2012-2021 Marc Siegel. +Licensed under the MIT License(http://choosealicense.com/licenses/mit/), +see LICENSE(LICENSE) for details.
View file
_service:tar_scm:docile-1.1.5.gem/data/Rakefile -> _service:tar_scm:docile-1.4.0.gem/data/Rakefile
Changed
@@ -1,28 +1,14 @@ -require 'rake/clean' -require 'bundler/gem_tasks' -require 'rspec/core/rake_task' -require File.expand_path('on_what', File.dirname(__FILE__)) +# frozen_string_literal: true + +require "rake/clean" +require "bundler/gem_tasks" +require "rspec/core/rake_task" # Default task for `rake` is to run rspec -task :default => :spec +task default: :spec # Use default rspec rake task RSpec::Core::RakeTask.new # Configure `rake clobber` to delete all generated files -CLOBBER.include('pkg', 'doc', 'coverage') - -# To limit needed compatibility with versions of dependencies, only configure -# yard doc generation when *not* on Travis, JRuby, or 1.8 -if !on_travis? && !on_jruby? && !on_1_8? - require 'github/markup' - require 'redcarpet' - require 'yard' - require 'yard/rake/yardoc_task' - - YARD::Rake::YardocTask.new do |t| - OTHER_PATHS = %w() - t.files = 'lib/**/*.rb', OTHER_PATHS - t.options = %w(--markup-provider=redcarpet --markup=markdown --main=README.md) - end -end +CLOBBER.include("pkg", "doc", "coverage")
View file
_service:tar_scm:docile-1.4.0.gem/data/SECURITY.md
Added
@@ -0,0 +1,18 @@ +# Security Policy + +## Supported Versions + +Use this section to tell people about which versions of your project are +currently being supported with security updates. + +| Version | Supported | +| ------- | ------------------ | +| 1.3.x | :white_check_mark: | +| < 1.3 | :x: | + +## Reporting a Vulnerability + +At this time, security issues and vulnerabilities in Docile should +be reported like any other issue. Please create an issue in the +public issue tracker(https://github.com/ms-ati/docile/issues) on +Github.
View file
_service:tar_scm:docile-1.1.5.gem/data/docile.gemspec -> _service:tar_scm:docile-1.4.0.gem/data/docile.gemspec
Changed
@@ -1,43 +1,29 @@ -require File.expand_path('on_what', File.dirname(__FILE__)) -$:.push File.expand_path('../lib', __FILE__) -require 'docile/version' +# frozen_string_literal: true + +require_relative "lib/docile/version" Gem::Specification.new do |s| - s.name = 'docile' + s.name = "docile" s.version = Docile::VERSION - s.author = 'Marc Siegel' - s.email = 'marc@usainnov.com' - s.homepage = 'https://ms-ati.github.io/docile/' - s.summary = 'Docile keeps your Ruby DSLs tame and well-behaved' - s.description = 'Docile turns any Ruby object into a DSL. Especially useful with the Builder pattern.' - s.license = 'MIT' - - # Files included in the gem - s.files = `git ls-files`.split("\n") - s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n") - s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) } - s.require_paths = %w(lib) - - # Specify oldest supported Ruby version - s.required_ruby_version = '>= 1.8.7' + s.author = "Marc Siegel" + s.email = "marc@usainnov.com" + s.homepage = "https://ms-ati.github.io/docile/" + s.summary = "Docile keeps your Ruby DSLs tame and well-behaved." + s.description = "Docile treats the methods of a given ruby object as a DSL " \ + "(domain specific language) within a given block. \n\n" \ + "Killer feature: you can also reference methods, instance " \ + "variables, and local variables from the original (non-DSL) "\ + "context within the block. \n\n" \ + "Docile releases follow Semantic Versioning as defined at " \ + "semver.org." + s.license = "MIT" - # Run rspec tests from rake - s.add_development_dependency 'rake' - s.add_development_dependency 'rspec', '~> 3.0.0' + # Specify oldest supported Ruby version (2.5 to support JRuby 9.2.17.0) + s.required_ruby_version = ">= 2.5.0" - # NOTE: needed for Travis builds on 1.8, but can't yet reproduce failure locally - s.add_development_dependency 'mime-types', '~> 1.25.1' if on_1_8? - - # To limit needed compatibility with versions of dependencies, only configure - # yard doc generation when *not* on Travis, JRuby, or 1.8 - if !on_travis? && !on_jruby? && !on_1_8? - # Github flavored markdown in YARD documentation - # http://blog.nikosd.com/2011/11/github-flavored-markdown-in-yard.html - s.add_development_dependency 'yard' - s.add_development_dependency 'redcarpet' - s.add_development_dependency 'github-markup' + # Files included in the gem + s.files = `git ls-files -z`.split("\x0").reject do |f| + f.match(%r{^(test|spec|features)/}) end - - # Coveralls test coverage tool, basically hosted SimpleCov - s.add_development_dependency 'coveralls' + s.require_paths = "lib" end
View file
_service:tar_scm:docile-1.1.5.gem/data/lib/docile.rb -> _service:tar_scm:docile-1.4.0.gem/data/lib/docile.rb
Changed
@@ -1,7 +1,10 @@ -require 'docile/version' -require 'docile/execution' -require 'docile/fallback_context_proxy' -require 'docile/chaining_fallback_context_proxy' +# frozen_string_literal: true + +require "docile/version" +require "docile/execution" +require "docile/fallback_context_proxy" +require "docile/chaining_fallback_context_proxy" +require "docile/backtrace_filter" # Docile keeps your Ruby DSLs tame and well-behaved. module Docile @@ -43,8 +46,53 @@ exec_in_proxy_context(dsl, FallbackContextProxy, *args, &block) dsl end + + ruby2_keywords :dsl_eval if respond_to?(:ruby2_keywords, true) module_function :dsl_eval + # Execute a block in the context of an object whose methods represent the + # commands in a DSL, and return *the block's return value*. + # + # @note Use with an *imperative* DSL (commands modify the context object) + # + # Use this method to execute an *imperative* DSL, which means that: + # + # 1. Each command mutates the state of the DSL context object + # 2. The return value of each command is ignored + # 3. The final return value is the original context object + # + # @example Use a String as a DSL + # Docile.dsl_eval_with_block_return("Hello, world!") do + # reverse! + # upcase! + # first + # end + # #=> "!" + # + # @example Use an Array as a DSL + # Docile.dsl_eval_with_block_return() do + # push "a" + # push "b" + # pop + # push "c" + # length + # end + # #=> 2 + # + # @param dsl Object context object whose methods make up the DSL + # @param args Array arguments to be passed to the block + # @param block Proc the block of DSL commands to be executed against the + # `dsl` context object + # @return Object the return value from executing the block + def dsl_eval_with_block_return(dsl, *args, &block) + exec_in_proxy_context(dsl, FallbackContextProxy, *args, &block) + end + + if respond_to?(:ruby2_keywords, true) + ruby2_keywords :dsl_eval_with_block_return + end + module_function :dsl_eval_with_block_return + # Execute a block in the context of an immutable object whose methods, # and the methods of their return values, represent the commands in a DSL. # @@ -80,5 +128,7 @@ def dsl_eval_immutable(dsl, *args, &block) exec_in_proxy_context(dsl, ChainingFallbackContextProxy, *args, &block) end + + ruby2_keywords :dsl_eval_immutable if respond_to?(:ruby2_keywords, true) module_function :dsl_eval_immutable end
View file
_service:tar_scm:docile-1.4.0.gem/data/lib/docile/backtrace_filter.rb
Added
@@ -0,0 +1,24 @@ +# frozen_string_literal: true + +module Docile + # @api private + # + # This is used to remove entries pointing to Docile's source files + # from {Exception#backtrace} and {Exception#backtrace_locations}. + # + # If {NoMethodError} is caught then the exception object will be extended + # by this module to add filter functionalities. + module BacktraceFilter + FILTER_PATTERN = %r{/lib/docile/}.freeze + + def backtrace + super.reject { |trace| trace =~ FILTER_PATTERN } + end + + if ::Exception.public_method_defined?(:backtrace_locations) + def backtrace_locations + super.reject { |location| location.absolute_path =~ FILTER_PATTERN } + end + end + end +end
View file
_service:tar_scm:docile-1.1.5.gem/data/lib/docile/chaining_fallback_context_proxy.rb -> _service:tar_scm:docile-1.4.0.gem/data/lib/docile/chaining_fallback_context_proxy.rb
Changed
@@ -1,4 +1,6 @@ -require 'docile/fallback_context_proxy' +# frozen_string_literal: true + +require "docile/fallback_context_proxy" module Docile # @api private @@ -10,11 +12,16 @@ # objects. # # @see Docile.dsl_eval_immutable + # + # rubocop:disable Style/MissingRespondToMissing class ChainingFallbackContextProxy < FallbackContextProxy # Proxy methods as in {FallbackContextProxy#method_missing}, replacing # `receiver` with the returned value. def method_missing(method, *args, &block) @__receiver__ = super(method, *args, &block) end + + ruby2_keywords :method_missing if respond_to?(:ruby2_keywords, true) end -end \ No newline at end of file + # rubocop:enable Style/MissingRespondToMissing +end
View file
_service:tar_scm:docile-1.1.5.gem/data/lib/docile/execution.rb -> _service:tar_scm:docile-1.4.0.gem/data/lib/docile/execution.rb
Changed
@@ -1,3 +1,5 @@ +# frozen_string_literal: true + module Docile # @api private # @@ -15,21 +17,37 @@ # @param block Proc the block of DSL commands to be executed # @return Object the return value of the block def exec_in_proxy_context(dsl, proxy_type, *args, &block) - block_context = eval('self', block.binding) + block_context = eval("self", block.binding) # rubocop:disable Style/EvalWithLocation + + # Use #equal? to test strict object identity (assuming that this dictum + # from the Ruby docs holds: "unlike ==, the equal? method should never + # be overridden by subclasses as it is used to determine object + # identity") + return dsl.instance_exec(*args, &block) if dsl.equal?(block_context) + proxy_context = proxy_type.new(dsl, block_context) begin block_context.instance_variables.each do |ivar| value_from_block = block_context.instance_variable_get(ivar) proxy_context.instance_variable_set(ivar, value_from_block) end + proxy_context.instance_exec(*args, &block) ensure + if block_context.respond_to?(:__docile_undo_fallback__) + block_context.send(:__docile_undo_fallback__) + end + block_context.instance_variables.each do |ivar| + next unless proxy_context.instance_variables.include?(ivar) + value_from_dsl_proxy = proxy_context.instance_variable_get(ivar) block_context.instance_variable_set(ivar, value_from_dsl_proxy) end end end + + ruby2_keywords :exec_in_proxy_context if respond_to?(:ruby2_keywords, true) module_function :exec_in_proxy_context end -end \ No newline at end of file +end
View file
_service:tar_scm:docile-1.1.5.gem/data/lib/docile/fallback_context_proxy.rb -> _service:tar_scm:docile-1.4.0.gem/data/lib/docile/fallback_context_proxy.rb
Changed
@@ -1,4 +1,6 @@ -require 'set' +# frozen_string_literal: true + +require "set" module Docile # @api private @@ -13,14 +15,20 @@ # This is useful for implementing DSL evaluation in the context of an object. # # @see Docile.dsl_eval + # + # rubocop:disable Style/MissingRespondToMissing class FallbackContextProxy # The set of methods which will **not** be proxied, but instead answered # by this object directly. NON_PROXIED_METHODS = Set:__send__, :object_id, :__id__, :==, :equal?, - :'!', :'!=', :instance_exec, :instance_variables, + :!, :!=, :instance_exec, :instance_variables, :instance_variable_get, :instance_variable_set, :remove_instance_variable + # The set of methods which will **not** fallback from the block's context + # to the dsl object. + NON_FALLBACK_METHODS = Set:class, :self, :respond_to?, :instance_of? + # The set of instance variables which are local to this object and hidden. # All other instance variables will be copied in and out of this object # from the scope in which this proxy was created. @@ -38,16 +46,44 @@ def initialize(receiver, fallback) @__receiver__ = receiver @__fallback__ = fallback + + # Enables calling DSL methods from helper methods in the block's context + unless fallback.respond_to?(:method_missing) + # NOTE: We could switch to {#define_singleton_method} on current Rubies + singleton_class = (class << fallback; self; end) + + # instrument {#method_missing} on the block's context to fallback to + # the DSL object. This allows helper methods in the block's context to + # contain calls to methods on the DSL object. + singleton_class. + send(:define_method, :method_missing) do |method, *args, &block| + m = method.to_sym + if !NON_FALLBACK_METHODS.member?(m) && + !fallback.respond_to?(m) && + receiver.respond_to?(m) + receiver.__send__(method.to_sym, *args, &block) + else + super(method, *args, &block) + end + end + + if singleton_class.respond_to?(:ruby2_keywords, true) + singleton_class.send(:ruby2_keywords, :method_missing) + end + + # instrument a helper method to remove the above instrumentation + singleton_class. + send(:define_method, :__docile_undo_fallback__) do + singleton_class.send(:remove_method, :method_missing) + singleton_class.send(:remove_method, :__docile_undo_fallback__) + end + end end # @return Array<Symbol> Instance variable names, excluding # {NON_PROXIED_INSTANCE_VARIABLES} - # - # @note on Ruby 1.8.x, the instance variable names are actually of - # type `String`. def instance_variables - # Ruby 1.8.x returns string names, convert to symbols for compatibility - super.select { |v| !NON_PROXIED_INSTANCE_VARIABLES.include?(v.to_sym) } + super.reject { |v| NON_PROXIED_INSTANCE_VARIABLES.include?(v) } end # Proxy all methods, excluding {NON_PROXIED_METHODS}, first to `receiver` @@ -56,8 +92,16 @@ if @__receiver__.respond_to?(method.to_sym) @__receiver__.__send__(method.to_sym, *args, &block) else - @__fallback__.__send__(method.to_sym, *args, &block) + begin + @__fallback__.__send__(method.to_sym, *args, &block) + rescue NoMethodError => e + e.extend(BacktraceFilter) + raise e + end end end + + ruby2_keywords :method_missing if respond_to?(:ruby2_keywords, true) end + # rubocop:enable Style/MissingRespondToMissing end
View file
_service:tar_scm:docile-1.1.5.gem/data/lib/docile/version.rb -> _service:tar_scm:docile-1.4.0.gem/data/lib/docile/version.rb
Changed
@@ -1,4 +1,6 @@ +# frozen_string_literal: true + module Docile # The current version of this library - VERSION = '1.1.5' + VERSION = "1.4.0" end
View file
_service:tar_scm:docile-1.1.5.gem/metadata.gz -> _service:tar_scm:docile-1.4.0.gem/metadata.gz
Changed
@@ -1,131 +1,48 @@ --- !ruby/object:Gem::Specification name: docile version: !ruby/object:Gem::Version - version: 1.1.5 + version: 1.4.0 platform: ruby authors: - Marc Siegel -autorequire: +autorequire: bindir: bin cert_chain: -date: 2014-06-15 00:00:00.000000000 Z -dependencies: -- !ruby/object:Gem::Dependency - name: rake - requirement: !ruby/object:Gem::Requirement - requirements: - - - ">=" - - !ruby/object:Gem::Version - version: '0' - type: :development - prerelease: false - version_requirements: !ruby/object:Gem::Requirement - requirements: - - - ">=" - - !ruby/object:Gem::Version - version: '0' -- !ruby/object:Gem::Dependency - name: rspec - requirement: !ruby/object:Gem::Requirement - requirements: - - - "~>" - - !ruby/object:Gem::Version - version: 3.0.0 - type: :development - prerelease: false - version_requirements: !ruby/object:Gem::Requirement - requirements: - - - "~>" - - !ruby/object:Gem::Version - version: 3.0.0 -- !ruby/object:Gem::Dependency - name: yard - requirement: !ruby/object:Gem::Requirement - requirements: - - - ">=" - - !ruby/object:Gem::Version - version: '0' - type: :development - prerelease: false - version_requirements: !ruby/object:Gem::Requirement - requirements: - - - ">=" - - !ruby/object:Gem::Version - version: '0' -- !ruby/object:Gem::Dependency - name: redcarpet - requirement: !ruby/object:Gem::Requirement - requirements: - - - ">=" - - !ruby/object:Gem::Version - version: '0' - type: :development - prerelease: false - version_requirements: !ruby/object:Gem::Requirement - requirements: - - - ">=" - - !ruby/object:Gem::Version - version: '0' -- !ruby/object:Gem::Dependency - name: github-markup - requirement: !ruby/object:Gem::Requirement - requirements: - - - ">=" - - !ruby/object:Gem::Version - version: '0' - type: :development - prerelease: false - version_requirements: !ruby/object:Gem::Requirement - requirements: - - - ">=" - - !ruby/object:Gem::Version - version: '0' -- !ruby/object:Gem::Dependency - name: coveralls - requirement: !ruby/object:Gem::Requirement - requirements: - - - ">=" - - !ruby/object:Gem::Version - version: '0' - type: :development - prerelease: false - version_requirements: !ruby/object:Gem::Requirement - requirements: - - - ">=" - - !ruby/object:Gem::Version - version: '0' -description: Docile turns any Ruby object into a DSL. Especially useful with the Builder - pattern. +date: 2021-05-12 00:00:00.000000000 Z +dependencies: +description: "Docile treats the methods of a given ruby object as a DSL (domain specific + language) within a given block. \n\nKiller feature: you can also reference methods, + instance variables, and local variables from the original (non-DSL) context within + the block. \n\nDocile releases follow Semantic Versioning as defined at semver.org." email: marc@usainnov.com executables: extensions: extra_rdoc_files: files: +- ".github/dependabot.yml" +- ".github/workflows/main.yml" - ".gitignore" - ".rspec" -- ".ruby-gemset" -- ".ruby-version" -- ".travis.yml" +- ".rubocop.yml" - ".yardopts" - Gemfile - HISTORY.md - LICENSE - README.md - Rakefile +- SECURITY.md - docile.gemspec - lib/docile.rb +- lib/docile/backtrace_filter.rb - lib/docile/chaining_fallback_context_proxy.rb - lib/docile/execution.rb - lib/docile/fallback_context_proxy.rb - lib/docile/version.rb -- on_what.rb -- spec/docile_spec.rb -- spec/spec_helper.rb homepage: https://ms-ati.github.io/docile/ licenses: - MIT metadata: {} -post_install_message: +post_install_message: rdoc_options: require_paths: - lib @@ -133,19 +50,15 @@ requirements: - - ">=" - !ruby/object:Gem::Version - version: 1.8.7 + version: 2.5.0 required_rubygems_version: !ruby/object:Gem::Requirement requirements: - - ">=" - !ruby/object:Gem::Version version: '0' requirements: -rubyforge_project: -rubygems_version: 2.2.2 -signing_key: +rubygems_version: 3.2.3 +signing_key: specification_version: 4 -summary: Docile keeps your Ruby DSLs tame and well-behaved -test_files: -- spec/docile_spec.rb -- spec/spec_helper.rb -has_rdoc: +summary: Docile keeps your Ruby DSLs tame and well-behaved. +test_files:
Locations
Projects
Search
Status Monitor
Help
Open Build Service
OBS Manuals
API Documentation
OBS Portal
Reporting a Bug
Contact
Mailing List
Forums
Chat (IRC)
Twitter
Open Build Service (OBS)
is an
openSUSE project
.
浙ICP备2022010568号-2