traitr 0.0.4 → 0.0.5

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: 020595fcb015240ac313662cc5e284f10ee4ab06
4
- data.tar.gz: 798775cefb913fc437972b29e8e412b792b29d9c
3
+ metadata.gz: 617169e1a6b866506fdb0e4804fe7d8e7eb22ad5
4
+ data.tar.gz: a54d3fa3d4ce4915eab40f90f89270efd2e7da23
5
5
  SHA512:
6
- metadata.gz: 7c8371264c2dcc1ce8b3cf7af4e057567c6b69e765e2e14279b420631f94b0de1ddc01e46623f50901e3700616563aba45d72d61a99eaa3911adc8ff959e1b56
7
- data.tar.gz: 0b71b50fe8da6da863269c9f6db7d82770a55ec6a1949f0b67eb4ce9a9f477058c6a0b73e6f5150ff2d14962ec3a57bdb72c67c456b720036f8a0b23ae915638
6
+ metadata.gz: 8fff94ed87623a0810bfd89ca3076dc8f2d3fd90cf21b284738d32a294dfe2cbd05f582b5fc143327f34ff90ec01bf82cd95e9fa7a00bbdfd1b697fc15240e4e
7
+ data.tar.gz: 5dfb5fb4b2af1e00372cddebdfec6b703364a9c20006d653a315d77e7ad6c3e5df8197df1b615ec9814a1b5b7da8b349df3a280bae0391147722fcc67aa80164
@@ -4,22 +4,21 @@ module Traitor
4
4
  @create_kwargs = {}
5
5
  @build_kwargs = {}
6
6
  @build_with_list = false # use (**attributes.merge(build_kwargs)) instead of (attributes, **build_kwargs)
7
+ @no_callbacks = false
7
8
 
8
9
  class << self
9
- attr_accessor :create_method, :create_kwargs, :build_kwargs, :build_with_list
10
+ attr_accessor :create_method, :create_kwargs, :build_kwargs, :build_with_list, :no_callbacks
10
11
 
11
12
  def configure_for_rails!
12
13
  @create_method = :save
13
14
  @create_kwargs = { validate: false }
14
15
  @build_kwargs = { without_protection: true }
15
- @build_with_list = false
16
16
  end
17
17
 
18
18
  def configure_safe_for_rails!
19
19
  @create_method = :save
20
20
  @create_kwargs = {}
21
21
  @build_kwargs = {}
22
- @build_with_list = false
23
22
  end
24
23
 
25
24
  def reset!
@@ -27,6 +26,19 @@ module Traitor
27
26
  @create_kwargs = {}
28
27
  @build_kwargs = {}
29
28
  @build_with_list = false
29
+ @no_callbacks = false
30
+ end
31
+
32
+ def stash!
33
+ @old_config = Hash[
34
+ self.instance_variables.map { |att| [att, self.instance_variable_get(att)] }
35
+ ]
36
+ end
37
+
38
+ def restore!
39
+ return unless @old_config
40
+ @old_config.each { |att, val| self.instance_variable_set(att, val) }
41
+ @old_config = nil
30
42
  end
31
43
  end
32
44
  end
