with_model 0.3.2 → 1.0.0

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.
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