rails2ext 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +5 -0
- data/.rspec +1 -0
- data/CHANGELOG +2 -0
- data/Gemfile +4 -0
- data/README.md +13 -0
- data/Rakefile +8 -0
- data/lib/rails2ext.rb +7 -0
- data/lib/rails2ext/active_record.rb +3 -0
- data/lib/rails2ext/active_record/first_or_create.rb +5 -0
- data/lib/rails2ext/active_support.rb +5 -0
- data/lib/rails2ext/active_support/command_retry.rb +80 -0
- data/lib/rails2ext/active_support/core_ext.rb +1 -0
- data/lib/rails2ext/active_support/core_ext/array.rb +1 -0
- data/lib/rails2ext/active_support/core_ext/array/uniq_by.rb +11 -0
- data/lib/rails2ext/active_support/core_ext/load_error.rb +4 -0
- data/lib/rails2ext/active_support/quick_logger.rb +32 -0
- data/lib/rails2ext/version.rb +3 -0
- data/rails2ext.gemspec +27 -0
- data/spec/active_record/first_or_create_spec.rb +56 -0
- data/spec/active_support/command_retry_spec.rb +72 -0
- data/spec/active_support/core_ext/array/uniq_by_spec.rb +13 -0
- data/spec/active_support/core_ext/load_error_spec.rb +5 -0
- data/spec/active_support/quick_logger_spec.rb +44 -0
- data/spec/spec_helper.rb +6 -0
- metadata +165 -0
data/.gitignore
ADDED
data/.rspec
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
--color
|
data/CHANGELOG
ADDED
data/Gemfile
ADDED
data/README.md
ADDED
@@ -0,0 +1,13 @@
|
|
1
|
+
# Rails2Ext
|
2
|
+
|
3
|
+
This gem is intended to collect all sort of **Rails 2.3.x** extensions that are not (yet?) present in the official repo.
|
4
|
+
Its structure mimic the original gems structure, so developers should feel at home browsing/extending it.
|
5
|
+
There is not much right now, but it could grow in size.
|
6
|
+
|
7
|
+
# Tests
|
8
|
+
|
9
|
+
Run
|
10
|
+
|
11
|
+
rake
|
12
|
+
|
13
|
+
to run the rspec test suite.
|
data/Rakefile
ADDED
data/lib/rails2ext.rb
ADDED
@@ -0,0 +1,80 @@
|
|
1
|
+
# CommandRetry helps you repeat system commands when they
|
2
|
+
# are not successful for a given number of times (repeat
|
3
|
+
# once by default).
|
4
|
+
# If all repetitions fail, an error (default is
|
5
|
+
# RuntimeError) will be raised unless you passed in
|
6
|
+
# +:fail => false+ option
|
7
|
+
#
|
8
|
+
# It accepts also a +on+ option, which can be a single
|
9
|
+
# exit code or an array of exit codes that will cause
|
10
|
+
# the block to be repeated.
|
11
|
+
# Other exit codes not included in the +on+ array (if
|
12
|
+
# provided) will not cause repetitions and will will
|
13
|
+
# not raise errors.
|
14
|
+
#
|
15
|
+
# Will retry 5 times, failing each time and eventually
|
16
|
+
# raise the default error:
|
17
|
+
#
|
18
|
+
# CommandRetry.retry(:times => 5) { system 'bingobongo' }
|
19
|
+
# #=> RuntimeError: #<RuntimeError:0x101d89648>
|
20
|
+
#
|
21
|
+
# Will fail 5 times with exit code 7, eventually will
|
22
|
+
# raise custom error:
|
23
|
+
#
|
24
|
+
# CommandRetry.retry(:fail => ArgumentError, :on => 7 :times => 5) do
|
25
|
+
# system 'curl localhost:123/notfound'
|
26
|
+
# end
|
27
|
+
#
|
28
|
+
# Will fail just once since exit code 7 is not
|
29
|
+
# included in +on+ array, and will raise no error:
|
30
|
+
#
|
31
|
+
# CommandRetry.retry(:on => 52, :times => 5) do
|
32
|
+
# system 'curl localhost:123/notfound'
|
33
|
+
# end
|
34
|
+
|
35
|
+
class CommandRetry
|
36
|
+
def self.retry(opts={}, &block)
|
37
|
+
new(opts, &block).retry
|
38
|
+
end
|
39
|
+
|
40
|
+
def initialize(opts={}, &block)
|
41
|
+
opts.symbolize_keys!
|
42
|
+
@times = opts[:times] || 2
|
43
|
+
@fail = opts[:fail] || RuntimeError unless opts[:fail] == false
|
44
|
+
@on = Array.wrap(opts[:on]) if opts[:on]
|
45
|
+
@command = block
|
46
|
+
end
|
47
|
+
|
48
|
+
def retry
|
49
|
+
result = false
|
50
|
+
status = 0
|
51
|
+
@times.times do
|
52
|
+
result = @command.call
|
53
|
+
status = exit_status
|
54
|
+
if should_break?(status)
|
55
|
+
break
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
if @fail && status != 0
|
60
|
+
unless on_allows?(status)
|
61
|
+
raise @fail, caller
|
62
|
+
end
|
63
|
+
end
|
64
|
+
result
|
65
|
+
end
|
66
|
+
|
67
|
+
private
|
68
|
+
|
69
|
+
def exit_status
|
70
|
+
$?.exitstatus
|
71
|
+
end
|
72
|
+
|
73
|
+
def should_break?(status)
|
74
|
+
status.zero? or on_allows?(status)
|
75
|
+
end
|
76
|
+
|
77
|
+
def on_allows?(status)
|
78
|
+
@on && !@on.include?(status)
|
79
|
+
end
|
80
|
+
end
|
@@ -0,0 +1 @@
|
|
1
|
+
Dir["#{File.dirname(__FILE__)}/core_ext/*.rb"].each { |filename| require filename }
|
@@ -0,0 +1 @@
|
|
1
|
+
require File.join(File.dirname(__FILE__), 'array', 'uniq_by')
|
@@ -0,0 +1,32 @@
|
|
1
|
+
require 'logger'
|
2
|
+
|
3
|
+
# quick and dirty logger: just inherit from here,
|
4
|
+
# set the filename attribute then you're ready to go
|
5
|
+
class QuickLogger
|
6
|
+
class << self
|
7
|
+
attr_accessor :filename
|
8
|
+
|
9
|
+
def filename_path
|
10
|
+
if defined?(Rails)
|
11
|
+
File.join Rails.root, 'log', [@filename, Rails.env, 'log'].join('.')
|
12
|
+
else
|
13
|
+
[@filename, 'log'].join('.')
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
def method_missing(log_level, message)
|
18
|
+
@logger ||= ::Logger.new(filename_path)
|
19
|
+
if ::Logger::SEV_LABEL.include?(log_level.to_s.upcase)
|
20
|
+
@logger.send log_level, "[#{Time.now}] #{message}"
|
21
|
+
else
|
22
|
+
super
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
# keep legacy interface
|
29
|
+
module Quick
|
30
|
+
class Logger < QuickLogger
|
31
|
+
end
|
32
|
+
end
|
data/rails2ext.gemspec
ADDED
@@ -0,0 +1,27 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
$:.push File.expand_path("../lib", __FILE__)
|
3
|
+
require "rails2ext/version"
|
4
|
+
|
5
|
+
Gem::Specification.new do |s|
|
6
|
+
s.name = "rails2ext"
|
7
|
+
s.version = Rails2ext::VERSION
|
8
|
+
s.platform = Gem::Platform::RUBY
|
9
|
+
s.authors = ["andrea longhi"]
|
10
|
+
s.email = ["andrea@spaghetticode.it"]
|
11
|
+
s.homepage = ""
|
12
|
+
s.summary = %q{some useful extensions for rails 2 apps}
|
13
|
+
s.description = %q{some useful extensions for rails 2 apps}
|
14
|
+
|
15
|
+
# s.rubyforge_project = "rails2ext"
|
16
|
+
|
17
|
+
s.files = `git ls-files`.split("\n")
|
18
|
+
s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
|
19
|
+
s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
|
20
|
+
s.require_paths = ["lib"]
|
21
|
+
|
22
|
+
s.add_runtime_dependency 'rails', '~> 2.3.0'
|
23
|
+
s.add_development_dependency 'rake'
|
24
|
+
s.add_development_dependency 'rspec'
|
25
|
+
s.add_development_dependency 'mocha'
|
26
|
+
s.add_development_dependency 'sqlite3'
|
27
|
+
end
|
@@ -0,0 +1,56 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
class Person < ActiveRecord::Base
|
4
|
+
establish_connection :adapter => 'sqlite3', :database => ':memory:'
|
5
|
+
connection.create_table table_name, :force => true do |t|
|
6
|
+
t.string :name
|
7
|
+
end
|
8
|
+
end
|
9
|
+
|
10
|
+
describe FirstOrCreate do
|
11
|
+
before { Person.delete_all }
|
12
|
+
|
13
|
+
context 'when no record matches given attributes' do
|
14
|
+
context 'when attributes are valid' do
|
15
|
+
let(:attributes) { {:name => 'Joe'} }
|
16
|
+
|
17
|
+
it 'should create a new record' do
|
18
|
+
expect do
|
19
|
+
Person.first_or_create!(attributes)
|
20
|
+
end.to change(Person, :count).by(1)
|
21
|
+
end
|
22
|
+
|
23
|
+
it 'created record should have requested attributes' do
|
24
|
+
Person.first_or_create!(attributes)
|
25
|
+
Person.find_by_name(attributes[:name]).should_not be_nil
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
context 'when attributes are not valid' do
|
30
|
+
let(:attributes) { {:surname => 'Doe'} }
|
31
|
+
|
32
|
+
it 'should raise an error' do
|
33
|
+
expect do
|
34
|
+
Person.first_or_create!(attributes)
|
35
|
+
end.to raise_error(ActiveRecord::StatementInvalid)
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
context 'when a record matches given attributes' do
|
41
|
+
before do
|
42
|
+
@attributes = {:name => 'Joe'}
|
43
|
+
@joe = Person.create!(@attributes)
|
44
|
+
end
|
45
|
+
|
46
|
+
it 'should return that record' do
|
47
|
+
Person.first_or_create!(@attributes).should == @joe
|
48
|
+
end
|
49
|
+
|
50
|
+
it 'should not create a new record' do
|
51
|
+
expect do
|
52
|
+
Person.first_or_create!(@attributes)
|
53
|
+
end.to_not change(Person, :count)
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
@@ -0,0 +1,72 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe CommandRetry do
|
4
|
+
describe '#retry' do
|
5
|
+
context 'when command is successful' do
|
6
|
+
it 'should raise no error' do
|
7
|
+
command = CommandRetry.new {system 'echo'}
|
8
|
+
lambda {command.retry}.should_not raise_error
|
9
|
+
end
|
10
|
+
end
|
11
|
+
|
12
|
+
context 'when command is not successful' do
|
13
|
+
it 'should raise an error' do
|
14
|
+
command = CommandRetry.new {system 'will fail'}
|
15
|
+
lambda {command.retry}.should raise_error(RuntimeError)
|
16
|
+
end
|
17
|
+
|
18
|
+
context 'when providing "times" option' do
|
19
|
+
subject { CommandRetry.new(:times => 5) {system 'will fail'} }
|
20
|
+
|
21
|
+
it 'should repeat operation, if not successful' do
|
22
|
+
subject.expects(:exit_status).times(5).returns(1)
|
23
|
+
subject.retry rescue nil
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
context 'when providing "fail" option' do
|
28
|
+
context 'when "fail" is a class' do
|
29
|
+
subject { CommandRetry.new(:fail => ArgumentError) {system 'will fail'} }
|
30
|
+
|
31
|
+
it 'should raise expected error' do
|
32
|
+
lambda {subject.retry}.should raise_error(ArgumentError)
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
context 'when "fail" is set to false' do
|
37
|
+
subject { CommandRetry.new(:fail => false) {system 'will fail'} }
|
38
|
+
|
39
|
+
it 'should raise no error' do
|
40
|
+
lambda {subject.retry}.should_not raise_error
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
context 'when providing "on" option' do
|
46
|
+
subject { CommandRetry.new(:on => 42, :times => 3) {system 'will fail'} }
|
47
|
+
|
48
|
+
it 'should retry for given exit codes' do
|
49
|
+
subject.expects(:exit_status).times(3).returns(42)
|
50
|
+
subject.retry rescue nil
|
51
|
+
end
|
52
|
+
|
53
|
+
it 'should not raise error for other exit codes' do
|
54
|
+
subject.expects(:exit_status).times(1).returns(1)
|
55
|
+
lambda {subject.retry}.should_not raise_error
|
56
|
+
end
|
57
|
+
|
58
|
+
it 'should not retry for other exit codes' do
|
59
|
+
subject.expects(:exit_status).times(1).returns(1)
|
60
|
+
subject.retry
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
describe '::retry' do
|
67
|
+
it 'should wrap initialization and retry process' do
|
68
|
+
CommandRetry.any_instance.expects(:retry)
|
69
|
+
CommandRetry.retry(:fail => false) {system 'ls'}
|
70
|
+
end
|
71
|
+
end
|
72
|
+
end
|
@@ -0,0 +1,13 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Array do
|
4
|
+
describe '#uniq_by' do
|
5
|
+
it 'should return an array' do
|
6
|
+
[].uniq_by {}.should be_an(Array)
|
7
|
+
end
|
8
|
+
|
9
|
+
it 'should return unique values' do
|
10
|
+
[1, 2, 3, 4].uniq_by { |i| i.odd? }.should == [1, 2]
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
@@ -0,0 +1,44 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe QuickLogger do
|
4
|
+
class TestLogger < QuickLogger; end
|
5
|
+
|
6
|
+
it 'should have filename accessor' do
|
7
|
+
filename = 'something_else'
|
8
|
+
TestLogger.filename = filename
|
9
|
+
TestLogger.filename.should == filename
|
10
|
+
end
|
11
|
+
|
12
|
+
describe 'filename_path' do
|
13
|
+
context 'when extending a rails app' do
|
14
|
+
before do
|
15
|
+
unless defined?(Rails)
|
16
|
+
module Rails; end
|
17
|
+
end
|
18
|
+
Rails.stubs(:env => 'test', :root => '/rails/rootpath')
|
19
|
+
end
|
20
|
+
|
21
|
+
it 'should be in log dir, include rails env, have log extension' do
|
22
|
+
TestLogger.filename = 'some/path'
|
23
|
+
TestLogger.filename_path.should == '/rails/rootpath/log/some/path.test.log'
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
context 'when used alone' do
|
28
|
+
before do
|
29
|
+
Object.send(:remove_const, :Rails) if defined?(Rails)
|
30
|
+
end
|
31
|
+
|
32
|
+
it 'should match the plain filename' do
|
33
|
+
TestLogger.filename = 'other/path'
|
34
|
+
TestLogger.filename_path.should == 'other/path.log'
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
it 'should respond to classic logger methods' do
|
40
|
+
lambda do
|
41
|
+
TestLogger.info "message"
|
42
|
+
end.should_not raise_error(NameError)
|
43
|
+
end
|
44
|
+
end
|
data/spec/spec_helper.rb
ADDED
metadata
ADDED
@@ -0,0 +1,165 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: rails2ext
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
hash: 29
|
5
|
+
prerelease:
|
6
|
+
segments:
|
7
|
+
- 0
|
8
|
+
- 0
|
9
|
+
- 1
|
10
|
+
version: 0.0.1
|
11
|
+
platform: ruby
|
12
|
+
authors:
|
13
|
+
- andrea longhi
|
14
|
+
autorequire:
|
15
|
+
bindir: bin
|
16
|
+
cert_chain: []
|
17
|
+
|
18
|
+
date: 2012-07-11 00:00:00 Z
|
19
|
+
dependencies:
|
20
|
+
- !ruby/object:Gem::Dependency
|
21
|
+
name: rails
|
22
|
+
version_requirements: &id001 !ruby/object:Gem::Requirement
|
23
|
+
none: false
|
24
|
+
requirements:
|
25
|
+
- - ~>
|
26
|
+
- !ruby/object:Gem::Version
|
27
|
+
hash: 3
|
28
|
+
segments:
|
29
|
+
- 2
|
30
|
+
- 3
|
31
|
+
- 0
|
32
|
+
version: 2.3.0
|
33
|
+
type: :runtime
|
34
|
+
requirement: *id001
|
35
|
+
prerelease: false
|
36
|
+
- !ruby/object:Gem::Dependency
|
37
|
+
name: rake
|
38
|
+
version_requirements: &id002 !ruby/object:Gem::Requirement
|
39
|
+
none: false
|
40
|
+
requirements:
|
41
|
+
- - ">="
|
42
|
+
- !ruby/object:Gem::Version
|
43
|
+
hash: 3
|
44
|
+
segments:
|
45
|
+
- 0
|
46
|
+
version: "0"
|
47
|
+
type: :development
|
48
|
+
requirement: *id002
|
49
|
+
prerelease: false
|
50
|
+
- !ruby/object:Gem::Dependency
|
51
|
+
name: rspec
|
52
|
+
version_requirements: &id003 !ruby/object:Gem::Requirement
|
53
|
+
none: false
|
54
|
+
requirements:
|
55
|
+
- - ">="
|
56
|
+
- !ruby/object:Gem::Version
|
57
|
+
hash: 3
|
58
|
+
segments:
|
59
|
+
- 0
|
60
|
+
version: "0"
|
61
|
+
type: :development
|
62
|
+
requirement: *id003
|
63
|
+
prerelease: false
|
64
|
+
- !ruby/object:Gem::Dependency
|
65
|
+
name: mocha
|
66
|
+
version_requirements: &id004 !ruby/object:Gem::Requirement
|
67
|
+
none: false
|
68
|
+
requirements:
|
69
|
+
- - ">="
|
70
|
+
- !ruby/object:Gem::Version
|
71
|
+
hash: 3
|
72
|
+
segments:
|
73
|
+
- 0
|
74
|
+
version: "0"
|
75
|
+
type: :development
|
76
|
+
requirement: *id004
|
77
|
+
prerelease: false
|
78
|
+
- !ruby/object:Gem::Dependency
|
79
|
+
name: sqlite3
|
80
|
+
version_requirements: &id005 !ruby/object:Gem::Requirement
|
81
|
+
none: false
|
82
|
+
requirements:
|
83
|
+
- - ">="
|
84
|
+
- !ruby/object:Gem::Version
|
85
|
+
hash: 3
|
86
|
+
segments:
|
87
|
+
- 0
|
88
|
+
version: "0"
|
89
|
+
type: :development
|
90
|
+
requirement: *id005
|
91
|
+
prerelease: false
|
92
|
+
description: some useful extensions for rails 2 apps
|
93
|
+
email:
|
94
|
+
- andrea@spaghetticode.it
|
95
|
+
executables: []
|
96
|
+
|
97
|
+
extensions: []
|
98
|
+
|
99
|
+
extra_rdoc_files: []
|
100
|
+
|
101
|
+
files:
|
102
|
+
- .gitignore
|
103
|
+
- .rspec
|
104
|
+
- CHANGELOG
|
105
|
+
- Gemfile
|
106
|
+
- README.md
|
107
|
+
- Rakefile
|
108
|
+
- lib/rails2ext.rb
|
109
|
+
- lib/rails2ext/active_record.rb
|
110
|
+
- lib/rails2ext/active_record/first_or_create.rb
|
111
|
+
- lib/rails2ext/active_support.rb
|
112
|
+
- lib/rails2ext/active_support/command_retry.rb
|
113
|
+
- lib/rails2ext/active_support/core_ext.rb
|
114
|
+
- lib/rails2ext/active_support/core_ext/array.rb
|
115
|
+
- lib/rails2ext/active_support/core_ext/array/uniq_by.rb
|
116
|
+
- lib/rails2ext/active_support/core_ext/load_error.rb
|
117
|
+
- lib/rails2ext/active_support/quick_logger.rb
|
118
|
+
- lib/rails2ext/version.rb
|
119
|
+
- rails2ext.gemspec
|
120
|
+
- spec/active_record/first_or_create_spec.rb
|
121
|
+
- spec/active_support/command_retry_spec.rb
|
122
|
+
- spec/active_support/core_ext/array/uniq_by_spec.rb
|
123
|
+
- spec/active_support/core_ext/load_error_spec.rb
|
124
|
+
- spec/active_support/quick_logger_spec.rb
|
125
|
+
- spec/spec_helper.rb
|
126
|
+
homepage: ""
|
127
|
+
licenses: []
|
128
|
+
|
129
|
+
post_install_message:
|
130
|
+
rdoc_options: []
|
131
|
+
|
132
|
+
require_paths:
|
133
|
+
- lib
|
134
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
135
|
+
none: false
|
136
|
+
requirements:
|
137
|
+
- - ">="
|
138
|
+
- !ruby/object:Gem::Version
|
139
|
+
hash: 3
|
140
|
+
segments:
|
141
|
+
- 0
|
142
|
+
version: "0"
|
143
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
144
|
+
none: false
|
145
|
+
requirements:
|
146
|
+
- - ">="
|
147
|
+
- !ruby/object:Gem::Version
|
148
|
+
hash: 3
|
149
|
+
segments:
|
150
|
+
- 0
|
151
|
+
version: "0"
|
152
|
+
requirements: []
|
153
|
+
|
154
|
+
rubyforge_project:
|
155
|
+
rubygems_version: 1.8.24
|
156
|
+
signing_key:
|
157
|
+
specification_version: 3
|
158
|
+
summary: some useful extensions for rails 2 apps
|
159
|
+
test_files:
|
160
|
+
- spec/active_record/first_or_create_spec.rb
|
161
|
+
- spec/active_support/command_retry_spec.rb
|
162
|
+
- spec/active_support/core_ext/array/uniq_by_spec.rb
|
163
|
+
- spec/active_support/core_ext/load_error_spec.rb
|
164
|
+
- spec/active_support/quick_logger_spec.rb
|
165
|
+
- spec/spec_helper.rb
|