external_fields 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 7f07e8a7db6679bd7137bc5b612118d5d7554738
4
+ data.tar.gz: 9591ced4076f386180722d103d6177e46ea9f6f0
5
+ SHA512:
6
+ metadata.gz: 47c6d1ceacace126d600488a85b980ba7c466d32ef80e7b15b147015410134ae8b4a41175cc1ff911785e15499805cbaef07f89a5d38eda5a9694e142fa57fb6
7
+ data.tar.gz: 650583bada54722659ce56b4ac884e1b5fa460116263c32be4588e6ab31057c1e1480db31ca4fbabf81689503799da58f7d08f09d42af621ebe4fe11499e080a
data/.gitignore ADDED
@@ -0,0 +1,15 @@
1
+ /.bundle/
2
+ /.yardoc
3
+ /Gemfile.lock
4
+ /_yardoc/
5
+ /coverage/
6
+ /doc/
7
+ /pkg/
8
+ /spec/reports/
9
+ /tmp/
10
+ *.bundle
11
+ *.so
12
+ *.o
13
+ *.a
14
+ mkmf.log
15
+ *.gem
data/.overcommit.yml ADDED
@@ -0,0 +1,60 @@
1
+ CommitMsg:
2
+ CapitalizedSubject:
3
+ enabled: true
4
+ HardTabs:
5
+ enabled: true
6
+ RussianNovel:
7
+ enabled: true
8
+ SingleLineSubject:
9
+ enabled: true
10
+ TextWidth:
11
+ enabled: true
12
+ TrailingPeriod:
13
+ enabled: true
14
+ PreCommit:
15
+ AuthorEmail:
16
+ enabled: true
17
+ AuthorName:
18
+ enabled: true
19
+ Brakeman: # Performs static code security checking.
20
+ enabled: false
21
+ BrokenSymlinks:
22
+ enabled: true
23
+ BundleCheck:
24
+ enabled: true
25
+ CssLint:
26
+ enabled: true
27
+ HamlLint:
28
+ enabled: true
29
+ HardTabs:
30
+ enabled: true
31
+ HtmlTidy: # Uses the `tidy` executable (installed on OS X by default).
32
+ enabled: true
33
+ ImageOptim:
34
+ enabled: true
35
+ Jscs: # Checks for JavaScript style.
36
+ enabled: true
37
+ JsHint: # Checks for JavaScript best practices.
38
+ enabled: true
39
+ JsonSyntax:
40
+ enabled: true
41
+ LocalPathsInGemfile:
42
+ enabled: true
43
+ MergeConflicts:
44
+ enabled: true
45
+ PryBinding:
46
+ enabled: true
47
+ Reek:
48
+ enabled: false
49
+ RuboCop:
50
+ enabled: true
51
+ problem_on_unmodified_line: warn
52
+ ScssLint:
53
+ enabled: true
54
+ TrailingWhitespace:
55
+ enabled: true
56
+ TravisLint: # Checks Travis CI configurations. We use Travis for our open-
57
+ # source repositories.
58
+ enabled: true
59
+ YamlSyntax:
60
+ enabled: true
data/.rubocop.yml ADDED
@@ -0,0 +1,271 @@
1
+ require:
2
+ - rubocop/rspec/focused
3
+
4
+ # This (http://c2.com/cgi/wiki?AbcMetric) is super obnoxious
5
+ AbcSize:
6
+ Enabled: false
7
+
8
+ AccessorMethodName:
9
+ Enabled: false
10
+
11
+ Alias:
12
+ Enabled: false
13
+
14
+ AllCops:
15
+ Exclude:
16
+ - "vendor/**/*"
17
+ - "spec/dummy/**/*"
18
+ - "db/schema.rb"
19
+ - "db/migrate/**/*"
20
+ RunRailsCops: true
21
+
22
+ AmbiguousOperator:
23
+ Enabled: false
24
+
25
+ AmbiguousRegexpLiteral:
26
+ Enabled: false
27
+
28
+ ArrayJoin:
29
+ Enabled: false
30
+
31
+ AsciiComments:
32
+ Enabled: false
33
+
34
+ AsciiIdentifiers:
35
+ Enabled: false
36
+
37
+ AssignmentInCondition:
38
+ Enabled: true
39
+
40
+ Attr:
41
+ Enabled: false
42
+
43
+ BlockNesting:
44
+ Enabled: false
45
+
46
+ BracesAroundHashParameters:
47
+ Enabled: false
48
+
49
+ CaseEquality:
50
+ Enabled: false
51
+
52
+ CharacterLiteral:
53
+ Enabled: false
54
+
55
+ ClassLength:
56
+ Enabled: false
57
+
58
+ ClassVars:
59
+ Enabled: false
60
+
61
+ CollectionMethods:
62
+ PreferredMethods:
63
+ find: detect
64
+ reduce: inject
65
+ collect: map
66
+ find_all: select
67
+
68
+ ColonMethodCall:
69
+ Enabled: false
70
+
71
+ CommentAnnotation:
72
+ Enabled: false
73
+
74
+ ConditionPosition:
75
+ Enabled: false
76
+
77
+ CyclomaticComplexity:
78
+ Enabled: false
79
+
80
+ Delegate:
81
+ Enabled: false
82
+
83
+ DeprecatedClassMethods:
84
+ Enabled: false
85
+
86
+ DeprecatedHashMethods:
87
+ Enabled: false
88
+
89
+ Documentation:
90
+ Enabled: false
91
+
92
+ DotPosition:
93
+ EnforcedStyle: trailing
94
+
95
+ DoubleNegation:
96
+ Enabled: false
97
+
98
+ ElseLayout:
99
+ Enabled: false
100
+
101
+ EmptyLiteral:
102
+ Enabled: false
103
+
104
+ Encoding:
105
+ Enabled: false
106
+
107
+ EvenOdd:
108
+ Enabled: false
109
+
110
+ FileName:
111
+ Enabled: false
112
+
113
+ FlipFlop:
114
+ Enabled: false
115
+
116
+ FormatString:
117
+ Enabled: false
118
+
119
+ GlobalVars:
120
+ Enabled: false
121
+
122
+ GuardClause:
123
+ Enabled: false
124
+
125
+ HandleExceptions:
126
+ Enabled: false
127
+
128
+ IfUnlessModifier:
129
+ Enabled: false
130
+
131
+ IfWithSemicolon:
132
+ Enabled: false
133
+
134
+ InvalidCharacterLiteral:
135
+ Enabled: false
136
+
137
+ Lambda:
138
+ Enabled: false
139
+
140
+ LambdaCall:
141
+ Enabled: false
142
+
143
+ LineEndConcatenation:
144
+ Enabled: false
145
+
146
+ LineLength:
147
+ Max: 80
148
+
149
+ LiteralInCondition:
150
+ Enabled: false
151
+
152
+ LiteralInInterpolation:
153
+ Enabled: false
154
+
155
+ Loop:
156
+ Enabled: false
157
+
158
+ MethodLength:
159
+ Enabled: false
160
+
161
+ ModuleFunction:
162
+ Enabled: false
163
+
164
+ NegatedIf:
165
+ Enabled: false
166
+
167
+ NegatedWhile:
168
+ Enabled: false
169
+
170
+ Next:
171
+ Enabled: false
172
+
173
+ NilComparison:
174
+ Enabled: false
175
+
176
+ Not:
177
+ Enabled: false
178
+
179
+ NumericLiterals:
180
+ Enabled: false
181
+
182
+ OneLineConditional:
183
+ Enabled: false
184
+
185
+ OpMethod:
186
+ Enabled: false
187
+
188
+ ParameterLists:
189
+ Enabled: false
190
+
191
+ ParenthesesAsGroupedExpression:
192
+ Enabled: false
193
+
194
+ PercentLiteralDelimiters:
195
+ PreferredDelimiters:
196
+ '%': '{}'
197
+
198
+ PerceivedComplexity:
199
+ Enabled: false
200
+
201
+ PerlBackrefs:
202
+ Enabled: false
203
+
204
+ PredicateName:
205
+ Enabled: false
206
+
207
+ Proc:
208
+ Enabled: false
209
+
210
+ RaiseArgs:
211
+ Enabled: false
212
+
213
+ RedundantReturn:
214
+ AllowMultipleReturnValues: true
215
+
216
+ RegexpLiteral:
217
+ Enabled: false
218
+
219
+ RequireParentheses:
220
+ Enabled: false
221
+
222
+ Rspec/Focused:
223
+ Enabled: true
224
+
225
+ SelfAssignment:
226
+ Enabled: false
227
+
228
+ SignalException:
229
+ EnforcedStyle: only_raise
230
+
231
+ SingleLineBlockParams:
232
+ Enabled: false
233
+
234
+ SingleLineMethods:
235
+ Enabled: false
236
+
237
+ SpecialGlobalVars:
238
+ Enabled: false
239
+
240
+ StringLiterals:
241
+ EnforcedStyle: double_quotes
242
+
243
+ Style/MultilineBlockChain:
244
+ Enabled: false
245
+
246
+ VariableInterpolation:
247
+ Enabled: false
248
+
249
+ TrailingComma:
250
+ Enabled: false
251
+
252
+ TrivialAccessors:
253
+ Enabled: false
254
+
255
+ UnderscorePrefixedVariableName:
256
+ Enabled: false
257
+
258
+ VariableInterpolation:
259
+ Enabled: false
260
+
261
+ Void:
262
+ Enabled: false
263
+
264
+ WhenThen:
265
+ Enabled: false
266
+
267
+ WhileUntilModifier:
268
+ Enabled: false
269
+
270
+ WordArray:
271
+ Enabled: false
data/.travis.yml ADDED
@@ -0,0 +1,12 @@
1
+ language: ruby
2
+ rvm:
3
+ - 2.2.1
4
+ script: bundle exec rspec
5
+ addons:
6
+ code_climate:
7
+ repo_token: 9f025c501f5daf9ffc6712005e4cda18ce4f6afe76c2c0913889712cefb3679e
8
+ notifications:
9
+ email: false
10
+ hipchat:
11
+ rooms:
12
+ secure: c6XVH78Isrp/TvZsQaq2Ne442rLoUU5FX4N6PgF8jdbMIiPN5dEyURH1LgBop5grv2ZY8BwZeVjNvKVlr8V9wDoER6AV81MclV398qOiIy020dS8ahgpj7F7EO/hKU3iQX4d+3r3a5oeeWjDXdN4uPbeWR5uLXEsXDtX3HUZGxc1p/fT8xUSQufb+kZXccrYV2ryWIa7bQxWlpfAnTm/VQxl3tf5riK7vjq1TkwxvNl4Rv5TjkPFJkryyEcDtutX1jWF8O/nsxzejG604pfyZHcoDjl5erIatalHDwOxr7H1u0XYVpnldiv/L37TGkZaMWuRnCraWn6GDdmqWrpRWYqQfanpdNq9iNB8lWpsPDfnMgLQAbDnSobeeKkkQAeY0lgZjDwcP8AySjEGX/BhdIcYgs6l3C6JR3lj1P47w0KU9YgOxrRf32RGfVRfbT9cz/xqalPjVpJPOmdEoG4vC9tWZTaTBHNnmfJwrcuqnbCLh3mufVvjQD8LDo53xzKJqDguR+j7G0pKfYrwRyRbc1fwBeiVhQwmwtS8u/Swr8ImHN1r50Ma4FId+dBRkstqunfzHjchv/Om96KVPp8rL1sTMHyZvobre8OA4ovjxgQfTFIXholNtOH4Ege/ol9KxF+Sg1fBeELT8c2Jw8Hp46WduyrIcFkRBgNnSqcKnD8=
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source "https://rubygems.org"
2
+
3
+ # Specify your gem's dependencies in external_fields.gemspec
4
+ gemspec
data/LICENSE ADDED
@@ -0,0 +1,22 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2015 Panorama Education
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
22
+
data/README.md ADDED
@@ -0,0 +1,152 @@
1
+ [![Code Climate](https://codeclimate.com/github/panorama-ed/rails_external_fields/badges/gpa.svg)](https://codeclimate.com/github/panorama-ed/rails_external_fields) [![Test Coverage](https://codeclimate.com/github/panorama-ed/rails_external_fields/badges/coverage.svg)](https://codeclimate.com/github/panorama-ed/rails_external_fields) [![Build Status](https://travis-ci.org/panorama-ed/rails_external_fields.svg)](https://travis-ci.org/panorama-ed/rails_external_fields) [![Inline docs](http://inch-ci.org/github/panorama-ed/rails_external_fields.png)](http://inch-ci.org/github/panorama-ed/rails_external_fields) [![Gem Version](https://badge.fury.io/rb/rails_external_fields.svg)](http://badge.fury.io/rb/rails_external_fields)
2
+
3
+ # ExternalFields
4
+ Create the illusion that an object has specific attributes when those attributes
5
+ actually belong to an associated object.
6
+
7
+ This is particularly useful for different classes within a single-
8
+ table inheritance table to have access to separate fields in class-specific
9
+ associations.
10
+
11
+ ## Installation
12
+ Add this line to your application's Gemfile:
13
+
14
+ ````
15
+ gem "external_fields"
16
+ ```
17
+
18
+ And then execute:
19
+
20
+ ```
21
+ $ bundle
22
+ ```
23
+
24
+ Or install it yourself as:
25
+
26
+ ```
27
+ $ gem install external_fields
28
+ ```
29
+
30
+ ## Usage
31
+ Include `ExternalFields` and define the external fields using the `external_field` method. For example, if `grade_level`, `age` and `credits` are defined in another class `StudentData` and you want to access them in `Student` you could do:
32
+
33
+ ```ruby
34
+ require "active_record"
35
+ require "active_support"
36
+
37
+ require "external_fields"
38
+
39
+ class Student < ActiveRecord::Base
40
+ include ExternalFields
41
+
42
+ has_one :data,
43
+ class_name: StudentData
44
+
45
+ external_field :grade_level, # External attribute 1
46
+ :age, # External attribute 2
47
+ :credits, # External attribute 3
48
+ :data, # Name of the association
49
+ class_name: "StudentData" # Class name of association
50
+ end
51
+ ```
52
+
53
+ where the external fields are defined in another associated class:
54
+
55
+ ```ruby
56
+ class StudentData < ActiveRecord::Base
57
+ attr_accessor :grade_level, :age, :credits
58
+ end
59
+ ```
60
+
61
+ Now you can directly call the accessors on the `Student` objects:
62
+
63
+ ```ruby
64
+ > s = Student.create!
65
+ > s.age
66
+ => nil
67
+
68
+ > s.age = 10
69
+ > s.age
70
+ => 10
71
+
72
+ > s.grade_level = 4
73
+ > s.grade_level
74
+ => 4
75
+ ```
76
+
77
+ ### Overriding default behavior using `underscored` accessors
78
+ You can also add underscored accessors using the `underscore` flag
79
+
80
+ ```ruby
81
+ ...
82
+ external_field :grade_level, # External attribute 1
83
+ :age, # External attribute 2
84
+ :credits, # External attribute 3
85
+ :data, # Name of the association
86
+ class_name: "StudentData" # Class name of association
87
+ underscore: true # Flag for underscored accessors
88
+ ...
89
+ ```
90
+
91
+ This will allow you to use the external fields using underscored methods:
92
+ ```ruby
93
+ s = Student.create!
94
+ s._age
95
+ s._grade_level
96
+ ```
97
+
98
+ This approach lets you override the default behavior cleanly. For example,
99
+ you could override the grade level using this method:
100
+
101
+ ```ruby
102
+ def grade_level
103
+ if _grade_level == 0
104
+ "Kindergarten"
105
+ else
106
+ _grade_level
107
+ end
108
+ end
109
+ ```
110
+
111
+ ### Accessing the original association
112
+
113
+ In some instances it's helpful to be able to use the original association
114
+ without building an object on access. For instance, you might want to have a
115
+ validation inspect a value without creating a new object on each save. In that
116
+ case, you can use the `use_original` flag on the association like so:
117
+
118
+ ```ruby
119
+ validate :kindergarten_students_have_names
120
+
121
+ def kindergarten_students_have_names
122
+ data_obj = data(use_original: true)
123
+
124
+ if data_obj && grade_level == "Kindergarten" && name.blank?
125
+ # Note that `name` is an attribute on `Student` but `grade_level`
126
+ # is accessed through the `data` association as defined earlier
127
+ # in the README.
128
+ errors.add(:name, "must be present for kindergarten students")
129
+ end
130
+ end
131
+ ```
132
+
133
+ ## Documentation
134
+
135
+ We have documentation on [RubyDoc](http://www.rubydoc.info/github/panorama-ed/rails_external_fields/master).
136
+
137
+ ## Contributing
138
+
139
+ 1. Fork it (https://github.com/panorama-ed/rails_external_fields/fork)
140
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
141
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
142
+ 4. Push to the branch (`git push origin my-new-feature`)
143
+ 5. Create a new Pull Request
144
+
145
+ **Make sure your changes have appropriate tests (`bundle exec rspec`)
146
+ and conform to the Rubocop style specified.** We use
147
+ [overcommit](https://github.com/causes/overcommit) to enforce good code.
148
+
149
+ ## License
150
+
151
+ `ExternalFields` is released under the
152
+ [MIT License](https://github.com/panorama-ed/rails_external_fields/blob/master/LICENSE).
@@ -0,0 +1,39 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path("../lib", __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require "external_fields/version"
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = "external_fields"
8
+ spec.version = ExternalFields::VERSION
9
+ spec.authors = ["Sagar Jauhari"]
10
+ spec.email = ["sagarjauhari@gmail.com"]
11
+ spec.summary = "Access attributes from an associated model."
12
+ spec.description = "This concern maintains the illusion that a given "\
13
+ "object has specified attributes, when those "\
14
+ "attributes are in fact attached to an associated "\
15
+ "object. This is particularly useful for different "\
16
+ "classes within a single-table inheritance table to "\
17
+ "have access to separate fields in class-specific "\
18
+ "associations."
19
+
20
+ spec.homepage = "https://github.com/panorama-ed/rails-external-fields"
21
+ spec.license = "MIT"
22
+
23
+ spec.files = `git ls-files -z`.split("\x0")
24
+ spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
25
+ spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
26
+ spec.require_paths = ["lib"]
27
+
28
+ spec.add_dependency "activerecord", "~> 4.0"
29
+
30
+ spec.add_development_dependency "bundler", "~> 1.7"
31
+ spec.add_development_dependency "codeclimate-test-reporter", "~> 0.4"
32
+ spec.add_development_dependency "overcommit", "~> 0.23"
33
+ spec.add_development_dependency "rspec", "~> 3.2"
34
+ spec.add_development_dependency "rspec-rails", "~> 3.2"
35
+ spec.add_development_dependency "rubocop", "~> 0.29"
36
+ spec.add_development_dependency "rubocop-rspec-focused", "~> 0.0"
37
+ spec.add_development_dependency "temping", "~> 3.2"
38
+ spec.add_development_dependency "sqlite3", "~> 1.3"
39
+ end
@@ -0,0 +1,3 @@
1
+ module ExternalFields
2
+ VERSION = "0.1.0"
3
+ end
@@ -0,0 +1,87 @@
1
+ require "external_fields/version"
2
+
3
+ # This concern maintains the illusion that a given object has specified
4
+ # attributes, when those attributes are in fact attached to an associated
5
+ # object. This is particularly useful for different classes within a single-
6
+ # table inheritance table to have access to separate fields in class-specific
7
+ # associations.
8
+
9
+ module ExternalFields
10
+ extend ActiveSupport::Concern
11
+
12
+ included do
13
+ class_attribute :_external_field_associations
14
+
15
+ # Provides a getter and setter for the given attribute on the associated
16
+ # object. We provide either normal or underscored getters and setters, the
17
+ # latter allowing the defining class to use alias_method to override
18
+ # behavior while still accessing these underlying implementations.
19
+ #
20
+ # @param attrs [Array<Symbol>] list of external fields
21
+ # @param assoc [Symbol] name of the association
22
+ # @param class_name [String] name of the associated class
23
+ # @param underscore [Boolean] underscored accessor created if true
24
+ def self.external_field(*attrs, assoc, class_name: nil, underscore: false)
25
+ self._external_field_associations ||= []
26
+
27
+ attrs.each do |attr|
28
+ # Store the original association method for use in the overwritten one.
29
+ original_method = instance_method(assoc)
30
+
31
+ # First, we define an accessor for the associated object.
32
+ # Note we ensure that we only define the accessor once. Further, if
33
+ # `use_original` is true, we use the original Rails association
34
+ # accessor, which will not build a new object. Otherwise, we build a new
35
+ # object if one does not exist already.
36
+ unless self._external_field_associations.include? assoc
37
+ define_method assoc do |use_original: false|
38
+ if use_original
39
+ # Call original overwritten method
40
+ original_method.bind(self).call
41
+ else
42
+ # Try calling the original method to see if we get a result.
43
+ existing_value = original_method.bind(self).call
44
+
45
+ # Use existing value if one is there.
46
+ if existing_value
47
+ existing_value
48
+ else # Otherwise, build a new object.
49
+ # Find the class of the object we need to build.
50
+ klass = class_name.try(:constantize) ||
51
+ self.class.reflect_on_association(assoc).klass
52
+
53
+ send("#{assoc}=", klass.new)
54
+ end
55
+ end
56
+ end
57
+ end
58
+
59
+ # Now, define the getters for the specific attribute.
60
+ define_method(underscore ? "_#{attr}" : attr) do
61
+ send(assoc).try(attr)
62
+ end
63
+
64
+ # Now, define the setters for the specific attribute.
65
+ define_method(underscore ? "_#{attr}=" : "#{attr}=") do |new_attr|
66
+ send(assoc).send("#{attr}=", new_attr)
67
+ end
68
+
69
+ # Add the association name to the set of external field associations.
70
+ # This allows other parts of the codebase to quickly see all of the
71
+ # associations a class has that store external fields. This array stores
72
+ # association name symbols, like: [:address, :extra_data]
73
+ # Note that a Set could be used here but an Array was chosen for
74
+ # familiarity since the size of the array will be relatively small.
75
+ unless self._external_field_associations.include? assoc
76
+ # We need to duplicate the array because a subclass of a model with
77
+ # this mixin would otherwise modify its parent class' array, since the
78
+ # << operator works in-place.
79
+ self._external_field_associations =
80
+ self._external_field_associations.dup
81
+
82
+ self._external_field_associations << assoc
83
+ end
84
+ end
85
+ end
86
+ end
87
+ end
@@ -0,0 +1,90 @@
1
+ require "spec_helper"
2
+
3
+ RSpec.describe ExternalFields do
4
+ describe ".external_fields" do
5
+ describe "the association" do
6
+ Temping.create :test_class do
7
+ with_columns do |t|
8
+ t.string :name
9
+ end
10
+
11
+ include ExternalFields
12
+
13
+ has_one :assoc,
14
+ class_name: "AssociationTestClass"
15
+
16
+ external_field :ext_field_1,
17
+ :assoc,
18
+ class_name: "AssociationTestClass"
19
+
20
+ external_field :ext_field_2,
21
+ :assoc,
22
+ class_name: "AssociationTestClass",
23
+ underscore: true
24
+ end
25
+
26
+ Temping.create :association_test_class do
27
+ with_columns do |t|
28
+ t.integer :test_class_id
29
+ t.string :ext_field_1
30
+ t.string :ext_field_2
31
+ end
32
+
33
+ belongs_to :test_class
34
+ end
35
+
36
+ # Clean up after each test. This is a lot lighter for these few tests than
37
+ # trying to wrangle with RSpec-Rails to get transactional tests to work.
38
+ after :each do
39
+ TestClass.delete_all
40
+ AssociationTestClass.delete_all
41
+ end
42
+
43
+ it "should be built on first access" do
44
+ e = TestClass.create!(name: "Hello")
45
+
46
+ expect(AssociationTestClass.count).to eq(0)
47
+ expect(e.assoc.class).to eq(AssociationTestClass)
48
+ end
49
+
50
+ it "should be saved when the model is saved" do
51
+ e = TestClass.create!(name: "Hello")
52
+ expect(AssociationTestClass.count).to eq(0)
53
+ expect(e.assoc.class).to eq(AssociationTestClass)
54
+ e.save!
55
+ expect(AssociationTestClass.count).to eq(1)
56
+ end
57
+
58
+ it "should not be created or saved if unused" do
59
+ e = TestClass.create!
60
+ e.name = "TEST"
61
+ e.save!
62
+ expect(AssociationTestClass.count).to eq(0)
63
+ end
64
+
65
+ it "should be created if used" do
66
+ e = TestClass.create!(name: "Hello", ext_field_1: "Field1")
67
+
68
+ expect(AssociationTestClass.count).to eq(1)
69
+ expect(e.ext_field_1).to eq "Field1"
70
+ end
71
+
72
+ context "when underscore flag is true" do
73
+ it "should provide underscored methods" do
74
+ e = TestClass.create!(_ext_field_2: "_Field2")
75
+
76
+ expect(AssociationTestClass.count).to eq(1)
77
+ expect(e._ext_field_2).to eq "_Field2"
78
+ end
79
+ end
80
+
81
+ it "should provide an accessor that does not build a new object" do
82
+ e = TestClass.new(name: "Hello")
83
+
84
+ e.assoc(use_original: true) # Access without creating
85
+ e.save!
86
+ expect(AssociationTestClass.count).to eq 0
87
+ end
88
+ end
89
+ end
90
+ end
@@ -0,0 +1,48 @@
1
+ require "codeclimate-test-reporter"
2
+ CodeClimate::TestReporter.start
3
+
4
+ # Connect to an in-memory database for ActiveRecord tests.
5
+ require "temping"
6
+ ActiveRecord::Base.
7
+ establish_connection(adapter: "sqlite3", database: ":memory:")
8
+
9
+ require "external_fields"
10
+
11
+ RSpec.configure do |config|
12
+ # These two settings work together to allow you to limit a spec run
13
+ # to individual examples or groups you care about by tagging them with
14
+ # `:focus` metadata. When nothing is tagged with `:focus`, all examples
15
+ # get run.
16
+ config.filter_run :focus
17
+ config.run_all_when_everything_filtered = true
18
+
19
+ # Limits the available syntax to the non-monkey patched syntax that is
20
+ # recommended.
21
+ # For more details, see:
22
+ # - http://myronmars.to/n/dev-blog/2012/06/rspecs-new-expectation-syntax
23
+ # - http://teaisaweso.me/blog/2013/05/27/rspecs-new-message-expectation-syntax/
24
+ # - http://myronmars.to/n/dev-blog/2014/05/notable-changes-in-rspec-3#new__config_option_to_disable_rspeccore_monkey_patching
25
+ config.disable_monkey_patching!
26
+
27
+ # Many RSpec users commonly either run the entire suite or an individual
28
+ # file, and it's useful to allow more verbose output when running an
29
+ # individual spec file.
30
+ if config.files_to_run.one?
31
+ # Use the documentation formatter for detailed output,
32
+ # unless a formatter has already been configured
33
+ # (e.g. via a command-line flag).
34
+ config.default_formatter = "doc"
35
+ end
36
+
37
+ # Run specs in random order to surface order dependencies. If you find an
38
+ # order dependency and want to debug it, you can fix the order by providing
39
+ # the seed, which is printed after each run.
40
+ # --seed 1234
41
+ config.order = :random
42
+
43
+ # Seed global randomization in this process using the `--seed` CLI option.
44
+ # Setting this allows you to use `--seed` to deterministically reproduce
45
+ # test failures related to randomization by passing the same `--seed` value
46
+ # as the one that triggered the failure.
47
+ Kernel.srand config.seed
48
+ end
metadata ADDED
@@ -0,0 +1,202 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: external_fields
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Sagar Jauhari
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2015-09-18 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: activerecord
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '4.0'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '4.0'
27
+ - !ruby/object:Gem::Dependency
28
+ name: bundler
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '1.7'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '1.7'
41
+ - !ruby/object:Gem::Dependency
42
+ name: codeclimate-test-reporter
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: '0.4'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: '0.4'
55
+ - !ruby/object:Gem::Dependency
56
+ name: overcommit
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - "~>"
60
+ - !ruby/object:Gem::Version
61
+ version: '0.23'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - "~>"
67
+ - !ruby/object:Gem::Version
68
+ version: '0.23'
69
+ - !ruby/object:Gem::Dependency
70
+ name: rspec
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - "~>"
74
+ - !ruby/object:Gem::Version
75
+ version: '3.2'
76
+ type: :development
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - "~>"
81
+ - !ruby/object:Gem::Version
82
+ version: '3.2'
83
+ - !ruby/object:Gem::Dependency
84
+ name: rspec-rails
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - "~>"
88
+ - !ruby/object:Gem::Version
89
+ version: '3.2'
90
+ type: :development
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - "~>"
95
+ - !ruby/object:Gem::Version
96
+ version: '3.2'
97
+ - !ruby/object:Gem::Dependency
98
+ name: rubocop
99
+ requirement: !ruby/object:Gem::Requirement
100
+ requirements:
101
+ - - "~>"
102
+ - !ruby/object:Gem::Version
103
+ version: '0.29'
104
+ type: :development
105
+ prerelease: false
106
+ version_requirements: !ruby/object:Gem::Requirement
107
+ requirements:
108
+ - - "~>"
109
+ - !ruby/object:Gem::Version
110
+ version: '0.29'
111
+ - !ruby/object:Gem::Dependency
112
+ name: rubocop-rspec-focused
113
+ requirement: !ruby/object:Gem::Requirement
114
+ requirements:
115
+ - - "~>"
116
+ - !ruby/object:Gem::Version
117
+ version: '0.0'
118
+ type: :development
119
+ prerelease: false
120
+ version_requirements: !ruby/object:Gem::Requirement
121
+ requirements:
122
+ - - "~>"
123
+ - !ruby/object:Gem::Version
124
+ version: '0.0'
125
+ - !ruby/object:Gem::Dependency
126
+ name: temping
127
+ requirement: !ruby/object:Gem::Requirement
128
+ requirements:
129
+ - - "~>"
130
+ - !ruby/object:Gem::Version
131
+ version: '3.2'
132
+ type: :development
133
+ prerelease: false
134
+ version_requirements: !ruby/object:Gem::Requirement
135
+ requirements:
136
+ - - "~>"
137
+ - !ruby/object:Gem::Version
138
+ version: '3.2'
139
+ - !ruby/object:Gem::Dependency
140
+ name: sqlite3
141
+ requirement: !ruby/object:Gem::Requirement
142
+ requirements:
143
+ - - "~>"
144
+ - !ruby/object:Gem::Version
145
+ version: '1.3'
146
+ type: :development
147
+ prerelease: false
148
+ version_requirements: !ruby/object:Gem::Requirement
149
+ requirements:
150
+ - - "~>"
151
+ - !ruby/object:Gem::Version
152
+ version: '1.3'
153
+ description: This concern maintains the illusion that a given object has specified
154
+ attributes, when those attributes are in fact attached to an associated object.
155
+ This is particularly useful for different classes within a single-table inheritance
156
+ table to have access to separate fields in class-specific associations.
157
+ email:
158
+ - sagarjauhari@gmail.com
159
+ executables: []
160
+ extensions: []
161
+ extra_rdoc_files: []
162
+ files:
163
+ - ".gitignore"
164
+ - ".overcommit.yml"
165
+ - ".rubocop.yml"
166
+ - ".travis.yml"
167
+ - Gemfile
168
+ - LICENSE
169
+ - README.md
170
+ - external_fields.gemspec
171
+ - lib/external_fields.rb
172
+ - lib/external_fields/version.rb
173
+ - spec/external_fields_spec.rb
174
+ - spec/spec_helper.rb
175
+ homepage: https://github.com/panorama-ed/rails-external-fields
176
+ licenses:
177
+ - MIT
178
+ metadata: {}
179
+ post_install_message:
180
+ rdoc_options: []
181
+ require_paths:
182
+ - lib
183
+ required_ruby_version: !ruby/object:Gem::Requirement
184
+ requirements:
185
+ - - ">="
186
+ - !ruby/object:Gem::Version
187
+ version: '0'
188
+ required_rubygems_version: !ruby/object:Gem::Requirement
189
+ requirements:
190
+ - - ">="
191
+ - !ruby/object:Gem::Version
192
+ version: '0'
193
+ requirements: []
194
+ rubyforge_project:
195
+ rubygems_version: 2.4.8
196
+ signing_key:
197
+ specification_version: 4
198
+ summary: Access attributes from an associated model.
199
+ test_files:
200
+ - spec/external_fields_spec.rb
201
+ - spec/spec_helper.rb
202
+ has_rdoc: