cylons 0.0.1 → 0.0.2
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 +7 -0
- data/.gitignore +2 -0
- data/.rspec +1 -0
- data/Gemfile +3 -2
- data/Guardfile +39 -0
- data/README.md +93 -39
- data/bin/cylons +11 -12
- data/cylons.gemspec +13 -8
- data/lib/cylons.rb +43 -14
- data/lib/cylons/active_record_extensions.rb +20 -27
- data/lib/cylons/{remote_proxy.rb → agent.rb} +104 -47
- data/lib/cylons/config.rb +26 -0
- data/lib/cylons/connection.rb +11 -15
- data/lib/cylons/errors.rb +2 -1
- data/lib/cylons/local_registry.rb +5 -11
- data/lib/cylons/logging.rb +41 -0
- data/lib/cylons/railtie.rb +4 -25
- data/lib/cylons/registry_adapter.rb +10 -1
- data/lib/cylons/remote.rb +11 -22
- data/lib/cylons/remote_discovery.rb +29 -18
- data/lib/cylons/remote_pagination.rb +32 -0
- data/lib/cylons/remote_registry.rb +12 -15
- data/lib/cylons/remote_schema.rb +2 -2
- data/lib/cylons/rpc.rb +64 -72
- data/lib/cylons/service_manager.rb +30 -20
- data/lib/cylons/version.rb +1 -1
- data/spec/inventory_test_app.rb +24 -0
- data/spec/lib/cylons/connection_spec.rb +15 -0
- data/spec/lib/cylons/interface_spec.rb +7 -0
- data/spec/lib/cylons/remote_registry_spec.rb +57 -0
- data/spec/lib/cylons/service_manager_spec.rb +40 -4
- data/spec/spec_helper.rb +30 -2
- data/spec/support/inventory_test_node.rb +49 -0
- data/spec/support/schema.rb +24 -0
- metadata +181 -150
- data/lib/cylons/configuration.rb +0 -38
- data/spec/lib/cylons/remote_registry.rb +0 -7
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: eb519882f4bf37d3a0b69e51a1d84517965d122f
|
4
|
+
data.tar.gz: a1f350512a94e1ead21987957b9e75e91cb30de5
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: b6a2a8b849ced51a30dd7ba062f72d5f51a6a6a8afde706e2011eef6fe1f4cb23fa3a2c7e73a3400a1a7d4413800832d2df1d9360c27556cf65e9eb857ba2893
|
7
|
+
data.tar.gz: 6ac49e71477cb817fb05ad9396145739d81b9f477c4757628d915e401c77a4a906dc67a49e2bac36800e39031c8ee8483af1bb8d80c893b9a12d7dd245aef4af
|
data/.gitignore
CHANGED
data/.rspec
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
--color
|
data/Gemfile
CHANGED
@@ -1,4 +1,5 @@
|
|
1
1
|
source 'https://rubygems.org'
|
2
|
-
|
3
|
-
|
2
|
+
#dcell needs https://github.com/celluloid/dcell/pull/72 to be merged or fix the alias_method issue
|
3
|
+
gem 'dcell', github: 'jasonayre/dcell', branch: 'master'
|
4
|
+
# gem "dcell", :path => "~/gems/dcell"
|
4
5
|
gemspec
|
data/Guardfile
ADDED
@@ -0,0 +1,39 @@
|
|
1
|
+
# A sample Guardfile
|
2
|
+
# More info at https://github.com/guard/guard#readme
|
3
|
+
|
4
|
+
guard :bundler do
|
5
|
+
watch('Gemfile')
|
6
|
+
# Uncomment next line if your Gemfile contains the `gemspec' command.
|
7
|
+
# watch(/^.+\.gemspec/)
|
8
|
+
end
|
9
|
+
|
10
|
+
# Note: The cmd option is now required due to the increasing number of ways
|
11
|
+
# rspec may be run, below are examples of the most common uses.
|
12
|
+
# * bundler: 'bundle exec rspec'
|
13
|
+
# * bundler binstubs: 'bin/rspec'
|
14
|
+
# * spring: 'bin/rsspec' (This will use spring if running and you have
|
15
|
+
# installed the spring binstubs per the docs)
|
16
|
+
# * zeus: 'zeus rspec' (requires the server to be started separetly)
|
17
|
+
# * 'just' rspec: 'rspec'
|
18
|
+
guard :rspec, cmd: 'bundle exec rspec' do
|
19
|
+
watch(%r{^spec/.+_spec\.rb$})
|
20
|
+
watch(%r{^lib/(.+)\.rb$}) { |m| "spec/lib/#{m[1]}_spec.rb" }
|
21
|
+
watch('spec/spec_helper.rb') { "spec" }
|
22
|
+
|
23
|
+
# Rails example
|
24
|
+
watch(%r{^app/(.+)\.rb$}) { |m| "spec/#{m[1]}_spec.rb" }
|
25
|
+
watch(%r{^app/(.*)(\.erb|\.haml|\.slim)$}) { |m| "spec/#{m[1]}#{m[2]}_spec.rb" }
|
26
|
+
watch(%r{^app/controllers/(.+)_(controller)\.rb$}) { |m| ["spec/routing/#{m[1]}_routing_spec.rb", "spec/#{m[2]}s/#{m[1]}_#{m[2]}_spec.rb", "spec/acceptance/#{m[1]}_spec.rb"] }
|
27
|
+
watch(%r{^spec/support/(.+)\.rb$}) { "spec" }
|
28
|
+
watch('config/routes.rb') { "spec/routing" }
|
29
|
+
watch('app/controllers/application_controller.rb') { "spec/controllers" }
|
30
|
+
watch('spec/rails_helper.rb') { "spec" }
|
31
|
+
|
32
|
+
# Capybara features specs
|
33
|
+
watch(%r{^app/views/(.+)/.*\.(erb|haml|slim)$}) { |m| "spec/features/#{m[1]}_spec.rb" }
|
34
|
+
|
35
|
+
# Turnip features and steps
|
36
|
+
watch(%r{^spec/acceptance/(.+)\.feature$})
|
37
|
+
watch(%r{^spec/acceptance/steps/(.+)_steps\.rb$}) { |m| Dir[File.join("**/#{m[1]}.feature")][0] || 'spec/acceptance' }
|
38
|
+
end
|
39
|
+
|
data/README.md
CHANGED
@@ -1,78 +1,132 @@
|
|
1
1
|
# Cylons
|
2
2
|
|
3
|
-
Collectively intelligent remote models which behave very much like models they are claiming to be. (
|
3
|
+
Collectively intelligent remote models which behave very much like models they are claiming to be. (Or the first zero configuration RPC/SOA framework).
|
4
4
|
|
5
|
-
Cylons lets your models in one Rails app, act very much like your ActiveRecord models in another Rails app, providing a
|
5
|
+
Cylons lets your models in one Rails app, act very much like your ActiveRecord models in another Rails app, providing a foundation for building an SOA infrastructure. Not exactly production ready, but getting there.
|
6
6
|
|
7
|
-
### Quick Explanation
|
7
|
+
### Quick Explanation / Scenario
|
8
8
|
|
9
|
+
Youve got a product model in one app, a category model in another. A category has many remote products. Then youve got another app, with a front end, that you want to use data from in both of those apps. Its as simple as:
|
10
|
+
(note you just need to include gem and initializers additionally)
|
11
|
+
|
12
|
+
**App 1**
|
13
|
+
*Product Model:*
|
14
|
+
``` ruby
|
15
|
+
class Product < ActiveRecord::Base
|
16
|
+
include ::Cylons::Remote
|
17
|
+
remote_belongs_to :category
|
18
|
+
end
|
19
|
+
```
|
20
|
+
*Category Agent:*
|
21
|
+
``` ruby
|
22
|
+
class Category < Cylons::Agent
|
23
|
+
|
24
|
+
end
|
25
|
+
```
|
26
|
+
|
27
|
+
**App 2**
|
28
|
+
*Category Model:*
|
29
|
+
``` ruby
|
30
|
+
class Category < ActiveRecord::Base
|
31
|
+
include ::Cylons::Remote
|
32
|
+
remote_has_many :products
|
33
|
+
end
|
34
|
+
```
|
35
|
+
*Product Agent:*
|
36
|
+
``` ruby
|
37
|
+
class Product < Cylons::Agent
|
38
|
+
|
39
|
+
end
|
40
|
+
```
|
41
|
+
|
42
|
+
That minimal amount of code will enable you to do things from app 3 such as:
|
43
|
+
|
44
|
+
*App 3*
|
45
|
+
``` ruby
|
46
|
+
category = Category.first
|
47
|
+
category.products
|
48
|
+
|
49
|
+
Product.create
|
50
|
+
Category.create
|
51
|
+
```
|
52
|
+
|
53
|
+
So on a so forth. Extensive examples provided down further.
|
9
54
|
|
10
55
|
### Depends heavily on:
|
11
|
-
DCell
|
12
|
-
Zookeeper
|
56
|
+
* DCell
|
57
|
+
* Zookeeper
|
13
58
|
|
14
59
|
### Heavily inspired by
|
15
|
-
This concept - http://www.youtube.com/watch?v=Hu-jvAWTZ9o&feature=autoplay&list=PLF88804CB7380F32C&playnext=1#t=4m59s
|
16
|
-
ActiveRemote - https://github.com/liveh2o/active_remote
|
17
|
-
DCell - https://github.com/celluloid/dcell
|
60
|
+
* This concept - http://www.youtube.com/watch?v=Hu-jvAWTZ9o&feature=autoplay&list=PLF88804CB7380F32C&playnext=1#t=4m59s
|
61
|
+
* ActiveRemote - https://github.com/liveh2o/active_remote
|
62
|
+
* DCell - https://github.com/celluloid/dcell
|
18
63
|
|
19
64
|
### Alternatives
|
20
|
-
|
65
|
+
Right now, the gem is still in sketchy mode. If you are looking for a heavy duty rpc ruby framework, I'd recommend:
|
21
66
|
|
22
|
-
ActiveRemote - https://github.com/liveh2o/active_remote
|
23
|
-
Protobuf - https://github.com/localshred/protobuf
|
24
|
-
|
25
|
-
Add those two together == winning.
|
26
|
-
|
27
|
-
### Reasons for building
|
28
|
-
Originally it started as a way to communicate between my raspberry pis, because http is so last summer. Soon I found myself wanting a database connection. So I ended up making it more active_record like. Those aren't reasons but brain tired done typing yep.
|
67
|
+
* ActiveRemote - https://github.com/liveh2o/active_remote
|
68
|
+
* Protobuf - https://github.com/localshred/protobuf
|
29
69
|
|
30
70
|
|
31
71
|
### Quick start
|
32
72
|
|
33
|
-
|
34
73
|
### How it works?
|
35
74
|
|
36
75
|
### Install ZK, Clone and run the examples
|
37
76
|
|
38
77
|
```
|
39
78
|
git clone https://github.com/jasonayre/cylons_demo
|
40
|
-
|
41
79
|
```
|
42
80
|
|
43
|
-
open
|
81
|
+
open 2 new terminal windows/tabs
|
44
82
|
|
45
|
-
*Prepare the
|
46
|
-
|
47
|
-
```
|
48
|
-
cd inventory
|
49
|
-
SKIP_CYLONS=true bundle exec rake db:create && rake db:migrate && rake db:seed
|
50
|
-
```
|
51
|
-
|
52
|
-
*Prepare the user credentials service, identify*
|
83
|
+
*Prepare & start the fake user credentials service, identify*
|
53
84
|
```
|
54
85
|
cd identify
|
55
|
-
|
86
|
+
bundle exec rake db:create && rake db:migrate && rake db:seed
|
87
|
+
bundle exec cylons start
|
56
88
|
```
|
57
89
|
|
58
|
-
*
|
90
|
+
*cd into admin service in other window, launch console and run some commands*
|
91
|
+
|
92
|
+
``` ruby
|
93
|
+
cd static_admin
|
94
|
+
bundle
|
95
|
+
RPC=1 bundle exec rails c
|
59
96
|
```
|
60
|
-
|
61
|
-
|
97
|
+
|
98
|
+
*Then run some rails console commands on the remote cylons service*
|
99
|
+
``` ruby
|
100
|
+
User.all
|
101
|
+
User.first
|
102
|
+
u = User.create(:name => "asdasd", :email => "bill@initech.com")
|
103
|
+
u.name = "blumbergh"
|
104
|
+
u.save
|
105
|
+
|
106
|
+
u = User.create(:name => "asdasd", :email => "asdasd@asdasd.com", :password => "asdasd")
|
107
|
+
{:error=>"unknown attribute: password"}
|
108
|
+
|
109
|
+
u = User.create(:email => "asdasd@asdasd")
|
110
|
+
puts u.errors
|
111
|
+
#<ActiveModel::Errors:0x343a4ddd @base=#<User created_at: nil, email: "asdasd@asdasd", id: nil, name: nil, updated_at: nil>, @messages={:name=>["can't be blank", "can't be blank"]}
|
112
|
+
|
113
|
+
users = User.search(:name => "blumbergh")
|
114
|
+
[#<User created_at: "2014-11-04 22:23:10.697000", email: "bill@initech.com", id: 2013, name: "blumbergh", updated_at: "2014-11-04 22:23:25.993000">]
|
115
|
+
|
116
|
+
#(when ::Cylons::RemotePagination included into remote model, results will be a will paginate collection)
|
117
|
+
users.current_page
|
118
|
+
|
119
|
+
#dont know why this isnt returning integer thats a bug..
|
120
|
+
users.current_page
|
121
|
+
=> page 1
|
62
122
|
```
|
123
|
+
|
63
124
|
*Start Zookeeper, and start each service up with:*
|
64
125
|
```
|
65
126
|
bundle exec cylons start
|
66
127
|
```
|
67
128
|
|
68
|
-
*
|
69
|
-
```
|
70
|
-
cd admin
|
71
|
-
bx rake db:seed
|
72
|
-
```
|
73
|
-
|
74
|
-
Note: there will be quite a few N+1 queries happening, intentionally. This is to demonstrate communication between the services, and speed. Each record that is created will make a call to Inventory, to check if that record already exists. If not, it will build the record by doing a Category.first_or_create (Taxon Service), to get the category_id, then it will make 3 additional calls to the Inventory service, 1 for manufacturer, 1 for department, and then finally one to actually create the Product.
|
75
|
-
|
129
|
+
*NOTE: You just need to pass a flag RPC=1 to force connection when running rails c or rails s -- RPC env var just needs to exist to force connection
|
76
130
|
|
77
131
|
## Installation
|
78
132
|
|
data/bin/cylons
CHANGED
@@ -2,32 +2,32 @@
|
|
2
2
|
|
3
3
|
require 'thor'
|
4
4
|
require 'cylons'
|
5
|
+
|
6
|
+
ENV["RPC"] ||= "1"
|
7
|
+
|
5
8
|
class Services < ::Thor
|
6
9
|
class_option :app, :default => "./config/environment.rb"
|
7
|
-
|
10
|
+
|
8
11
|
desc "start", "Start cylon services"
|
9
12
|
def start
|
10
13
|
puts "Starting services"
|
11
14
|
require options[:app]
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
::Dir.glob(::Rails.root.join('app', 'models', "*.rb")).each{ |file| load file }
|
16
|
-
|
15
|
+
|
16
|
+
::Cylons.load_models
|
17
|
+
|
17
18
|
::Cylons.logger.info "Cylon Remotes: #{::Cylons::RemoteRegistry.remotes}"
|
18
|
-
|
19
|
+
|
19
20
|
::Cylons::RemoteRegistry.register_schemas
|
20
|
-
|
21
|
+
|
21
22
|
::Cylons::ServiceManager.start
|
22
23
|
|
23
|
-
|
24
|
-
|
25
|
-
end
|
24
|
+
sleep
|
26
25
|
end
|
27
26
|
end
|
28
27
|
|
29
28
|
::Services.start
|
30
29
|
|
30
|
+
|
31
31
|
[:INT, :QUIT, :TERM].each do |signal|
|
32
32
|
trap(signal) do
|
33
33
|
::Cylons.logger.info "Stopping Cylon Services"
|
@@ -35,4 +35,3 @@ end
|
|
35
35
|
exit 0
|
36
36
|
end
|
37
37
|
end
|
38
|
-
|
data/cylons.gemspec
CHANGED
@@ -17,24 +17,29 @@ Gem::Specification.new do |spec|
|
|
17
17
|
spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
|
18
18
|
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
19
19
|
spec.require_paths = ["lib"]
|
20
|
-
|
21
|
-
spec.add_dependency "active_attr"
|
20
|
+
|
22
21
|
spec.add_dependency "active_attr"
|
23
|
-
spec.add_dependency "dcell", "0.15.0"
|
24
22
|
spec.add_dependency "thor"
|
25
23
|
spec.add_dependency "zk"
|
26
|
-
spec.add_dependency 'pry'
|
27
24
|
spec.add_dependency "will_paginate"
|
28
|
-
spec.add_dependency "
|
25
|
+
spec.add_dependency "dcell"
|
26
|
+
|
27
|
+
spec.add_runtime_dependency "pry"
|
29
28
|
|
30
29
|
spec.add_development_dependency "bundler", "~> 1.3"
|
31
30
|
spec.add_development_dependency "rake"
|
32
|
-
spec.add_development_dependency "pry"
|
33
31
|
spec.add_development_dependency "activerecord"
|
34
|
-
|
35
|
-
spec.add_development_dependency "rake"
|
32
|
+
spec.add_development_dependency "sqlite3"
|
36
33
|
spec.add_development_dependency "rspec"
|
37
34
|
spec.add_development_dependency "rspec-pride"
|
38
35
|
spec.add_development_dependency "pry-nav"
|
39
36
|
spec.add_development_dependency "simplecov"
|
37
|
+
spec.add_development_dependency 'rspec-its', '~> 1'
|
38
|
+
spec.add_development_dependency 'rspec-collection_matchers', '~> 1'
|
39
|
+
spec.add_development_dependency 'guard', '~> 2'
|
40
|
+
spec.add_development_dependency 'guard-rspec', '~> 4'
|
41
|
+
spec.add_development_dependency 'guard-bundler', '~> 2'
|
42
|
+
spec.add_development_dependency 'rb-fsevent'
|
43
|
+
spec.add_development_dependency 'terminal-notifier-guard'
|
44
|
+
|
40
45
|
end
|
data/lib/cylons.rb
CHANGED
@@ -5,16 +5,20 @@ require 'active_support/core_ext/hash'
|
|
5
5
|
require 'active_support/inflector'
|
6
6
|
require 'active_support/json'
|
7
7
|
require 'will_paginate'
|
8
|
+
require 'will_paginate/array'
|
8
9
|
require "cylons/version"
|
9
10
|
|
10
11
|
require 'cylons/attributes'
|
12
|
+
require 'cylons/agent'
|
11
13
|
require 'cylons/connection'
|
12
|
-
require 'cylons/configuration'
|
14
|
+
# require 'cylons/configuration'
|
15
|
+
require 'cylons/config'
|
13
16
|
require 'cylons/errors'
|
17
|
+
require 'cylons/logging'
|
14
18
|
require 'cylons/remote'
|
15
19
|
require 'cylons/remote_registry'
|
16
20
|
require 'cylons/remote_discovery'
|
17
|
-
require 'cylons/
|
21
|
+
require 'cylons/remote_pagination'
|
18
22
|
require 'cylons/registry_adapter'
|
19
23
|
require 'cylons/service'
|
20
24
|
require 'cylons/service_manager'
|
@@ -22,36 +26,61 @@ require 'dcell'
|
|
22
26
|
require 'socket'
|
23
27
|
require 'zk'
|
24
28
|
require 'dcell/registries/zk_adapter'
|
25
|
-
require 'cylons/railtie'
|
26
29
|
require 'pry'
|
27
|
-
# require 'cylons/railtie' if defined?(Rails)
|
28
30
|
|
29
31
|
module Cylons
|
30
|
-
|
32
|
+
def self.connect?
|
33
|
+
!!ENV["RPC"]
|
34
|
+
end
|
35
|
+
|
36
|
+
def self.load_models
|
37
|
+
::Dir.glob(model_paths).each{ |file|
|
38
|
+
puts "loading #{file}"
|
39
|
+
load file }
|
40
|
+
end
|
41
|
+
|
42
|
+
def self.model_paths
|
43
|
+
if configuration.model_paths
|
44
|
+
return configuration.model_paths
|
45
|
+
elsif defined?(::Rails)
|
46
|
+
[::Rails.root.join('app', 'models', "*.rb"), ::Rails.root.join('app', 'models', "**", "*.rb")]
|
47
|
+
else
|
48
|
+
[]
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
31
52
|
def self.skip_cylons?
|
32
|
-
|
53
|
+
!connect?
|
33
54
|
end
|
34
|
-
|
55
|
+
|
35
56
|
def self.silence?
|
36
57
|
skip_cylons? || (defined?(Rails) && Rails.env == "test")
|
37
58
|
end
|
38
|
-
|
59
|
+
|
39
60
|
class << self
|
40
|
-
attr_accessor :configuration
|
41
|
-
|
61
|
+
attr_accessor :configuration
|
62
|
+
|
42
63
|
def configuration
|
43
|
-
@configuration ||= ::Cylons::
|
64
|
+
@configuration ||= ::Cylons::Config.new
|
44
65
|
end
|
45
66
|
|
46
67
|
def configure
|
47
68
|
yield(configuration) if block_given?
|
48
|
-
|
69
|
+
|
49
70
|
@logger = configuration.logger
|
50
|
-
|
71
|
+
|
51
72
|
::ActiveSupport.run_load_hooks(:cylons, self)
|
52
73
|
end
|
53
|
-
|
54
74
|
alias_method :config, :configuration
|
75
|
+
|
76
|
+
def logger
|
77
|
+
::Cylons.config.logger
|
78
|
+
end
|
79
|
+
|
80
|
+
|
81
|
+
delegate :connect, :to => ::Cylons::Connection
|
82
|
+
delegate :connected?, :to => ::Cylons::Connection
|
55
83
|
end
|
56
84
|
end
|
57
85
|
|
86
|
+
require 'cylons/railtie' if defined?(Rails)
|
@@ -2,21 +2,23 @@ require 'cylons/remote_discovery'
|
|
2
2
|
|
3
3
|
module Cylons
|
4
4
|
module ActiveRecordExtensions
|
5
|
+
extend ::ActiveSupport::Concern
|
6
|
+
|
7
|
+
SEARCH_OPTION_KEYS = [:opts, :options].freeze
|
8
|
+
MAX_PER_PAGE = 1000
|
9
|
+
|
5
10
|
module ClassMethods
|
6
|
-
|
7
|
-
SEARCH_OPTION_KEYS = [:opts, :options].freeze
|
8
|
-
|
9
11
|
def reload_remotes!
|
10
12
|
::Cylons::RemoteDiscovery.load_remotes unless ::Cylons.silence?
|
11
13
|
end
|
12
|
-
|
14
|
+
|
13
15
|
def remote_schema
|
14
16
|
::Cylons::RemoteRegistry.get_remote_schema(self.name) unless ::Cylons.silence?
|
15
17
|
end
|
16
|
-
|
18
|
+
|
17
19
|
def remote_belongs_to(*args)
|
18
20
|
options = args.extract_options!
|
19
|
-
|
21
|
+
|
20
22
|
args.each do |arg|
|
21
23
|
options[:foreign_key] = "#{arg}_id"
|
22
24
|
association_hash = {:name => arg, :association_type => :belongs_to, :options => options}
|
@@ -24,36 +26,27 @@ module Cylons
|
|
24
26
|
build_remote_belongs_to_association(association_hash)
|
25
27
|
end
|
26
28
|
end
|
27
|
-
|
28
|
-
#store remote has many assoc globally, then define it locally.
|
29
|
+
|
30
|
+
#store remote has many assoc globally, then define it locally.
|
29
31
|
def remote_has_many(*args)
|
30
32
|
options = args.extract_options!
|
31
|
-
|
33
|
+
|
32
34
|
args.each do |arg|
|
33
35
|
association_hash = {:name => arg, :association_type => :has_many, :options => options}
|
34
36
|
self.remote_associations << association_hash
|
35
37
|
build_remote_has_many_association(association_hash)
|
36
38
|
end
|
37
39
|
end
|
38
|
-
|
39
|
-
|
40
|
-
def scope_by(params = {})
|
40
|
+
|
41
|
+
def search(params = {})
|
41
42
|
search_options = params.extract!(*SEARCH_OPTION_KEYS)
|
42
|
-
|
43
|
+
|
43
44
|
search_options.delete_if {|k,v| v.nil? }
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
else
|
50
|
-
scoped_search = params.inject(scoped) do |combined_scope, param|
|
51
|
-
combined_scope.send("by_#{param.first}", param.last)
|
52
|
-
end
|
53
|
-
end
|
54
|
-
|
55
|
-
scoped_search
|
56
|
-
end
|
45
|
+
|
46
|
+
query_scope = params.inject(all) do |query, hash_pair|
|
47
|
+
query.__send__("by_#{hash_pair[0]}", hash_pair[1]).all
|
48
|
+
end.all
|
49
|
+
end
|
57
50
|
end
|
58
51
|
end
|
59
|
-
end
|
52
|
+
end
|