@@ -0,0 +1,63 @@
1
+ # note that we do not have activerecord as a dependency in this gem!
2
+ # do not `require 'traitor/helpers/active_record'` unless you have ActiveRecord
3
+ # in your gemfile
4
+
5
+ require 'active_record'
6
+
7
+ module Traitor
8
+ module Helpers
9
+ module ActiveRecord
10
+ def create_without_callbacks
11
+ case self.class.connection.class.name
12
+ when 'ActiveRecord::ConnectionAdapters::PostgreSQLAdapter'
13
+ create_without_callbacks_pg
14
+ when 'ActiveRecord::ConnectionAdapters::SQLite3Adapter'
15
+ create_without_callbacks_sqlite
16
+ else
17
+ create_without_callbacks_default
18
+ end
19
+ end
20
+
21
+ private
22
+
23
+ def create_without_callbacks_default
24
+ insert_sql = self.class.arel_table.create_insert.tap do |im|
25
+ im.insert(self.send(:arel_attributes_with_values_for_create, self.attribute_names))
26
+ end.to_sql
27
+
28
+ pk = self.class.primary_key
29
+ self.class.connection.execute(insert_sql)
30
+ id = self.maximum(pk)
31
+ self.send(:"#{pk}=", id)
32
+ self.clear_changes_information
33
+ end
34
+
35
+ def create_without_callbacks_sqlite
36
+ insert_sql = self.class.arel_table.create_insert.tap do |im|
37
+ im.insert(self.send(:arel_attributes_with_values_for_create, self.attribute_names))
38
+ end.to_sql
39
+
40
+ conn = self.class.connection
41
+ conn.execute(insert_sql)
42
+
43
+ pk = self.class.primary_key
44
+ id = conn.execute("SELECT last_insert_rowid() AS id")[0]['id']
45
+ self.send(:"#{pk}=", id)
46
+ self.clear_changes_information
47
+ end
48
+
49
+ def create_without_callbacks_pg
50
+ insert_sql = self.class.arel_table.create_insert.tap do |im|
51
+ im.insert(self.send(:arel_attributes_with_values_for_create, self.attribute_names))
52
+ end.to_sql
53
+
54
+ pk = self.class.primary_key
55
+ id = self.class.connection.execute(insert_sql + " RETURNING #{pk}")[0][pk]
56
+ self.send(:"#{pk}=", id)
57
+ self.clear_changes_information
58
+ end
59
+ end
60
+ end
61
+ end
62
+
63
+ ActiveRecord::Base.send :include, Traitor::Helpers::ActiveRecord
@@ -0,0 +1,29 @@
1
+ require 'rspec'
2
+
3
+ module Traitor
4
+ module Helpers
5
+ class RSpec
6
+ def self.configure!
7
+ ::RSpec.configure do |config|
8
+ config.around(:example) do |example|
9
+ traitor_configs = example.metadata && example.metadata.select { |key, conf| key.to_s.start_with? 'traitor_' }
10
+ if traitor_configs && traitor_configs.any?
11
+ Traitor::Config.stash!
12
+ traitor_configs.each do |key, conf|
13
+ Traitor::Config.send(:"#{key.to_s.sub('traitor_', '')}=", conf)
14
+ end
15
+
16
+ example.run
17
+
18
+ Traitor::Config.restore!
19
+ else
20
+ example.run
21
+ end
22
+ end
23
+ end
24
+ end
25
+ end
26
+ end
27
+ end
28
+
29
+ Traitor::Helpers::RSpec.configure!
data/lib/traitor.rb CHANGED
@@ -6,139 +6,141 @@ module Traitor
6
6
  BLOCK_KEYS = [:after_build, :after_create]
7
7
 
8
8
  @trait_library = {}
9
+ @alternate_create_methods = {}
9
10
  @block_library = {}
10
11
  @class_cache = {}
11
12
  @trait_cache = {}
12
13
 
13
- def self.reset!
14
- @trait_library = {}
15
- @block_library = {}
16
- @class_cache = {}
17
- @trait_cache = {}
18
- end
14
+ class << self
15
+ def reset!
16
+ @trait_library = {}
17
+ @alternate_create_methods = {}
18
+ @block_library = {}
19
+ @class_cache = {}
20
+ @trait_cache = {}
21
+ end
19
22
 
20
- def self.define(klass, **traits)
21
- @trait_library[klass] ||= {}
23
+ def define(klass, **traits)
24
+ @trait_library[klass] ||= {}
22
25
 
23
- (traits.keys & BLOCK_KEYS).each do |block_type|
24
- block = traits.delete block_type
25
- @block_library[klass] ||= {class: {}, traits: {}}
26
- @block_library[klass][:class][block_type] = block
27
- end
26
+ if alternate_create_method = traits.delete(:create_using)
27
+ @alternate_create_methods[klass] = [alternate_create_method, traits.delete(:create_using_kwargs) || {}]
28
+ end
28
29
 
29
- traits.each do |trait, attributes|
30
- (attributes.keys & BLOCK_KEYS).each do |block_type|
31
- block = attributes.delete block_type
30
+ (traits.keys & BLOCK_KEYS).each do |block_type|
31
+ raise Traitor::Error.new("Callbacks are forbidden!") if Traitor::Config.no_callbacks
32
+ block = traits.delete block_type
32
33
  @block_library[klass] ||= {class: {}, traits: {}}
