reactive-record 0.7.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: c14856b73501aab70804ad8351301b87b948fd75
4
+ data.tar.gz: b0aef64c154ca72e6af956a1966e0e77235bafec
5
+ SHA512:
6
+ metadata.gz: bcc0cdea12ce7c93e27b6179ed6c2842207cf7e046bef8da8eb46643a2adf6964fad1e6d4d0f3c75853bf661de19142f28c987352b4f16abe03fbacdab8464a2
7
+ data.tar.gz: f861152c0a4ca7fda801ccf5ee5b8603a7c50a40c8d19506d9c90c71d68c732b99e092da468aa951577341b9f2056c0a89c85d102fdfd192824b814ec92fc6ad
data/MIT-LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ Copyright 2015 YOURNAME
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.rdoc ADDED
@@ -0,0 +1,3 @@
1
+ = ReactiveRecord
2
+
3
+ This project rocks and uses MIT-LICENSE.
data/Rakefile ADDED
@@ -0,0 +1,29 @@
1
+ begin
2
+ require 'bundler/setup'
3
+ rescue LoadError
4
+ puts 'You must `gem install bundler` and `bundle install` to run rake tasks'
5
+ end
6
+
7
+ APP_RAKEFILE = File.expand_path("../spec/dummy/Rakefile", __FILE__)
8
+ load 'rails/tasks/engine.rake'
9
+ Bundler::GemHelper.install_tasks
10
+ Dir[File.join(File.dirname(__FILE__), 'tasks/**/*.rake')].each {|f| load f }
11
+ require 'rspec/core'
12
+ require 'rspec/core/rake_task'
13
+ desc "Run all specs in spec directory (excluding plugin specs)"
14
+ RSpec::Core::RakeTask.new(:spec => 'app:db:test:prepare')
15
+
16
+ require 'opal/rspec/rake_task'
17
+ require 'bundler'
18
+ Bundler.require
19
+
20
+ # Add our opal/ directory to the load path
21
+ #Opal.append_path File.expand_path('../lib', __FILE__)
22
+
23
+ Opal::RSpec::RakeTask.new(:spec_opal) do |s|
24
+ s.sprockets.paths.tap { s.sprockets.clear_paths }[0..-2].each { |path| s.sprockets.append_path path}
25
+ s.main = 'sprockets_runner'
26
+ s.append_path 'spec-opal'
27
+ end
28
+
29
+ task :default => [:spec, :spec_opal]
@@ -0,0 +1,4 @@
1
+ module ReactiveRecord
2
+ class ApplicationController < ActionController::Base
3
+ end
4
+ end
@@ -0,0 +1,22 @@
1
+ require 'reactive_record/server_data_cache'
2
+
3
+ module ReactiveRecord
4
+
5
+ class ReactiveRecordController < ApplicationController
6
+
7
+ def fetch
8
+ render :json => ReactiveRecord::ServerDataCache[params[:pending_fetches]]
9
+ end
10
+
11
+
12
+ def save
13
+ render :json => ReactiveRecord::Base.save_records(params[:models], params[:associations])
14
+ end
15
+
16
+ def destroy
17
+ render :json => ReactiveRecord::Base.destroy_record(params[:model], params[:id], params[:vector])
18
+ end
19
+
20
+ end
21
+
22
+ end
data/config/routes.rb ADDED
@@ -0,0 +1,5 @@
1
+ ReactiveRecord::Engine.routes.draw do
2
+ root :to => "reactive_record#fetch", via: :post
3
+ match 'save', to: 'reactive_record#save', via: :post
4
+ match 'destroy', to: 'reactive_record#destroy', via: :post
5
+ end
data/lib/Gemfile ADDED
@@ -0,0 +1,17 @@
1
+ source "http://rubygems.org"
2
+
3
+ # Declare your gem's dependencies in reactive_record.gemspec.
4
+ # Bundler will treat runtime dependencies like base dependencies, and
5
+ # development dependencies will be added by default to the :development group.
6
+ gemspec
7
+
8
+ # jquery-rails is used by the dummy application
9
+ gem "jquery-rails"
10
+
11
+ # Declare any dependencies that are still in development here instead of in
12
+ # your gemspec. These might include edge Rails or gems from your path or
13
+ # Git. Remember to move these dependencies to your gemspec before releasing
14
+ # your gem to rubygems.org.
15
+
16
+ # To use debugger
17
+ # gem 'debugger'
@@ -0,0 +1,28 @@
1
+ if RUBY_ENGINE == 'opal'
2
+
3
+ require "opal-react"
4
+ require "reactive_record/server_data_cache"
5
+ require "reactive_record/active_record/reactive_record/while_loading"
6
+ require "reactive_record/active_record/reactive_record/isomorphic_base"
7
+ require "reactive_record/active_record/aggregations"
8
+ require "reactive_record/active_record/associations"
9
+ require "reactive_record/active_record/reactive_record/base"
10
+ require "reactive_record/active_record/reactive_record/collection"
11
+ require "reactive_record/active_record/class_methods"
12
+ require "reactive_record/active_record/instance_methods"
13
+ require "reactive_record/active_record/base"
14
+ require "reactive_record/interval"
15
+
16
+ else
17
+
18
+ require "opal"
19
+ require "reactive_record/version"
20
+ require "reactive_record/engine"
21
+ require "reactive_record/server_data_cache"
22
+ require "reactive_record/active_record/reactive_record/isomorphic_base"
23
+ require "reactive_record/serializers"
24
+
25
+ Opal.append_path File.expand_path('../', __FILE__).untaint
26
+ Opal.append_path File.expand_path('../../vendor', __FILE__).untaint
27
+
28
+ end
@@ -0,0 +1,38 @@
1
+ module ActiveRecord
2
+
3
+ class Base
4
+
5
+ def self.reflect_on_all_aggregations
6
+ base_class.instance_eval { @aggregations ||= [] }
7
+ end
8
+
9
+ def self.reflect_on_aggregation(attribute)
10
+ reflect_on_all_aggregations.detect { |aggregation| aggregation.attribute == attribute }
11
+ end
12
+
13
+ end
14
+
15
+ module Aggregations
16
+
17
+ class AggregationReflection
18
+
19
+ attr_reader :klass_name
20
+ attr_reader :attribute
21
+
22
+ def initialize(owner_class, macro, name, options = {})
23
+ owner_class.reflect_on_all_aggregations << self
24
+ @owner_class = owner_class
25
+ @klass_name = options[:class_name] || name.camelize
26
+ @attribute = name
27
+ end
28
+
29
+ def klass
30
+ @klass ||= Object.const_get(@klass_name)
31
+ end
32
+
33
+ end
34
+
35
+ end
36
+
37
+
38
+ end
@@ -0,0 +1,54 @@
1
+ module ActiveRecord
2
+
3
+ class Base
4
+
5
+ def self.reflect_on_all_associations
6
+ base_class.instance_eval { @associations ||= superclass.instance_eval { (@associations && @associations.dup) || [] } }
7
+ end
8
+
9
+ def self.reflect_on_association(attribute)
10
+ reflect_on_all_associations.detect { |association| association.attribute == attribute }
11
+ end
12
+
13
+ end
14
+
15
+ module Associations
16
+
17
+ class AssociationReflection
18
+
19
+ attr_reader :association_foreign_key
20
+ attr_reader :attribute
21
+ attr_reader :macro
22
+
23
+ def initialize(owner_class, macro, name, options = {})
24
+ owner_class.reflect_on_all_associations << self
25
+ @owner_class = owner_class
26
+ @macro = macro
27
+ @klass_name = options[:class_name] || (collection? && name.camelize.gsub(/s$/,"")) || name.camelize
28
+ @association_foreign_key = options[:foreign_key] || (macro == :belongs_to && "#{name}_id") || "#{@owner_class.name.underscore}_id"
29
+ @attribute = name
30
+ end
31
+
32
+ def inverse_of
33
+ unless @inverse_of
34
+ inverse_association = klass.reflect_on_all_associations.detect { | association | association.association_foreign_key == @association_foreign_key }
35
+ raise "Association #{@owner_class}.#{attribute} (foreign_key: #{@association_foreign_key}) has no inverse in #{@klass_name}" unless inverse_association
36
+ @inverse_of = inverse_association.attribute
37
+ end
38
+ @inverse_of
39
+ end
40
+
41
+ def klass
42
+ @klass ||= Object.const_get(@klass_name)
43
+ end
44
+
45
+ def collection?
46
+ [:has_many].include? @macro
47
+ end
48
+
49
+ end
50
+
51
+ end
52
+
53
+
54
+ end
@@ -0,0 +1,9 @@
1
+ module ActiveRecord
2
+ class Base
3
+
4
+ extend ClassMethods
5
+
6
+ include InstanceMethods
7
+
8
+ end
9
+ end
@@ -0,0 +1,113 @@
1
+ module ActiveRecord
2
+
3
+ module ClassMethods
4
+
5
+ def base_class
6
+
7
+ unless self < Base
8
+ raise ActiveRecordError, "#{name} doesn't belong in a hierarchy descending from ActiveRecord"
9
+ end
10
+
11
+ if superclass == Base || superclass.abstract_class?
12
+ self
13
+ else
14
+ superclass.base_class
15
+ end
16
+
17
+ end
18
+
19
+ def abstract_class?
20
+ defined?(@abstract_class) && @abstract_class == true
21
+ end
22
+
23
+ def primary_key
24
+ base_class.instance_eval { @primary_key_value || :id }
25
+ end
26
+
27
+ def primary_key=(val)
28
+ base_class.instance_eval { @primary_key_value = val }
29
+ end
30
+
31
+ def inheritance_column
32
+ base_class.instance_eval {@inheritance_column_value || "type"}
33
+ end
34
+
35
+ def inheritance_column=(name)
36
+ base_class.instance_eval {@inheritance_column_value = name}
37
+ end
38
+
39
+ def model_name
40
+ # in reality should return ActiveModel::Name object, blah blah
41
+ name
42
+ end
43
+
44
+ def find(id)
45
+ base_class.instance_eval {ReactiveRecord::Base.find(self, primary_key, id)}
46
+ end
47
+
48
+ def find_by(opts = {})
49
+ base_class.instance_eval {ReactiveRecord::Base.find(self, opts.first.first, opts.first.last)}
50
+ end
51
+
52
+ def method_missing(name, *args, &block)
53
+ if args.count == 1 && name =~ /^find_by_/ && !block
54
+ find_by(name.gsub(/^find_by_/, "") => args[0])
55
+ else
56
+ raise "#{self.name}.#{name}(#{args}) (called class method missing)"
57
+ end
58
+ end
59
+
60
+ def abstract_class=(val)
61
+ @abstract_class = val
62
+ end
63
+
64
+ def scope(name, body)
65
+ singleton_class.send(:define_method, name) { ReactiveRecord::Collection.new(self, nil, nil, self, name) }
66
+ end
67
+
68
+ def all
69
+ ReactiveRecord::Collection.new(self)
70
+ end
71
+
72
+ [:belongs_to, :has_many, :has_one].each do |macro|
73
+ define_method(macro) do |name, opts = {}|
74
+ Associations::AssociationReflection.new(base_class, macro, name, opts)
75
+ end
76
+ end
77
+
78
+ def composed_of(name, opts = {})
79
+ Aggregations::AggregationReflection.new(base_class, :composed_of, name, opts)
80
+ end
81
+
82
+ [
83
+ "table_name=", "before_validation", "with_options", "validates_presence_of", "validates_format_of",
84
+ "accepts_nested_attributes_for", "after_create", "before_save", "before_destroy", "where", "validate",
85
+ "attr_protected", "validates_numericality_of", "default_scope", "has_attached_file", "attr_accessible",
86
+ "serialize"
87
+ ].each do |method|
88
+ define_method(method.to_s) { |*args, &block| }
89
+ end
90
+
91
+ def _react_param_conversion(param, opt = nil)
92
+ # defines how react will convert incoming json to this ActiveRecord model
93
+ param_is_native = !param.respond_to?(:is_a?) rescue true
94
+ param = JSON.from_object param if param_is_native
95
+ if param.is_a? self
96
+ param
97
+ elsif param.is_a? Hash
98
+ if opt == :validate_only
99
+ ReactiveRecord::Base.infer_type_from_hash(self, param) == self
100
+ else
101
+ target = find(param[primary_key])
102
+ param.each { |key, value| param[key] = [value] }
103
+ ReactiveRecord::Base.load_from_json(param, target)
104
+ target
105
+ end
106
+ else
107
+ nil
108
+ end
109
+ end
110
+
111
+ end
112
+
113
+ end
@@ -0,0 +1,76 @@
1
+ module ActiveRecord
2
+
3
+ module InstanceMethods
4
+
5
+ def attributes
6
+ @backing_record.attributes
7
+ end
8
+
9
+ def initialize(hash = {})
10
+ if hash.is_a? ReactiveRecord::Base
11
+ @backing_record = hash
12
+ else
13
+ # standard active_record new -> creates a new instance, primary key is ignored if present
14
+ hash[primary_key] = nil
15
+ @backing_record = ReactiveRecord::Base.new(self.class, hash, self)
16
+ end
17
+ end
18
+
19
+ def primary_key
20
+ self.class.primary_key
21
+ end
22
+
23
+ def id
24
+ @backing_record.reactive_get!(primary_key)
25
+ end
26
+
27
+ def id=(value)
28
+ @backing_record.id = value
29
+ end
30
+
31
+ def model_name
32
+ # in reality should return ActiveModel::Name object, blah blah
33
+ self.class.model_name
34
+ end
35
+
36
+ def revert
37
+ @backing_record.revert
38
+ end
39
+
40
+ def changed?
41
+ @backing_record.changed?
42
+ end
43
+
44
+ def ==(ar_instance)
45
+ @backing_record == ar_instance.instance_eval { @backing_record }
46
+ end
47
+
48
+ def method_missing(name, *args, &block)
49
+ if name =~ /_changed\?$/
50
+ @backing_record.changed?(name.gsub(/_changed\?$/,""))
51
+ elsif args.count == 1 && name =~ /=$/ && !block
52
+ attribute_name = name.gsub(/=$/,"")
53
+ @backing_record.reactive_set!(attribute_name, args[0])
54
+ elsif args.count == 0 && !block
55
+ @backing_record.reactive_get!(name)
56
+ else
57
+ super
58
+ end
59
+ end
60
+
61
+ def save(&block)
62
+ @backing_record.save &block
63
+ end
64
+
65
+ def saving?
66
+ @backing_record.saving?
67
+ end
68
+
69
+ def destroy(&block)
70
+ @backing_record.destroy &block
71
+ end
72
+
73
+ end
74
+
75
+ end
76
+