with_model 0.3.2 → 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: fb1eb5e067e816d4644cde5fa9da460fd764ac36
4
- data.tar.gz: 5de4c0d4f74cf020b4c6541b31fdcdb3ac4d053b
3
+ metadata.gz: b88698902a3eed64e0fc34a173d4758e4f108dc5
4
+ data.tar.gz: 49b3e03abeccfc847d9f5751e5107ff3c486233e
5
5
  SHA512:
6
- metadata.gz: 809520bde82da03692043a5e3b23bce6ceaffcaba26db542e4dec5380658bc00551ea8c6504d04c2a702a5983397d7a047596558926d79c0616f9296332a8b8c
7
- data.tar.gz: e64fcb0db081580c10cd54f0b15f4ccde04fdadc5dd92edef5cc3944d68c7a54bb965b4a811f99999042402ee0d4d6c733929b03c3a02d4152d166a5619ceeca
6
+ metadata.gz: e021cf0aa7032ea90c7572f28172d2158062682f382fbe8036489b88120607e986638c3b059cf3be30605f93465c90e3c417ff616f8b385a2eff0f097a4d1814
7
+ data.tar.gz: efd6470ae68ea7ae8861f8b0067c8fddb67062553e68eb88ec6c6afa53fc8f7160f8e05490fb1521da135e6c2fde76ec473dab85f0e48e3caa13a9781e12ca67
data/.gitignore CHANGED
@@ -1,8 +1,9 @@
1
- .idea
2
1
  pkg/*
3
- *.gem
4
- .bundle
5
- .rvmrc
6
2
  doc
3
+ coverage
7
4
  Gemfile.lock
5
+ .rvmrc
6
+ .idea
7
+ .bundle
8
8
  *.rbc
9
+ *.gem
@@ -1,30 +1,20 @@
1
1
  language: ruby
2
2
 
3
- script: "bundle exec rspec spec"
4
-
5
3
  rvm:
6
- - 1.8.7
7
4
  - 1.9.3
8
5
  - 2.0.0
9
- - jruby-18mode
10
6
  - jruby-19mode
11
- - rbx-18mode
12
- - rbx-19mode
13
- - ree
7
+ - rbx-2.2
14
8
 
15
9
  env:
16
- - ACTIVE_RECORD_VERSION="~> 4.0.0.rc1"
10
+ - ACTIVE_RECORD_BRANCH="master"
11
+ - ACTIVE_RECORD_BRANCH="4-0-stable"
12
+ - ACTIVE_RECORD_VERSION="~> 4.0.0"
17
13
  - ACTIVE_RECORD_VERSION="~> 3.2.0"
18
14
  - ACTIVE_RECORD_VERSION="~> 3.1.0"
19
15
  - ACTIVE_RECORD_VERSION="~> 3.0.0"
20
16
 
21
17
  matrix:
22
18
  allow_failures:
23
- - env: ACTIVE_RECORD_VERSION="~> 4.0.0.rc1"
24
- exclude:
25
- - rvm:
26
- - 1.8.7
27
- - jruby-18mode
28
- - rbx-18mode
29
- - ree
30
- env: ACTIVE_RECORD_VERSION="~> 4.0.0.rc1"
19
+ - env: ACTIVE_RECORD_BRANCH="master"
20
+ - env: ACTIVE_RECORD_BRANCH="4-0-stable"
@@ -0,0 +1,70 @@
1
+ ### 1.0.0
2
+ - Start using [Semantic Versioning 2.0.0](http://semver.org/spec/v2.0.0.html)
3
+ - Complete refactor of internals (Andrew Marshall)
4
+ - Remove support for Active Record 2 (Andrew Marshall)
5
+ - Remove dependency on RSpec (Andrew Marshall)
6
+ - Add support for MiniTest (Andrew Marshall)
7
+ - Add option for specifying superclass (Miks Miķelsons)
8
+
9
+ ### 0.3.2
10
+
11
+ - Allow calling with_model without a block. (Andrew Marshall)
12
+ - Ensure that ActiveSupport's descendants works correctly between tests. (Andrew Marshall)
13
+ - Allow Active Record 4 in gemspec.
14
+
15
+ ### 0.3.1
16
+
17
+ - Don't cache connection between tests. (Ryan Ong & Richard Nuno)
18
+
19
+ ### 0.3
20
+
21
+ - Use RSpec 2.11's built-in constant stubbing.
22
+ - Remove RSpec 1.x and Active Record 2.x support.
23
+ - Remove Mixico support.
24
+
25
+ ### 0.2.6
26
+
27
+ - Active Record 3.2 compatible. (Steven Harman / Brent Wheeldon)
28
+
29
+ ### 0.2.5
30
+
31
+ - Clear Active Record 3.x associations class cache between specs to clean up test
32
+ - pollution.
33
+
34
+ ### 0.2.4
35
+
36
+ - Active Record 3.1 compatible.
37
+ - Fix bug where column information was being cached incorrectly by Active
38
+ - Record.
39
+
40
+ ### 0.2.3
41
+
42
+ - Create a new class each run to prevent test pollution. (J. Andrew Marshall)
43
+ - Use :UpperCase in examples.
44
+
45
+ ### 0.2.2
46
+
47
+ - The table block is now optional.
48
+
49
+ ### 0.2.1
50
+
51
+ - Fix a bug when the with_model name contains capital letters. Now you can
52
+ - safely make calls like `with_model :BlogPost`
53
+
54
+ ### 0.2
55
+
56
+ - Remove the buggy attr_accessor method for accessing with_model classes. Now
57
+ - there is only the constant available in the example group.
58
+
59
+ ### 0.1.5
60
+
61
+ - WithModel::Base is now marked as an abstract_class, which makes polymorphic
62
+ - belongs_to work properly.
63
+
64
+ ### 0.1.4
65
+
66
+ - Add ability to pass arguments to create_table.
67
+
68
+ ### 0.1.2
69
+
70
+ - Make Mixico optional.
data/Gemfile CHANGED
@@ -1,10 +1,9 @@
1
- source "https://rubygems.org"
1
+ source 'https://rubygems.org'
2
2
 
3
3
  gemspec
4
4
 
5
- gem "rake"
6
- gem "sqlite3", :platforms => :ruby
7
- gem "activerecord-jdbcsqlite3-adapter", :platforms => :jruby
8
- gem "rdoc"
5
+ gem 'activerecord', :github => 'rails', :branch => ENV['ACTIVE_RECORD_BRANCH'] if ENV['ACTIVE_RECORD_BRANCH']
6
+ gem 'activerecord', ENV['ACTIVE_RECORD_VERSION'] if ENV['ACTIVE_RECORD_VERSION']
7
+ gem 'activerecord-jdbcsqlite3-adapter', :platforms => :jruby
9
8
  gem 'coveralls', :require => false, :platform => :mri_20
10
- gem 'activerecord', ENV["ACTIVE_RECORD_VERSION"] if ENV["ACTIVE_RECORD_VERSION"]
9
+ gem 'sqlite3', :platforms => :ruby
data/LICENSE CHANGED
@@ -1,4 +1,4 @@
1
- Copyright (c) 2010 Case Commons, LLC
1
+ Copyright (c) 2010-2013 Case Commons, LLC
2
2
 
3
3
  Permission is hereby granted, free of charge, to any person obtaining a copy
4
4
  of this software and associated documentation files (the "Software"), to deal
@@ -0,0 +1,164 @@
1
+ # [with_model](https://github.com/Casecommons/with_model)
2
+
3
+ [![Build Status](https://secure.travis-ci.org/Casecommons/with_model.png?branch=master)](https://travis-ci.org/Casecommons/with_model)
4
+ [![Code Climate](https://codeclimate.com/github/Casecommons/with_model.png)](https://codeclimate.com/github/Casecommons/with_model)
5
+ [![Coverage Status](https://coveralls.io/repos/Casecommons/with_model/badge.png?branch=master)](https://coveralls.io/r/Casecommons/with_model)
6
+ [![Gem Version](https://badge.fury.io/rb/with_model.png)](https://rubygems.org/gems/with_model)
7
+ [![Dependency Status](https://gemnasium.com/Casecommons/with_model.png)](https://gemnasium.com/Casecommons/with_model)
8
+
9
+ `with_model` dynamically builds an ActiveRecord model (with table) before each test in a group and destroys it afterwards.
10
+
11
+ ## Installation
12
+
13
+ Install as usual: `gem install with_model` or add `gem 'with_model'` to your Gemfile. See `.travis.yml` for supported (tested) Ruby versions.
14
+
15
+ ## RSpec
16
+
17
+ Extend `WithModel` into RSpec:
18
+
19
+ ```ruby
20
+ require 'with_model'
21
+
22
+ RSpec.configure do |config|
23
+ config.extend WithModel
24
+ end
25
+ ```
26
+
27
+ ## minitest/spec
28
+
29
+ Extend `WithModel` into minitest/spec:
30
+
31
+ ```ruby
32
+ require 'with_model'
33
+
34
+ class Minitest::Spec
35
+ extend WithModel
36
+ end
37
+ ```
38
+
39
+ ## Usage
40
+
41
+ After setting up as above, call `with_model` and inside its block pass it a `table` block and a `model` block.
42
+
43
+ ```ruby
44
+ require 'spec_helper'
45
+
46
+ describe "A blog post" do
47
+ before :all do
48
+ module SomeModule; end
49
+ end
50
+
51
+ after :all do
52
+ Object.send :remove_const, :SomeModule
53
+ end
54
+
55
+ with_model :BlogPost do
56
+ # The table block works just like a migration.
57
+ table do |t|
58
+ t.string :title
59
+ t.timestamps
60
+ end
61
+
62
+ # The model block works just like the class definition.
63
+ model do
64
+ include SomeModule
65
+ has_many :comments
66
+ validates_presence_of :title
67
+
68
+ def self.some_class_method
69
+ 'chunky'
70
+ end
71
+
72
+ def some_instance_method
73
+ 'bacon'
74
+ end
75
+ end
76
+ end
77
+
78
+ # with_model classes can have associations.
79
+ with_model :Comment do
80
+ table do |t|
81
+ t.string :text
82
+ t.belongs_to :blog_post
83
+ t.timestamps
84
+ end
85
+
86
+ model do
87
+ belongs_to :blog_post
88
+ end
89
+ end
90
+
91
+ it "can be accessed as a constant" do
92
+ expect(BlogPost).to be
93
+ end
94
+
95
+ it "has the module" do
96
+ expect(BlogPost.include?(SomeModule)).to be_true
97
+ end
98
+
99
+ it "has the class method" do
100
+ expect(BlogPost.some_class_method).to eq 'chunky'
101
+ end
102
+
103
+ it "has the instance method" do
104
+ expect(BlogPost.new.some_instance_method).to eq 'bacon'
105
+ end
106
+
107
+ it "can do all the things a regular model can" do
108
+ record = BlogPost.new
109
+ expect(record).to_not be_valid
110
+ record.title = "foo"
111
+ expect(record).to be_valid
112
+ expect(record.save).to be_true
113
+ expect(record.reload).to eq record
114
+ record.comments.create!(:text => "Lorem ipsum")
115
+ expect(record.comments.count).to eq 1
116
+ end
117
+
118
+ # with_model classes can have inheritance.
119
+ class Car < ActiveRecord::Base
120
+ self.abstract_class = true
121
+ end
122
+
123
+ with_model :Ford, superclass: Car do
124
+ end
125
+
126
+ it "has a specified superclass" do
127
+ expect(Ford < Car).to be_true
128
+ end
129
+ end
130
+
131
+ describe "another example group" do
132
+ it "does not have the constant anymore" do
133
+ expect(defined?(BlogPost)).to be_false
134
+ end
135
+ end
136
+
137
+ describe "with table options" do
138
+ with_model :WithOptions do
139
+ table :id => false do |t|
140
+ t.string 'foo'
141
+ t.timestamps
142
+ end
143
+ end
144
+
145
+ it "respects the additional options" do
146
+ expect(WithOptions.columns.map(&:name)).to_not include("id")
147
+ end
148
+ end
149
+ ```
150
+
151
+ ## Requirements
152
+
153
+ - Ruby 1.9.3+
154
+ - RSpec or minitest/spec
155
+ - ActiveRecord 3+ (for ActiveRecord 2, use with_model 0.2.x)
156
+
157
+ ## Versioning
158
+
159
+ As of version 1.0.0, with_model uses [Semantic Versioning 2.0.0](http://semver.org/spec/v2.0.0.html). Previous versions used an ad-hoc versioning scheme.
160
+
161
+ ## License
162
+
163
+ Copyright © 2010-2014 Case Commons, LLC.
164
+ Licensed under the MIT license, available in the “LICENSE” file.
data/Rakefile CHANGED
@@ -1,21 +1,13 @@
1
- require 'bundler'
2
- Bundler::GemHelper.install_tasks
1
+ require 'bundler/gem_tasks'
2
+ require 'rspec/core/rake_task'
3
3
 
4
- task :default => :spec
5
-
6
- def bundle_exec(command)
7
- sh %Q{bundle update && bundle exec #{command}}
8
- end
9
-
10
- desc "Run all specs"
11
- task "spec" do
12
- bundle_exec("rspec spec")
13
- end
4
+ desc 'Run specs'
5
+ RSpec::Core::RakeTask.new
14
6
 
15
7
  namespace "doc" do
16
8
  desc "Generate README and preview in browser"
17
9
  task "readme" do
18
- sh "rdoc -c utf8 README.rdoc && open doc/README_rdoc.html"
10
+ sh "markdown README.md > README.html && open README.html"
19
11
  end
20
12
  end
21
13
 
@@ -1,23 +1,22 @@
1
+ require 'with_model/model'
2
+ require 'with_model/model/dsl'
3
+ require 'with_model/table'
4
+ require 'with_model/version'
5
+
1
6
  module WithModel
2
- autoload :Base, "with_model/base"
3
- autoload :Dsl, "with_model/dsl"
4
- autoload :VERSION, "with_model/version"
7
+ def with_model(name, options = {}, &block)
8
+ model = Model.new name, options
9
+ dsl = Model::DSL.new model
10
+ dsl.instance_exec(&block) if block
5
11
 
6
- def with_model(name, &block)
7
- dsl = Dsl.new(name, self)
8
- dsl.instance_eval(&block) if block
9
- dsl.execute
12
+ before { model.create }
13
+ after { model.destroy }
10
14
  end
11
15
 
12
16
  def with_table(name, options = {}, &block)
13
- before do
14
- connection = ActiveRecord::Base.connection
15
- connection.drop_table(name) if connection.table_exists?(name)
16
- connection.create_table(name, options, &block)
17
- end
17
+ table = Table.new name, options, &block
18
18
 
19
- after do
20
- ActiveRecord::Base.connection.drop_table(name)
21
- end
19
+ before { table.create }
20
+ after { table.destroy }
22
21
  end
23
22
  end
@@ -0,0 +1,24 @@
1
+ module WithModel
2
+ class ConstantStubber
3
+ def initialize const_name
4
+ @const_name = const_name.to_sym
5
+ @original_value = nil
6
+ end
7
+
8
+ def stub_const value
9
+ if Object.const_defined?(@const_name)
10
+ @original_value = Object.const_get(@const_name)
11
+ Object.send :remove_const, @const_name
12
+ end
13
+
14
+ Object.const_set @const_name, value
15
+ end
16
+
17
+ def unstub_const
18
+ Object.send :remove_const, @const_name
19
+ Object.const_set @const_name, @original_value if @original_value
20
+ @original_value = nil
21
+ end
22
+ end
23
+ private_constant :ConstantStubber
24
+ end
@@ -0,0 +1,7 @@
1
+ module WithModel
2
+ module Methods
3
+ def with_model?
4
+ true
5
+ end
6
+ end
7
+ end
@@ -0,0 +1,76 @@
1
+ require 'active_support/core_ext/string/inflections'
2
+ require 'with_model/constant_stubber'
3
+ require 'with_model/methods'
4
+ require 'with_model/table'
5
+
6
+ module WithModel
7
+ class Model
8
+ attr_writer :model_block, :table_block, :table_options
9
+
10
+ def initialize name, options = {}
11
+ @name = name.to_sym
12
+ @options = options
13
+ @model_block = proc {}
14
+ @table_block = proc {}
15
+ @table_options = {}
16
+ end
17
+
18
+ def create
19
+ table.create
20
+ @model = Class.new(superclass)
21
+
22
+ class << @model
23
+ include WithModel::Methods
24
+ end
25
+
26
+ stubber.stub_const @model
27
+ setup_model
28
+ end
29
+
30
+ def superclass
31
+ @options.fetch(:superclass) { ActiveRecord::Base }
32
+ end
33
+
34
+ def destroy
35
+ stubber.unstub_const
36
+ remove_from_superclass_descendants
37
+ reset_dependencies_cache
38
+ table.destroy
39
+ @model = nil
40
+ end
41
+
42
+ private
43
+
44
+ def const_name
45
+ @name.to_s.camelize.freeze
46
+ end
47
+
48
+ def setup_model
49
+ @model.table_name = table_name
50
+ @model.class_eval(&@model_block)
51
+ @model.reset_column_information
52
+ end
53
+
54
+ def remove_from_superclass_descendants
55
+ return unless @model.superclass.respond_to?(:direct_descendants)
56
+ @model.superclass.direct_descendants.delete(@model)
57
+ end
58
+
59
+ def reset_dependencies_cache
60
+ return unless defined?(ActiveSupport::Dependencies::Reference)
61
+ ActiveSupport::Dependencies::Reference.clear!
62
+ end
63
+
64
+ def stubber
65
+ @stubber ||= ConstantStubber.new const_name
66
+ end
67
+
68
+ def table
69
+ @table ||= Table.new table_name, @table_options, &@table_block
70
+ end
71
+
72
+ def table_name
73
+ "with_model_#{@name.to_s.tableize}_#{$$}".freeze
74
+ end
75
+ end
76
+ end