33
- @block_library[klass][:traits][trait] ||= {}
34
- @block_library[klass][:traits][trait][block_type] = block
34
+ @block_library[klass][:class][block_type] = block
35
35
  end
36
- end
37
36
 
38
- @trait_library[klass].merge!(traits)
39
- end
37
+ traits.each do |trait, attributes|
38
+ (attributes.keys & BLOCK_KEYS).each do |block_type|
39
+ raise Traitor::Error.new("Callbacks are forbidden!") if Traitor::Config.no_callbacks
40
+ block = attributes.delete block_type
41
+ @block_library[klass] ||= {class: {}, traits: {}}
42
+ @block_library[klass][:traits][trait] ||= {}
43
+ @block_library[klass][:traits][trait][block_type] = block
44
+ end
45
+ end
40
46
 
41
- ##
42
- # build an instance of an object using the defined traits and attributes,
43
- # and then save it.
44
- ##
45
- def self.create(klass, *traits, **attributes)
46
- create_method = Traitor::Config.create_method
47
- raise Traitor::Error.new("Cannot call Traitor.create until you have configured Traitor.create_method .") unless create_method
47
+ @trait_library[klass].merge!(traits)
48
+ end
48
49
 
49
- record = build(klass, *traits, **attributes)
50
+ ##
51
+ # build an instance of an object using the defined traits and attributes.
52
+ ##
53
+ def build(klass, *traits, **attributes)
54
+ attributes = get_attributes_from_traits(klass, traits).merge(attributes)
55
+ build_kwargs = Traitor::Config.build_kwargs || {}
56
+
57
+ record = if Traitor::Config.build_with_list
58
+ convert_to_class(klass).new(**attributes.merge(build_kwargs))
59
+ elsif build_kwargs.any?
60
+ convert_to_class(klass).new(attributes, **build_kwargs)
61
+ else
62
+ convert_to_class(klass).new(attributes)
63
+ end
50
64
 
51
- if (create_kwargs = Traitor::Config.create_kwargs).any? # assignment intentional
52
- record.public_send(create_method, **create_kwargs)
53
- else
54
- record.public_send(create_method)
65
+ call_blocks(klass, :after_build, record, *traits)
66
+ record
55
67
  end
56
68
 
57
- call_blocks(klass, :after_create, record, *traits)
58
- record
59
- end
69
+ ##
70
+ # build an instance of an object using the defined traits and attributes,
71
+ # and then save it.
72
+ ##
73
+ def create(klass, *traits, **attributes)
74
+ create_method, create_kwargs = @alternate_create_methods[klass] ||
75
+ [Traitor::Config.create_method, Traitor::Config.create_kwargs || {}]
60
76
 
61
- ##
62
- # build an instance of an object using the defined traits and attributes.
63
- ##
64
- def self.build(klass, *traits, **attributes)
65
- attributes = get_attributes_from_traits(klass, traits).merge(attributes)
66
- build_kwargs = Traitor::Config.build_kwargs
67
-
68
- record = if Traitor::Config.build_with_list
69
- convert_to_class(klass).new(**attributes.merge(build_kwargs))
70
- elsif build_kwargs.any?
71
- convert_to_class(klass).new(attributes, **build_kwargs)
72
- else
73
- convert_to_class(klass).new(attributes)
74
- end
77
+ raise Traitor::Error.new("Cannot call Traitor.create until you have configured Traitor.create_method .") unless create_method
75
78
 
76
- call_blocks(klass, :after_build, record, *traits)
77
- record
78
- end
79
+ record = build(klass, *traits, **attributes)
79
80
 
80
- def self.create_using(klass, create_method, *traits, **attributes)
81
- old_create_method = Traitor::Config.create_method
82
- old_create_kwargs = Traitor::Config.create_kwargs
81
+ if create_kwargs.any? # assignment intentional
82
+ record.public_send(create_method, **create_kwargs)
83
+ else
84
+ record.public_send(create_method)
85
+ end
83
86
 
84
- new_create_kwargs = attributes.delete :create_kwargs
85
- Traitor::Config.create_method = create_method
86
- Traitor::Config.create_kwargs = new_create_kwargs if new_create_kwargs
87
+ call_blocks(klass, :after_create, record, *traits)
88
+ record
89
+ end
87
90
 
88
- create(klass, *traits, **attributes)
89
- ensure
90
- Traitor::Config.create_method = old_create_method
91
- Traitor::Config.create_kwargs = old_create_kwargs
92
- end
91
+ def create_using(klass, create_method, *traits, **attributes)
92
+ old_create_method_kwargs = @alternate_create_methods[klass]
93
+ @alternate_create_methods[klass] = [create_method, attributes.delete(:create_kwargs) || {}]
94
+ create(klass, *traits, **attributes)
95
+ ensure
96
+ @alternate_create_methods[klass] = old_create_method_kwargs
97
+ end
93
98
 
94
- # private methods
99
+ private
95
100
 
96
- def self.call_blocks(klass, trigger, record, *traits)
97
- return unless @block_library[klass]
98
- [].tap do |blocks|
99
- blocks << @block_library[klass][:class][trigger]
100
- traits.each do |trait|
101
- if @block_library[klass][:traits][trait]
102
- blocks << @block_library[klass][:traits][trait][trigger]
101
+ def call_blocks(klass, trigger, record, *traits)
102
+ return unless @block_library[klass]
103
+ [].tap do |blocks|
104
+ blocks << @block_library[klass][:class][trigger]
105
+ traits.each do |trait|
106
+ if @block_library[klass][:traits][trait]
107
+ blocks << @block_library[klass][:traits][trait][trigger]
108
+ end
103
109
  end
104
- end
105
- end.compact.each { |block| block.call(record) }
106
- end
107
- private_class_method :call_blocks
110
+ end.compact.each { |block| block.call(record) }
111
+ end
108
112
 
109
- def self.convert_to_class(klass)
110
- @class_cache[klass] ||= Object.const_get(camelize(klass))
111
- rescue NameError
112
- raise Traitor::Error.new("Tried to create a #{camelize(klass)}, but it does not exist!")
113
- end
114
- private_class_method :convert_to_class
113
+ def convert_to_class(klass)
114
+ @class_cache[klass] ||= Object.const_get(camelize(klass))
115
+ rescue NameError
116
+ raise Traitor::Error.new("Tried to create a #{camelize(klass)}, but it does not exist!")
117
+ end
118
+
119
+ def get_attributes_from_traits(klass, traits)
120
+ # we only call this method when the klass has been converted to a key inside create
121
+ return {} unless library = @trait_library[klass]
115
122
 
116
- def self.get_attributes_from_traits(klass, traits)
117
- # we only call this method when the klass has been converted to a key inside create
118
- return {} unless library = @trait_library[klass]
123
+ traits = [:default_traits] + traits # always include default_traits as the first thing
119
124
 
120
- traits = [:default_traits] + traits # always include default_traits as the first thing
125
+ cache_key = klass.to_s + ':' + traits.join(':')
126
+ @trait_cache[cache_key] ||= {}.tap do |attributes|
127
+ traits.each { |trait| attributes.merge!(library[trait] || {}) }
128
+ end
121
129
 
122
- cache_key = klass.to_s + ':' + traits.join(':')
123
- @trait_cache[cache_key] ||= {}.tap do |attributes|
124
- traits.each { |trait| attributes.merge!(library[trait] || {}) }
130
+ # use late resolution on lambda values by calling them here as part of constructing a new hash
131
+ Hash[
132
+ @trait_cache[cache_key].map do |attribute, value|
133
+ [attribute, value.is_a?(Proc) && ![:after_build, :after_create].include?(attribute) ? value.call : value]
134
+ end
135
+ ]
125
136
  end
126
137
 
127
- # use late resolution on lambda values by calling them here as part of constructing a new hash
128
- Hash[
129
- @trait_cache[cache_key].map do |attribute, value|
130
- [attribute, value.is_a?(Proc) && ![:after_build, :after_create].include?(attribute) ? value.call : value]
131
- end
132
- ]
133
- end
134
- private_class_method :get_attributes_from_traits
135
-
136
- def self.camelize(term)
137
- string = term.to_s
138
- string[0] = string[0].upcase
139
- string.gsub!(/(?:_|(\/))([a-z\d]*)/i) { "#{$1}#{$2.capitalize}" }
140
- string.gsub!('/'.freeze, '::'.freeze)
141
- string
138
+ def camelize(term)
139
+ string = term.to_s
140
+ string[0] = string[0].upcase
141
+ string.gsub!(/(?:_|(\/))([a-z\d]*)/i) { "#{$1}#{$2.capitalize}" }
142
+ string.gsub!('/'.freeze, '::'.freeze)
143
+ string
144
+ end
142
145
  end
