remote_association 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.
- data/.gitignore +2 -0
- data/.rvmrc +48 -0
- data/Gemfile +6 -0
- data/Gemfile.lock +61 -0
- data/LICENSE +22 -0
- data/README.md +48 -0
- data/Rakefile +7 -0
- data/lib/remote_association/active_record/relation.rb +36 -0
- data/lib/remote_association/version.rb +3 -0
- data/lib/remote_association.rb +120 -0
- data/remote_association.gemspec +29 -0
- data/spec/config/database.example.yml +5 -0
- data/spec/remote_association/remote_association_spec.rb +97 -0
- data/spec/spec_helper.rb +38 -0
- data/spec/tasks/db_setup.rake +57 -0
- metadata +176 -0
data/.gitignore
ADDED
data/.rvmrc
ADDED
@@ -0,0 +1,48 @@
|
|
1
|
+
#!/usr/bin/env bash
|
2
|
+
|
3
|
+
# This is an RVM Project .rvmrc file, used to automatically load the ruby
|
4
|
+
# development environment upon cd'ing into the directory
|
5
|
+
|
6
|
+
# First we specify our desired <ruby>[@<gemset>], the @gemset name is optional,
|
7
|
+
# Only full ruby name is supported here, for short names use:
|
8
|
+
# echo "rvm use 1.9.3" > .rvmrc
|
9
|
+
environment_id="ruby-1.9.3-p194@remote_association"
|
10
|
+
|
11
|
+
# Uncomment the following lines if you want to verify rvm version per project
|
12
|
+
# rvmrc_rvm_version="1.14.3 (stable)" # 1.10.1 seams as a safe start
|
13
|
+
# eval "$(echo ${rvm_version}.${rvmrc_rvm_version} | awk -F. '{print "[[ "$1*65536+$2*256+$3" -ge "$4*65536+$5*256+$6" ]]"}' )" || {
|
14
|
+
# echo "This .rvmrc file requires at least RVM ${rvmrc_rvm_version}, aborting loading."
|
15
|
+
# return 1
|
16
|
+
# }
|
17
|
+
|
18
|
+
# First we attempt to load the desired environment directly from the environment
|
19
|
+
# file. This is very fast and efficient compared to running through the entire
|
20
|
+
# CLI and selector. If you want feedback on which environment was used then
|
21
|
+
# insert the word 'use' after --create as this triggers verbose mode.
|
22
|
+
if [[ -d "${rvm_path:-$HOME/.rvm}/environments"
|
23
|
+
&& -s "${rvm_path:-$HOME/.rvm}/environments/$environment_id" ]]
|
24
|
+
then
|
25
|
+
\. "${rvm_path:-$HOME/.rvm}/environments/$environment_id"
|
26
|
+
[[ -s "${rvm_path:-$HOME/.rvm}/hooks/after_use" ]] &&
|
27
|
+
\. "${rvm_path:-$HOME/.rvm}/hooks/after_use" || true
|
28
|
+
else
|
29
|
+
# If the environment file has not yet been created, use the RVM CLI to select.
|
30
|
+
rvm --create "$environment_id" || {
|
31
|
+
echo "Failed to create RVM environment '${environment_id}'."
|
32
|
+
return 1
|
33
|
+
}
|
34
|
+
fi
|
35
|
+
|
36
|
+
# If you use bundler, this might be useful to you:
|
37
|
+
# if [[ -s Gemfile ]] && {
|
38
|
+
# ! builtin command -v bundle >/dev/null ||
|
39
|
+
# builtin command -v bundle | GREP_OPTIONS= \grep $rvm_path/bin/bundle >/dev/null
|
40
|
+
# }
|
41
|
+
# then
|
42
|
+
# printf "%b" "The rubygem 'bundler' is not installed. Installing it now.\n"
|
43
|
+
# gem install bundler
|
44
|
+
# fi
|
45
|
+
# if [[ -s Gemfile ]] && builtin command -v bundle >/dev/null
|
46
|
+
# then
|
47
|
+
# bundle install | GREP_OPTIONS= \grep -vE '^Using|Your bundle is complete'
|
48
|
+
# fi
|
data/Gemfile
ADDED
data/Gemfile.lock
ADDED
@@ -0,0 +1,61 @@
|
|
1
|
+
PATH
|
2
|
+
remote: .
|
3
|
+
specs:
|
4
|
+
remote_association (0.0.1)
|
5
|
+
activerecord (~> 3.2)
|
6
|
+
activeresource (~> 3.2)
|
7
|
+
activesupport (~> 3.2)
|
8
|
+
|
9
|
+
GEM
|
10
|
+
remote: https://rubygems.org/
|
11
|
+
specs:
|
12
|
+
activemodel (3.2.8)
|
13
|
+
activesupport (= 3.2.8)
|
14
|
+
builder (~> 3.0.0)
|
15
|
+
activerecord (3.2.8)
|
16
|
+
activemodel (= 3.2.8)
|
17
|
+
activesupport (= 3.2.8)
|
18
|
+
arel (~> 3.0.2)
|
19
|
+
tzinfo (~> 0.3.29)
|
20
|
+
activeresource (3.2.8)
|
21
|
+
activemodel (= 3.2.8)
|
22
|
+
activesupport (= 3.2.8)
|
23
|
+
activesupport (3.2.8)
|
24
|
+
i18n (~> 0.6)
|
25
|
+
multi_json (~> 1.0)
|
26
|
+
arel (3.0.2)
|
27
|
+
builder (3.0.0)
|
28
|
+
columnize (0.3.6)
|
29
|
+
database_cleaner (0.8.0)
|
30
|
+
debugger (1.2.0)
|
31
|
+
columnize (>= 0.3.1)
|
32
|
+
debugger-linecache (~> 1.1.1)
|
33
|
+
debugger-ruby_core_source (~> 1.1.3)
|
34
|
+
debugger-linecache (1.1.2)
|
35
|
+
debugger-ruby_core_source (>= 1.1.1)
|
36
|
+
debugger-ruby_core_source (1.1.3)
|
37
|
+
diff-lcs (1.1.3)
|
38
|
+
fakeweb (1.3.0)
|
39
|
+
i18n (0.6.0)
|
40
|
+
multi_json (1.3.6)
|
41
|
+
pg (0.14.0)
|
42
|
+
rspec (2.11.0)
|
43
|
+
rspec-core (~> 2.11.0)
|
44
|
+
rspec-expectations (~> 2.11.0)
|
45
|
+
rspec-mocks (~> 2.11.0)
|
46
|
+
rspec-core (2.11.1)
|
47
|
+
rspec-expectations (2.11.2)
|
48
|
+
diff-lcs (~> 1.1.3)
|
49
|
+
rspec-mocks (2.11.2)
|
50
|
+
tzinfo (0.3.33)
|
51
|
+
|
52
|
+
PLATFORMS
|
53
|
+
ruby
|
54
|
+
|
55
|
+
DEPENDENCIES
|
56
|
+
database_cleaner (~> 0.8)
|
57
|
+
debugger
|
58
|
+
fakeweb
|
59
|
+
pg (~> 0.14)
|
60
|
+
remote_association!
|
61
|
+
rspec (~> 2.11)
|
data/LICENSE
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
Copyright (c) 2012 Denis Yagofarov
|
2
|
+
|
3
|
+
MIT License
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
6
|
+
a copy of this software and associated documentation files (the
|
7
|
+
"Software"), to deal in the Software without restriction, including
|
8
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
9
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
10
|
+
permit persons to whom the Software is furnished to do so, subject to
|
11
|
+
the following conditions:
|
12
|
+
|
13
|
+
The above copyright notice and this permission notice shall be
|
14
|
+
included in all copies or substantial portions of the Software.
|
15
|
+
|
16
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
17
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
18
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
19
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
20
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
21
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
22
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,48 @@
|
|
1
|
+
# Remote Association
|
2
|
+
|
3
|
+
Add ```has_``` and ```belongs_``` associations to models inherited from ActiveResource::Base
|
4
|
+
|
5
|
+
Say, you have Author and a service with Profiles. You can access profile of author as easy as `author.profile`.
|
6
|
+
|
7
|
+
Also, if you have 10K profiles and you need 3 of them, it won't load all profiles and won't do 3 requests to API.
|
8
|
+
Instead, just use ```Author.scoped.includes_remote(:profile)``` and it will do a get request like this one:
|
9
|
+
|
10
|
+
```GET http://example.com/profiles?author_id[]=1&author_id[]=2&author_id[]=3```
|
11
|
+
|
12
|
+
Don't want to use default ```author_id```? You can alter class of ```profile``` association and ```author_id``` key by options.
|
13
|
+
Just like in ActiveRecord.
|
14
|
+
|
15
|
+
Notice, that for now, associations work in read-only mode.
|
16
|
+
|
17
|
+
## Example
|
18
|
+
|
19
|
+
```ruby
|
20
|
+
class Profile < ActiveResource::Base
|
21
|
+
self.site = REMOTE_HOST
|
22
|
+
end
|
23
|
+
class User < ActiveRecord::Base
|
24
|
+
include RemoteAssociation::Base
|
25
|
+
has_one_remote :profile
|
26
|
+
end
|
27
|
+
|
28
|
+
User.first.profile
|
29
|
+
|
30
|
+
```
|
31
|
+
|
32
|
+
## Installation
|
33
|
+
|
34
|
+
Add this line to your application's Gemfile:
|
35
|
+
|
36
|
+
gem 'remote_association'
|
37
|
+
|
38
|
+
## TODO
|
39
|
+
|
40
|
+
Implement 'has_many_remote' analogie of 'AR.has_many'
|
41
|
+
|
42
|
+
## Contributing
|
43
|
+
|
44
|
+
1. Fork it
|
45
|
+
2. Create your feature branch (`git checkout -b my-new-feature`)
|
46
|
+
3. Commit your changes (`git commit -am 'Added some feature'`)
|
47
|
+
4. Push to the branch (`git push origin my-new-feature`)
|
48
|
+
5. Create new Pull Request
|
data/Rakefile
ADDED
@@ -0,0 +1,36 @@
|
|
1
|
+
module ActiveRecord
|
2
|
+
class Relation
|
3
|
+
# Loads relations to ActiveModel models of models, selected by current relation.
|
4
|
+
# The analogy is <tt>includes(*args)</tt> of ActiveRecord.
|
5
|
+
#
|
6
|
+
# May raise <tt>RemoteAssociation::SettingsNotFoundError</tt> if one of args can't be found among
|
7
|
+
# Class.activeresource_relations settings
|
8
|
+
#
|
9
|
+
# Returns all the records matched by the options of the relation, same as <tt>all(*args)</tt>
|
10
|
+
#
|
11
|
+
# === Examples
|
12
|
+
#
|
13
|
+
# Author.scoped.includes_remote(:profile, :avatar)
|
14
|
+
def includes_remote(*args)
|
15
|
+
keys = self.uniq.pluck(:id)
|
16
|
+
|
17
|
+
args.each do |r|
|
18
|
+
settings = klass.activeresource_relations[r.to_sym]
|
19
|
+
raise RemoteAssociation::SettingsNotFoundError, "Can't find settings for #{r} association" if settings.blank?
|
20
|
+
|
21
|
+
ar_accessor = r.to_sym
|
22
|
+
foregin_key = settings[:foreign_key]
|
23
|
+
ar_class = settings[:class_name ].constantize
|
24
|
+
|
25
|
+
remote_objects = ar_class.find(:all, :params => { foregin_key => keys })
|
26
|
+
|
27
|
+
self.each do |u|
|
28
|
+
u.send("#{ar_accessor}=", remote_objects.select {|s| s.send(foregin_key) == u.id })
|
29
|
+
u.instance_variable_set(:@remote_resources_prefetched, true)
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
self.all
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
@@ -0,0 +1,120 @@
|
|
1
|
+
require "active_record"
|
2
|
+
require "active_support"
|
3
|
+
|
4
|
+
require "remote_association/version"
|
5
|
+
require "remote_association/active_record/relation"
|
6
|
+
|
7
|
+
module RemoteAssociation
|
8
|
+
# Include this class to hav associations to ActiveResource models
|
9
|
+
#
|
10
|
+
# It will add methods to your class:
|
11
|
+
# * <tt>has_one_remote(name, *oprions)</tt>
|
12
|
+
# * <tt>activeresource_relations</tt>
|
13
|
+
# * <tt>add_activeresource_relation(name, options)</tt>
|
14
|
+
module Base
|
15
|
+
def self.included(base)
|
16
|
+
base.extend ClassMethods
|
17
|
+
base.send :include, InstanceMethods
|
18
|
+
|
19
|
+
base.class_eval do
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
module ClassMethods
|
24
|
+
# Specifies a one-to-one association with another class. This method should only be used
|
25
|
+
# if this class is a kind of ActiveResource::Base and service for this resource can
|
26
|
+
# return some kind of foreign key.
|
27
|
+
#
|
28
|
+
# Methods will be added for retrieval and query for a single associated object, for which
|
29
|
+
# this object holds an id:
|
30
|
+
#
|
31
|
+
# [association()]
|
32
|
+
# Returns the associated object. +nil+ is returned if none is found.
|
33
|
+
# [association=(associate)]
|
34
|
+
# Just setter, no saves.
|
35
|
+
#
|
36
|
+
# (+association+ is replaced with the symbol passed as the first argument, so
|
37
|
+
# <tt>has_one_remote :author</tt> would add among others <tt>author.nil?</tt>.)
|
38
|
+
#
|
39
|
+
# === Example
|
40
|
+
#
|
41
|
+
# A Author class declares <tt>has_one_remote :profile</tt>, which will add:
|
42
|
+
# * <tt>Authort#profile</tt> (similar to <tt>Profile.find(:first, params: { author_id: [author.id]})</tt>)
|
43
|
+
# * <tt>Author#profile=(profile)</tt> (will set @profile instance variable of Author# to profile value)
|
44
|
+
# The declaration can also include an options hash to specialize the behavior of the association.
|
45
|
+
#
|
46
|
+
# === Options
|
47
|
+
#
|
48
|
+
# [:class_name]
|
49
|
+
# Specify the class name of the association. Use it only if that name can't be inferred
|
50
|
+
# from the association name. So <tt>has_one_remote :profile</tt> will by default be linked to the Profile class, but
|
51
|
+
# if the real class name is SocialProfile, you'll have to specify it with this option.
|
52
|
+
# [:foreign_key]
|
53
|
+
# Specify the foreign key used for searching association on remote service. By default this is guessed to be the name
|
54
|
+
# of the current class with an "_id" suffix. So a class Author that defines a <tt>has_one_remote :profile</tt>
|
55
|
+
# association will use "author_id" as the default <tt>:foreign_key</tt>.
|
56
|
+
# This key will be used in :get request. Example: <tt>GET http://example.com/profiles?author_id[]=1</tt>
|
57
|
+
#
|
58
|
+
# Option examples:
|
59
|
+
# has_one_remote :firm, :foreign_key => "client_of"
|
60
|
+
# has_one_remote :author, :class_name => "Person", :foreign_key => "author_id"
|
61
|
+
def has_one_remote(remote_rel, options ={})
|
62
|
+
rel_options = {
|
63
|
+
class_name: remote_rel.to_s.classify,
|
64
|
+
foreign_key: self.model_name.to_s.foreign_key
|
65
|
+
}.merge(options.symbolize_keys)
|
66
|
+
|
67
|
+
add_activeresource_relation(remote_rel.to_sym, rel_options)
|
68
|
+
|
69
|
+
class_eval <<-RUBY, __FILE__, __LINE__+1
|
70
|
+
|
71
|
+
attr_accessor :#{remote_rel}
|
72
|
+
|
73
|
+
def #{remote_rel}
|
74
|
+
if remote_resources_prefetched?
|
75
|
+
@#{remote_rel} ? @#{remote_rel}.first : nil
|
76
|
+
else
|
77
|
+
@#{remote_rel} ||= #{rel_options[:class_name]}.find(:first, params: { #{rel_options[:foreign_key]}: [self.id]})
|
78
|
+
end
|
79
|
+
end
|
80
|
+
|
81
|
+
RUBY
|
82
|
+
|
83
|
+
end
|
84
|
+
|
85
|
+
# Adds settings of relation to ActiveResource model.
|
86
|
+
#
|
87
|
+
# === Parameters
|
88
|
+
# * <tt>name</tt> a Symbol, representing name of association
|
89
|
+
# * <tt>options</tt> a Hash, contains :class_name and :foreign_key settings
|
90
|
+
#
|
91
|
+
# === Examples
|
92
|
+
#
|
93
|
+
# Author.add_activeresource_relation(:profile, {class_name: "Profile", foreign_key: "author_id"})
|
94
|
+
def add_activeresource_relation(name, options)
|
95
|
+
existing_relations = activeresource_relations
|
96
|
+
existing_relations[name] = options
|
97
|
+
@activeresource_relations = existing_relations
|
98
|
+
end
|
99
|
+
|
100
|
+
# Returns settings for relations to ActiveResource models.
|
101
|
+
#
|
102
|
+
# === Examples
|
103
|
+
#
|
104
|
+
# Author.activeresource_relations #=> [{profile: {class_name: "Profile", foreign_key: "author_id"}}]
|
105
|
+
def activeresource_relations
|
106
|
+
@activeresource_relations ||= {}
|
107
|
+
end
|
108
|
+
end
|
109
|
+
|
110
|
+
module InstanceMethods
|
111
|
+
|
112
|
+
# Returns <tt>true</tt> if associations to remote relations already loaded and set
|
113
|
+
def remote_resources_prefetched?
|
114
|
+
@remote_resources_prefetched
|
115
|
+
end
|
116
|
+
end
|
117
|
+
end
|
118
|
+
|
119
|
+
class SettingsNotFoundError < StandardError; end
|
120
|
+
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
require File.expand_path('../lib/remote_association/version', __FILE__)
|
3
|
+
|
4
|
+
Gem::Specification.new do |gem|
|
5
|
+
gem.authors = ["Denis Yagofarov"]
|
6
|
+
gem.email = ["denyago@gmail.com"]
|
7
|
+
gem.description = %q{Your model has_one_remote ActiveResource instance}
|
8
|
+
gem.summary = %q{Adds relations to ActiveResource models}
|
9
|
+
gem.homepage = "https://github.com/denyago/remote_association"
|
10
|
+
|
11
|
+
gem.files = `git ls-files`.split($\)
|
12
|
+
gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
|
13
|
+
gem.test_files = gem.files.grep(%r{^(spec)/})
|
14
|
+
gem.name = "remote_association"
|
15
|
+
gem.require_paths = ["lib"]
|
16
|
+
gem.version = RemoteAssociation::VERSION
|
17
|
+
|
18
|
+
rails_version = "~> 3.2"
|
19
|
+
|
20
|
+
gem.add_dependency 'activesupport', rails_version
|
21
|
+
gem.add_dependency 'activerecord', rails_version
|
22
|
+
gem.add_dependency 'activeresource', rails_version
|
23
|
+
|
24
|
+
gem.add_development_dependency 'rspec', '~> 2.11'
|
25
|
+
gem.add_development_dependency 'pg', '~> 0.14'
|
26
|
+
gem.add_development_dependency 'database_cleaner', '~> 0.8'
|
27
|
+
gem.add_development_dependency 'fakeweb'
|
28
|
+
|
29
|
+
end
|
@@ -0,0 +1,97 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe RemoteAssociation do
|
4
|
+
before(:all) do
|
5
|
+
REMOTE_HOST = "http://127.0.0.1:3000"
|
6
|
+
PROFILES_JSON = [
|
7
|
+
{profile: {id: 1, user_id: 1, like: "letter A"}},
|
8
|
+
{profile: {id: 2, user_id: 2, like: "letter B"}}
|
9
|
+
]
|
10
|
+
end
|
11
|
+
|
12
|
+
before(:each) do
|
13
|
+
class Profile < ActiveResource::Base
|
14
|
+
self.site = REMOTE_HOST
|
15
|
+
end
|
16
|
+
class User < ActiveRecord::Base
|
17
|
+
include RemoteAssociation::Base
|
18
|
+
has_one_remote :profile
|
19
|
+
end
|
20
|
+
|
21
|
+
add_user(1,"User A")
|
22
|
+
add_user(2,"User B")
|
23
|
+
end
|
24
|
+
|
25
|
+
it 'should prefetch remote associations of models with defaults (single request)' do
|
26
|
+
FakeWeb.register_uri(:get, "#{REMOTE_HOST}/profiles.json?user_id%5B%5D=1&user_id%5B%5D=2", body: PROFILES_JSON.to_json)
|
27
|
+
|
28
|
+
users = User.scoped.includes_remote(:profile)
|
29
|
+
users.first.profile.like.should eq('letter A')
|
30
|
+
users.last.profile.like.should eq('letter B')
|
31
|
+
end
|
32
|
+
|
33
|
+
it 'should raise error if can\'t find settings for included remote' do
|
34
|
+
lambda{ User.scoped.includes_remote(:whatever) }.should raise_error(RemoteAssociation::SettingsNotFoundError, "Can't find settings for whatever association")
|
35
|
+
end
|
36
|
+
|
37
|
+
it 'should prefetch remote associations of models, passed as args of includes_remote' do
|
38
|
+
class OtherProfile < ActiveResource::Base
|
39
|
+
self.site = REMOTE_HOST
|
40
|
+
self.element_name = "profile"
|
41
|
+
end
|
42
|
+
class User < ActiveRecord::Base
|
43
|
+
include RemoteAssociation::Base
|
44
|
+
has_one_remote :profile
|
45
|
+
has_one_remote :other_profile
|
46
|
+
end
|
47
|
+
|
48
|
+
FakeWeb.register_uri(:get, "#{REMOTE_HOST}/other_profiles.json?user_id%5B%5D=1&user_id%5B%5D=2", body: PROFILES_JSON.to_json)
|
49
|
+
FakeWeb.register_uri(:get, "#{REMOTE_HOST}/profiles.json?user_id%5B%5D=1&user_id%5B%5D=2", body: PROFILES_JSON.to_json)
|
50
|
+
|
51
|
+
users = User.scoped.includes_remote(:profile, :other_profile)
|
52
|
+
users.first.profile.like.should eq('letter A')
|
53
|
+
users.last.profile.like.should eq('letter B')
|
54
|
+
users.first.other_profile.like.should eq('letter A')
|
55
|
+
users.last.other_profile.like.should eq('letter B')
|
56
|
+
end
|
57
|
+
|
58
|
+
it 'should autoload remote associations of each models without prefetching (1+N requiests)' do
|
59
|
+
FakeWeb.register_uri(:get, "#{REMOTE_HOST}/profiles.json?user_id%5B%5D=1", body: [PROFILES_JSON.first].to_json)
|
60
|
+
FakeWeb.register_uri(:get, "#{REMOTE_HOST}/profiles.json?user_id%5B%5D=2", body: [PROFILES_JSON.last].to_json)
|
61
|
+
|
62
|
+
users = User.scoped
|
63
|
+
users.first.profile.like.should eq('letter A')
|
64
|
+
users.last.profile.like.should eq('letter B')
|
65
|
+
end
|
66
|
+
|
67
|
+
describe "method :has_one_remote with options:" do
|
68
|
+
before(:each) do
|
69
|
+
@body = [PROFILES_JSON.first].to_json
|
70
|
+
end
|
71
|
+
it ":class_name - able to choose custom class of association" do
|
72
|
+
class CustomProfile < ActiveResource::Base
|
73
|
+
self.site = REMOTE_HOST
|
74
|
+
self.element_name = "profile"
|
75
|
+
end
|
76
|
+
class User < ActiveRecord::Base
|
77
|
+
include RemoteAssociation::Base
|
78
|
+
has_one_remote :profile, class_name: "CustomProfile"
|
79
|
+
end
|
80
|
+
FakeWeb.register_uri(:get, "#{REMOTE_HOST}/profiles.json?user_id%5B%5D=1", body: @body )
|
81
|
+
end
|
82
|
+
it ":foreign_key - can set uri param for search" do
|
83
|
+
class CustomProfile < ActiveResource::Base
|
84
|
+
self.site = REMOTE_HOST
|
85
|
+
self.element_name = "profile"
|
86
|
+
end
|
87
|
+
class User < ActiveRecord::Base
|
88
|
+
include RemoteAssociation::Base
|
89
|
+
has_one_remote :profile, foreign_key: :login_id
|
90
|
+
end
|
91
|
+
FakeWeb.register_uri(:get, "#{REMOTE_HOST}/profiles.json?login_id%5B%5D=1", body: @body)
|
92
|
+
end
|
93
|
+
after(:each) do
|
94
|
+
User.first.profile.like.should eq('letter A')
|
95
|
+
end
|
96
|
+
end
|
97
|
+
end
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,38 @@
|
|
1
|
+
require 'rspec'
|
2
|
+
require "database_cleaner"
|
3
|
+
require 'fake_web'
|
4
|
+
|
5
|
+
require 'remote_association'
|
6
|
+
|
7
|
+
require 'yaml'
|
8
|
+
require 'active_resource'
|
9
|
+
|
10
|
+
RSpec.configure do |config|
|
11
|
+
config.color_enabled = true
|
12
|
+
|
13
|
+
config.before(:suite) do
|
14
|
+
DatabaseCleaner.strategy = :transaction
|
15
|
+
FakeWeb.allow_net_connect = false
|
16
|
+
end
|
17
|
+
|
18
|
+
config.after(:suite) do
|
19
|
+
DatabaseCleaner.strategy = :truncation
|
20
|
+
DatabaseCleaner.clean
|
21
|
+
end
|
22
|
+
|
23
|
+
config.before(:each) do
|
24
|
+
DatabaseCleaner.start
|
25
|
+
end
|
26
|
+
|
27
|
+
config.after(:each) do
|
28
|
+
DatabaseCleaner.clean
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
root = File.dirname(__FILE__)
|
33
|
+
db_config = YAML.load_file("#{root}/config/database.yml")
|
34
|
+
ActiveRecord::Base.establish_connection(db_config)
|
35
|
+
|
36
|
+
def add_user(id, name)
|
37
|
+
ActiveRecord::Base.connection.execute("insert into \"public\".\"users\" (\"id\", \"name\") values ( #{id}, '#{name}');")
|
38
|
+
end
|
@@ -0,0 +1,57 @@
|
|
1
|
+
require 'active_record'
|
2
|
+
|
3
|
+
namespace :spec do
|
4
|
+
namespace :db do
|
5
|
+
desc "Setup DB for tests"
|
6
|
+
task :setup do
|
7
|
+
puts "Create database\n"
|
8
|
+
Rake::Task["spec:db:create"].invoke
|
9
|
+
puts "Migrate database\n"
|
10
|
+
Rake::Task["spec:db:migrate"].invoke
|
11
|
+
end
|
12
|
+
|
13
|
+
desc "Add tables required for tests"
|
14
|
+
task :migrate do
|
15
|
+
ActiveRecord::Base.establish_connection(db_config)
|
16
|
+
|
17
|
+
ActiveRecord::Base.connection.execute(<<SQL
|
18
|
+
DROP TABLE IF EXISTS "public"."users";
|
19
|
+
|
20
|
+
CREATE TABLE "public"."users" (
|
21
|
+
"id" int4 NOT NULL,
|
22
|
+
"name" varchar(255) NOT NULL,
|
23
|
+
CONSTRAINT "users_pkey" PRIMARY KEY ("id") NOT DEFERRABLE INITIALLY IMMEDIATE
|
24
|
+
)
|
25
|
+
WITH (OIDS=FALSE);
|
26
|
+
ALTER TABLE "public"."users" OWNER TO "rails";
|
27
|
+
SQL
|
28
|
+
)
|
29
|
+
end
|
30
|
+
|
31
|
+
desc "Create DB for tests"
|
32
|
+
task :create do
|
33
|
+
encoding = db_config[:encoding] || ENV['CHARSET'] || 'utf8'
|
34
|
+
begin
|
35
|
+
ActiveRecord::Base.establish_connection(db_config.merge('database' => 'postgres', 'schema_search_path' => 'public'))
|
36
|
+
ActiveRecord::Base.connection.drop_database(db_config['database']) and puts "previously dropping DB..." if db_present?
|
37
|
+
ActiveRecord::Base.connection.create_database(db_config['database'], db_config.merge('encoding' => encoding))
|
38
|
+
ActiveRecord::Base.establish_connection(db_config)
|
39
|
+
rescue
|
40
|
+
$stderr.puts $!, *($!.backtrace)
|
41
|
+
$stderr.puts "Couldn't create database for #{db_config.inspect}"
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
def db_config
|
46
|
+
root = File.expand_path('../../', __FILE__)
|
47
|
+
@db_conf ||= YAML.load_file("#{root}/config/database.yml")
|
48
|
+
end
|
49
|
+
|
50
|
+
def db_present?
|
51
|
+
ActiveRecord::Base.connection.execute("SELECT count(*) FROM pg_database where datname = '#{db_config['database']}'").values.flatten.first.to_i == 1
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
|
57
|
+
|
metadata
ADDED
@@ -0,0 +1,176 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: remote_association
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.1
|
5
|
+
prerelease:
|
6
|
+
platform: ruby
|
7
|
+
authors:
|
8
|
+
- Denis Yagofarov
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
date: 2012-08-23 00:00:00.000000000 Z
|
13
|
+
dependencies:
|
14
|
+
- !ruby/object:Gem::Dependency
|
15
|
+
name: activesupport
|
16
|
+
requirement: !ruby/object:Gem::Requirement
|
17
|
+
none: false
|
18
|
+
requirements:
|
19
|
+
- - ~>
|
20
|
+
- !ruby/object:Gem::Version
|
21
|
+
version: '3.2'
|
22
|
+
type: :runtime
|
23
|
+
prerelease: false
|
24
|
+
version_requirements: !ruby/object:Gem::Requirement
|
25
|
+
none: false
|
26
|
+
requirements:
|
27
|
+
- - ~>
|
28
|
+
- !ruby/object:Gem::Version
|
29
|
+
version: '3.2'
|
30
|
+
- !ruby/object:Gem::Dependency
|
31
|
+
name: activerecord
|
32
|
+
requirement: !ruby/object:Gem::Requirement
|
33
|
+
none: false
|
34
|
+
requirements:
|
35
|
+
- - ~>
|
36
|
+
- !ruby/object:Gem::Version
|
37
|
+
version: '3.2'
|
38
|
+
type: :runtime
|
39
|
+
prerelease: false
|
40
|
+
version_requirements: !ruby/object:Gem::Requirement
|
41
|
+
none: false
|
42
|
+
requirements:
|
43
|
+
- - ~>
|
44
|
+
- !ruby/object:Gem::Version
|
45
|
+
version: '3.2'
|
46
|
+
- !ruby/object:Gem::Dependency
|
47
|
+
name: activeresource
|
48
|
+
requirement: !ruby/object:Gem::Requirement
|
49
|
+
none: false
|
50
|
+
requirements:
|
51
|
+
- - ~>
|
52
|
+
- !ruby/object:Gem::Version
|
53
|
+
version: '3.2'
|
54
|
+
type: :runtime
|
55
|
+
prerelease: false
|
56
|
+
version_requirements: !ruby/object:Gem::Requirement
|
57
|
+
none: false
|
58
|
+
requirements:
|
59
|
+
- - ~>
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '3.2'
|
62
|
+
- !ruby/object:Gem::Dependency
|
63
|
+
name: rspec
|
64
|
+
requirement: !ruby/object:Gem::Requirement
|
65
|
+
none: false
|
66
|
+
requirements:
|
67
|
+
- - ~>
|
68
|
+
- !ruby/object:Gem::Version
|
69
|
+
version: '2.11'
|
70
|
+
type: :development
|
71
|
+
prerelease: false
|
72
|
+
version_requirements: !ruby/object:Gem::Requirement
|
73
|
+
none: false
|
74
|
+
requirements:
|
75
|
+
- - ~>
|
76
|
+
- !ruby/object:Gem::Version
|
77
|
+
version: '2.11'
|
78
|
+
- !ruby/object:Gem::Dependency
|
79
|
+
name: pg
|
80
|
+
requirement: !ruby/object:Gem::Requirement
|
81
|
+
none: false
|
82
|
+
requirements:
|
83
|
+
- - ~>
|
84
|
+
- !ruby/object:Gem::Version
|
85
|
+
version: '0.14'
|
86
|
+
type: :development
|
87
|
+
prerelease: false
|
88
|
+
version_requirements: !ruby/object:Gem::Requirement
|
89
|
+
none: false
|
90
|
+
requirements:
|
91
|
+
- - ~>
|
92
|
+
- !ruby/object:Gem::Version
|
93
|
+
version: '0.14'
|
94
|
+
- !ruby/object:Gem::Dependency
|
95
|
+
name: database_cleaner
|
96
|
+
requirement: !ruby/object:Gem::Requirement
|
97
|
+
none: false
|
98
|
+
requirements:
|
99
|
+
- - ~>
|
100
|
+
- !ruby/object:Gem::Version
|
101
|
+
version: '0.8'
|
102
|
+
type: :development
|
103
|
+
prerelease: false
|
104
|
+
version_requirements: !ruby/object:Gem::Requirement
|
105
|
+
none: false
|
106
|
+
requirements:
|
107
|
+
- - ~>
|
108
|
+
- !ruby/object:Gem::Version
|
109
|
+
version: '0.8'
|
110
|
+
- !ruby/object:Gem::Dependency
|
111
|
+
name: fakeweb
|
112
|
+
requirement: !ruby/object:Gem::Requirement
|
113
|
+
none: false
|
114
|
+
requirements:
|
115
|
+
- - ! '>='
|
116
|
+
- !ruby/object:Gem::Version
|
117
|
+
version: '0'
|
118
|
+
type: :development
|
119
|
+
prerelease: false
|
120
|
+
version_requirements: !ruby/object:Gem::Requirement
|
121
|
+
none: false
|
122
|
+
requirements:
|
123
|
+
- - ! '>='
|
124
|
+
- !ruby/object:Gem::Version
|
125
|
+
version: '0'
|
126
|
+
description: Your model has_one_remote ActiveResource instance
|
127
|
+
email:
|
128
|
+
- denyago@gmail.com
|
129
|
+
executables: []
|
130
|
+
extensions: []
|
131
|
+
extra_rdoc_files: []
|
132
|
+
files:
|
133
|
+
- .gitignore
|
134
|
+
- .rvmrc
|
135
|
+
- Gemfile
|
136
|
+
- Gemfile.lock
|
137
|
+
- LICENSE
|
138
|
+
- README.md
|
139
|
+
- Rakefile
|
140
|
+
- lib/remote_association.rb
|
141
|
+
- lib/remote_association/active_record/relation.rb
|
142
|
+
- lib/remote_association/version.rb
|
143
|
+
- remote_association.gemspec
|
144
|
+
- spec/config/database.example.yml
|
145
|
+
- spec/remote_association/remote_association_spec.rb
|
146
|
+
- spec/spec_helper.rb
|
147
|
+
- spec/tasks/db_setup.rake
|
148
|
+
homepage: https://github.com/denyago/remote_association
|
149
|
+
licenses: []
|
150
|
+
post_install_message:
|
151
|
+
rdoc_options: []
|
152
|
+
require_paths:
|
153
|
+
- lib
|
154
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
155
|
+
none: false
|
156
|
+
requirements:
|
157
|
+
- - ! '>='
|
158
|
+
- !ruby/object:Gem::Version
|
159
|
+
version: '0'
|
160
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
161
|
+
none: false
|
162
|
+
requirements:
|
163
|
+
- - ! '>='
|
164
|
+
- !ruby/object:Gem::Version
|
165
|
+
version: '0'
|
166
|
+
requirements: []
|
167
|
+
rubyforge_project:
|
168
|
+
rubygems_version: 1.8.24
|
169
|
+
signing_key:
|
170
|
+
specification_version: 3
|
171
|
+
summary: Adds relations to ActiveResource models
|
172
|
+
test_files:
|
173
|
+
- spec/config/database.example.yml
|
174
|
+
- spec/remote_association/remote_association_spec.rb
|
175
|
+
- spec/spec_helper.rb
|
176
|
+
- spec/tasks/db_setup.rake
|