rails2ext 0.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,5 @@
1
+ *.gem
2
+ .bundle
3
+ Gemfile.lock
4
+ pkg/*
5
+ something_else.log
data/.rspec ADDED
@@ -0,0 +1 @@
1
+ --color
@@ -0,0 +1,2 @@
1
+ = Version 0.0.1
2
+ * First release
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source "http://rubygems.org"
2
+
3
+ # Specify your gem's dependencies in rails2ext.gemspec
4
+ gemspec
@@ -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.
@@ -0,0 +1,8 @@
1
+ require 'bundler'
2
+ Bundler::GemHelper.install_tasks
3
+
4
+ require 'bundler/gem_tasks'
5
+ require 'rspec/core/rake_task'
6
+
7
+ Rspec::Core::RakeTask.new(:spec)
8
+ task :default => :spec
@@ -0,0 +1,7 @@
1
+ module Rails2ext
2
+ require 'active_support/all'
3
+ require 'active_record'
4
+ %w[active_support active_record].each do |filename|
5
+ require File.expand_path "../rails2ext/#{filename}", __FILE__
6
+ end
7
+ end
@@ -0,0 +1,3 @@
1
+ require File.join(File.dirname(__FILE__), 'active_record/first_or_create')
2
+
3
+ ActiveRecord::Base.extend FirstOrCreate
@@ -0,0 +1,5 @@
1
+ module FirstOrCreate
2
+ def first_or_create!(args)
3
+ find(:first, :conditions => args) || new(args).tap {|record| record.save! }
4
+ end
5
+ end
@@ -0,0 +1,5 @@
1
+ module ActiveSupport
2
+ require File.join(File.dirname(__FILE__), 'active_support/core_ext')
3
+ require File.join(File.dirname(__FILE__), 'active_support/command_retry')
4
+ require File.join(File.dirname(__FILE__), 'active_support/quick_logger')
5
+ end
@@ -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,11 @@
1
+ class Array
2
+ # Returns an unique array based on the criteria given as a +Proc+.
3
+ #
4
+ # [1, 2, 3, 4].uniq_by { |i| i.odd? } # => [1, 2]
5
+ #
6
+ def uniq_by
7
+ hash, array = {}, []
8
+ each { |i| hash[yield(i)] ||= (array << i) }
9
+ array
10
+ end
11
+ end
@@ -0,0 +1,4 @@
1
+ class MissingSourceFile
2
+ REGEXPS << [/^cannot load such file -- (.+)$/i, 1]
3
+ end
4
+
@@ -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
@@ -0,0 +1,3 @@
1
+ module Rails2ext
2
+ VERSION = "0.0.1"
3
+ end
@@ -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,5 @@
1
+ describe MissingSourceFile do
2
+ describe 'REGEXPS' do
3
+ it { MissingSourceFile::REGEXPS.should include([/^cannot load such file -- (.+)$/i, 1]) }
4
+ end
5
+ 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
@@ -0,0 +1,6 @@
1
+ require 'mocha'
2
+ require 'rails2ext'
3
+
4
+ Spec::Runner.configure do |config|
5
+ config.mock_with :mocha
6
+ end
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