143
- private_class_method :camelize
144
146
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: traitr
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.4
4
+ version: 0.0.5
5
5
  platform: ruby
6
6
  authors:
7
7
  - Zach Lome
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2016-07-26 00:00:00.000000000 Z
11
+ date: 2016-07-28 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -25,35 +25,35 @@ dependencies:
25
25
  - !ruby/object:Gem::Version
26
26
  version: '0'
27
27
  - !ruby/object:Gem::Dependency
28
- name: rake
28
+ name: rspec
29
29
  requirement: !ruby/object:Gem::Requirement
30
30
  requirements:
31
31
  - - ">="
32
32
  - !ruby/object:Gem::Version
33
- version: '0'
33
+ version: '3.0'
34
34
  type: :development
35
35
  prerelease: false
36
36
  version_requirements: !ruby/object:Gem::Requirement
37
37
  requirements:
38
38
  - - ">="
39
39
  - !ruby/object:Gem::Version
40
- version: '0'
40
+ version: '3.0'
41
41
  - !ruby/object:Gem::Dependency
42
- name: rspec
42
+ name: rspec-its
43
43
  requirement: !ruby/object:Gem::Requirement
44
44
  requirements:
45
45
  - - ">="
46
46
  - !ruby/object:Gem::Version
47
- version: '0'
47
+ version: '1.0'
48
48
  type: :development
49
49
  prerelease: false
50
50
  version_requirements: !ruby/object:Gem::Requirement
51
51
  requirements:
52
52
  - - ">="
53
53
  - !ruby/object:Gem::Version
54
- version: '0'
54
+ version: '1.0'
55
55
  - !ruby/object:Gem::Dependency
56
- name: rspec-its
56
+ name: timecop
57
57
  requirement: !ruby/object:Gem::Requirement
58
58
  requirements:
59
59
  - - ">="
@@ -67,7 +67,7 @@ dependencies:
67
67
  - !ruby/object:Gem::Version
68
68
  version: '0'
69
69
  - !ruby/object:Gem::Dependency
70
- name: timecop
70
+ name: pry
71
71
  requirement: !ruby/object:Gem::Requirement
72
72
  requirements:
73
73
  - - ">="
@@ -81,7 +81,7 @@ dependencies:
81
81
  - !ruby/object:Gem::Version
82
82
  version: '0'
83
83
  - !ruby/object:Gem::Dependency
84
- name: pry
84
+ name: sqlite3
85
85
  requirement: !ruby/object:Gem::Requirement
86
86
  requirements:
87
87
  - - ">="
@@ -94,6 +94,20 @@ dependencies:
94
94
  - - ">="
95
95
  - !ruby/object:Gem::Version
96
96
  version: '0'
97
+ - !ruby/object:Gem::Dependency
98
+ name: activerecord
99
+ requirement: !ruby/object:Gem::Requirement
100
+ requirements:
101
+ - - "~>"
102
+ - !ruby/object:Gem::Version
103
+ version: '4'
104
+ type: :development
105
+ prerelease: false
106
+ version_requirements: !ruby/object:Gem::Requirement
107
+ requirements:
108
+ - - "~>"
109
+ - !ruby/object:Gem::Version
110
+ version: '4'
97
111
  description: a lightweight, simplified, pure-ruby way to handle object model construction,
98
112
  similar to FactoryGirl.
99
113
  email:
@@ -106,6 +120,8 @@ files:
106
120
  - lib/traitor/config.rb
107
121
  - lib/traitor/error.rb
108
122
  - lib/traitor/find_definitions.rb
123
+ - lib/traitor/helpers/active_record.rb
124
+ - lib/traitor/helpers/rspec.rb
109
125
  homepage: https://github.com/kuraiou/traitor
110
126
  licenses:
111
127
  - MIT