hyper-mesh 0.5.1 → 0.5.2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/docs/activerecord_api.md +191 -11
- data/lib/active_record_base.rb +5 -1
- data/lib/hypermesh/version.rb +1 -1
- data/lib/reactive_record/active_record/class_methods.rb +37 -1
- data/lib/reactive_record/active_record/instance_methods.rb +13 -0
- data/lib/reactive_record/active_record/reactive_record/dummy_value.rb +1 -1
- data/lib/reactive_record/active_record/reactive_record/isomorphic_base.rb +22 -1
- data/lib/reactive_record/active_record/reactive_record/while_loading.rb +6 -0
- data/lib/reactive_record/server_data_cache.rb +1 -0
- data/lib/synchromesh/client_drivers.rb +19 -9
- data/reactive_record_test_app/Gemfile.lock +1 -1
- data/reactive_record_test_app/app/models/models.rb +1 -0
- data/reactive_record_test_app/app/{views/models → models/public}/address.rb +0 -0
- data/reactive_record_test_app/app/{views/models → models/public}/comment.rb +0 -0
- data/reactive_record_test_app/app/{views/models → models/public}/todo_item.rb +0 -0
- data/reactive_record_test_app/app/{views/models → models/public}/user.rb +0 -0
- data/reactive_record_test_app/config/application.rb +2 -1
- data/spec/reactive_record/edge_cases_spec.rb +1 -1
- data/spec/synchromesh/{unit_tests → aaa-unit_tests}/connection_spec.rb +0 -0
- data/spec/synchromesh/{unit_tests → aaa-unit_tests}/dummy_value_spec.rb +0 -0
- data/spec/synchromesh/column_types/column_type_spec.rb +16 -0
- data/spec/synchromesh/integration/saving_during_commit_spec.rb +64 -0
- metadata +13 -12
- data/reactive_record_test_app/app/models/.gitkeep +0 -0
- data/reactive_record_test_app/app/views/models.rb +0 -1
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 48e04a10e1ad295fd3b0d59e4bf55f376c4b7776
|
4
|
+
data.tar.gz: eef9862a88351836cc5a0bccfec7e3d7899d0315
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: c7458271b5d897075e1769db7017ce01e4cbe87d2c756605051f42e9131ddf8ca5816d81538b12c8f04e852902e4890b86cd3fabc944f6c1c2a484ddff91572e
|
7
|
+
data.tar.gz: b636a901cfe8eb0434c54cd3baa61534c34f758243531a2946b2d9dd3504e21d93f3154defbdf2542a6b31e78b7044377d05fe4b6a5c2ef82415f931ba655f91
|
data/docs/activerecord_api.md
CHANGED
@@ -1,9 +1,49 @@
|
|
1
1
|
## ActiveRecord API
|
2
2
|
|
3
|
-
HyperMesh uses a subset of the standard ActiveRecord API to give your client side HyperReact components access to your server side models.
|
3
|
+
HyperMesh uses a subset of the standard ActiveRecord API to give your client side HyperReact components access to your server side models. As much as possible HyperMesh follows the syntax as semantics of ActiveRecord.
|
4
|
+
|
5
|
+
### Interfacing to React
|
6
|
+
|
7
|
+
HyperMesh uses the React to deliver your model data to the client without you having to create extra APIs or specialized controllers. The key idea of React is that when state (or params) change, the portions of the display effected by this data will be updated.
|
8
|
+
|
9
|
+
HyperMesh automatically creates state objects that will be updated as server side data is loaded, or changes.
|
10
|
+
|
11
|
+
A brief overview of how this works will help you understand the how HyperMesh gets the job done.
|
12
|
+
|
13
|
+
#### Rendering Cycle
|
14
|
+
|
15
|
+
On the UI you will be reading models in order to display data.
|
16
|
+
|
17
|
+
If during the rendering of the display the model data is not yet loaded placeholder values (the default values from the `columns_hash`) will be returned by HyperMesh.
|
18
|
+
|
19
|
+
HyperMesh then keeps track of where these placeholders (or `DummyValue`s) are displayed, and when they do get loaded, those parts of the display will re-render.
|
20
|
+
|
21
|
+
If later the data changes (either due to local user actions, or receiving push updates) then again any parts of the display that were dependent on the current values will be re-rendered.
|
22
|
+
|
23
|
+
You normally do not have to be aware of this. Just access your models using the normal scopes and finders, to compute values and display attributes as you would on the server. Initially the display will show the placeholder values and then will be replaced with the real values.
|
24
|
+
|
25
|
+
|
26
|
+
#### Prerendering
|
27
|
+
|
28
|
+
During server-side pre-rendering, we do know all the values immediately so on initial page load all the values will be loaded and present.
|
29
|
+
|
30
|
+
#### Load Cycle Methods
|
31
|
+
|
32
|
+
There are a number of methods that allow you to interact with this load cycle when needed. These are documented [below].
|
33
|
+
|
4
34
|
|
5
35
|
### Class Methods
|
6
36
|
|
37
|
+
#### New and Create
|
38
|
+
|
39
|
+
`new`: Takes a hash of attributes and initializes a new unsaved record. The values of any attributes not specified in the hash will be taken from the models default values specified in the `columns_hash`.
|
40
|
+
|
41
|
+
If new is passed a native javascript object it will be treated as a hash and converted accordingly.
|
42
|
+
|
43
|
+
`create`: Short hand for `new(...).save`. See the `save` instance method for details on how saving is done.
|
44
|
+
|
45
|
+
#### Scoping and Finding
|
46
|
+
|
7
47
|
`scope` and `default_scope`: HyperMesh adds four new options to these methods: `joins`, `client`, `select` and `server`. The `joins` option provides information on how the scope will be joined with other models. The `client` and `select` options allow scoping to be done on the client side to offload this from the server, and the `server` option is there just for symmetry with the othe options. See the [Client Side Scoping](/docs/client_side_scoping.md) page for more details.
|
8
48
|
|
9
49
|
```ruby
|
@@ -30,6 +70,24 @@ scope :completed,
|
|
30
70
|
Word.all.each { |word| LI { word.text }}
|
31
71
|
```
|
32
72
|
|
73
|
+
`limit` and `offset`: These builtin scopes behave as they do on the server:
|
74
|
+
|
75
|
+
```ruby
|
76
|
+
Word.offset(500).limit(20) # get words 500-519
|
77
|
+
```
|
78
|
+
|
79
|
+
`find`: takes an id and returns the corresponding record.
|
80
|
+
|
81
|
+
`find_by`: takes single item hash indicating an attribute value pair to find.
|
82
|
+
|
83
|
+
`find_by_...`: i.e. `find_by_first_name` these will find the first record with a matching attribute.
|
84
|
+
|
85
|
+
```ruby
|
86
|
+
Word.find_by_text('hello') # short for Word.find_by(text: 'hello')
|
87
|
+
```
|
88
|
+
|
89
|
+
#### Relationships and Aggregations
|
90
|
+
|
33
91
|
`belongs_to, has_many, has_one`: These all work as on the server. However it is important that you fully specify both sides of the relationship. This is not always necessary on the server because ActiveRecord uses the table schema to work things out.
|
34
92
|
|
35
93
|
```ruby
|
@@ -44,30 +102,152 @@ end
|
|
44
102
|
|
45
103
|
`composed_of`: You can create aggregate models like ActiveRecord.
|
46
104
|
|
105
|
+
#### Defining server methods
|
106
|
+
|
107
|
+
Normally an application defined instance method will run on the client and the server:
|
108
|
+
|
109
|
+
```ruby
|
110
|
+
class User < ActiveRecord::Base
|
111
|
+
def full_name
|
112
|
+
"#{first_name} #{last_name}"
|
113
|
+
end
|
114
|
+
end
|
115
|
+
```
|
116
|
+
|
117
|
+
Sometimes it is desirable to only run method on the server. This can be done using the `server_method` macro:
|
118
|
+
|
119
|
+
```ruby
|
120
|
+
class User < ActiveRecord::Base
|
121
|
+
server_method :full_name, default: '' do
|
122
|
+
"#{first_name} #{last_name}"
|
123
|
+
end
|
124
|
+
end
|
125
|
+
```
|
126
|
+
|
127
|
+
When the method is first called on the client the default value will be returned, and there will be a reactive update when the true value is returned from the server.
|
128
|
+
|
129
|
+
To force the value to be recomputed at the server append a `!` to the end of the name, otherwise the last value returned from the server will continue to be returned.
|
130
|
+
|
131
|
+
#### Model Information
|
132
|
+
|
47
133
|
`column_names`: returns a list of the database columns.
|
48
134
|
|
49
135
|
`columns_hash`: returns the details of the columns specification. Note that on the server `columns_hash` returns a hash of objects specifying column information. On the client the entire structure is just one big hash of hashes.
|
50
136
|
|
51
|
-
`abstract_class=`, `abstract_class?`, `primary_key`, `primary_key=`, `inheritance_column`, `inheritance_column=`, `model_name`:
|
137
|
+
`abstract_class=`, `abstract_class?`, `primary_key`, `primary_key=`, `inheritance_column`, `inheritance_column=`, `model_name`: All work as on the server. See ActiveRecord documentation for more info.
|
52
138
|
|
53
|
-
|
139
|
+
### Instance Methods
|
54
140
|
|
55
|
-
|
141
|
+
#### Attribute and Relationship Getter and Setters
|
56
142
|
|
57
|
-
|
143
|
+
All attributes have an associated getter and setter. All relationships have a getter. All belongs_to relationships have a setter. `has_many` relationships can be updated using the push (`<<`) operator or using the `delete` method.
|
58
144
|
|
59
|
-
|
145
|
+
```ruby
|
146
|
+
puts my_todo.name
|
147
|
+
my_todo.name = "neuname"
|
148
|
+
my_todo.comments << a_new_comment
|
149
|
+
a_new_comment.todo == my_todo # true!
|
150
|
+
```
|
151
|
+
|
152
|
+
In addition if the attribute getter ends with a bang (!) then this will force a fetch of the attribute from the server. This is typically not necessary if push updates are configured.
|
153
|
+
|
154
|
+
#### Saving
|
155
|
+
|
156
|
+
The `save` method works like ActiveRecord save, *except* it returns a promise that is resolved when the save completes (or fails.)
|
60
157
|
|
61
158
|
```ruby
|
62
|
-
|
159
|
+
my_todo.save(validate: false).then do |result|
|
160
|
+
# result is a hash with {success: ..., message: , models: ....}
|
161
|
+
end
|
63
162
|
```
|
64
163
|
|
65
|
-
|
164
|
+
After saving the models will have an `errors` hash with any validation problems.
|
66
165
|
|
67
|
-
`
|
166
|
+
During the save operation the method `saving?` will return `true`. This can be used to instead of (or with) the promise to update the screen:
|
68
167
|
|
69
|
-
|
168
|
+
```ruby
|
169
|
+
render do
|
170
|
+
...
|
171
|
+
if some_model.saving?
|
172
|
+
... display please wait ...
|
173
|
+
elsif some_model.errors.any?
|
174
|
+
... highlight the errors ...
|
175
|
+
else
|
176
|
+
... display data ...
|
177
|
+
end
|
178
|
+
...
|
179
|
+
end
|
180
|
+
```
|
181
|
+
|
182
|
+
#### Destroy
|
183
|
+
|
184
|
+
Like `save` destroy returns a promise that is resolved when the destroy completes.
|
185
|
+
|
186
|
+
After the destroy completes the records `destroyed?` method will return true.
|
187
|
+
|
188
|
+
#### Other Instance Methods
|
189
|
+
|
190
|
+
`new?` returns true if the model is new and not yet saved.
|
191
|
+
|
192
|
+
`primary_key` returns the primary key for the model
|
193
|
+
|
194
|
+
`id` returns the value of the primary key for this instance
|
195
|
+
|
196
|
+
`model_name` returns the model_name.
|
197
|
+
|
198
|
+
`revert` Undoes any unsaved changes to the instance.
|
199
|
+
|
200
|
+
`changed?` returns true if any attributes have changed (always true for a new model)
|
201
|
+
|
202
|
+
`dup` duplicate the instance.
|
203
|
+
|
204
|
+
`==` two instances are the same if they reference the same underlying table row.
|
205
|
+
|
206
|
+
`..._changed?` (i.e. name_changed?) returns true if the specific attribute has changed.
|
207
|
+
|
208
|
+
`itself` returns the record, but will also force a load of at least the model's id.
|
209
|
+
|
210
|
+
#### Other Methods for Interacting with the Load & Render Cycle
|
211
|
+
|
212
|
+
#### `loading?` and `loaded?`
|
213
|
+
|
214
|
+
All Ruby objects will respond to these methods. If you want to put up a "Please Wait" message, spinner, etc, you can use the `loaded?` or `loading?` method to determine if the object represents a real loaded value or not.
|
215
|
+
|
216
|
+
#### The `HyperMesh.load` Method
|
217
|
+
|
218
|
+
Sometimes it is necessary to insure values are loaded outside of the rendering cycle. For this you can use the `HyperMesh.load` method:
|
70
219
|
|
71
220
|
```ruby
|
72
|
-
|
221
|
+
HyperMesh.load do
|
222
|
+
x = my_model.some_attribute
|
223
|
+
OtherModel.find(x+12).other_attribute
|
224
|
+
# code in here can be arbitrarily complex and load
|
225
|
+
# will re-execute it until all values are loaded
|
226
|
+
# the final expression is passed to the promise
|
227
|
+
end.then |result|
|
228
|
+
puts result
|
229
|
+
end
|
73
230
|
```
|
231
|
+
|
232
|
+
|
233
|
+
|
234
|
+
#### Force Loading Attributes
|
235
|
+
|
236
|
+
Like
|
237
|
+
|
238
|
+
Normally you will simply display attributes as part of the render method, and when the values are loaded from the server the component will re-render.
|
239
|
+
|
240
|
+
Sometimes outside of the render method you may need to insure an attribute (or a server side method) is loaded before proceeding. This is typically when you are building some kind of higher level store.
|
241
|
+
|
242
|
+
The `load` takes a list of attributes (symbols) and will insure these are loaded. Load returns a promise that is resolved when the load completes, or can be passed a block that will execute when the load completes.
|
243
|
+
|
244
|
+
```ruby
|
245
|
+
before_mount do
|
246
|
+
Todo.find(1).load(:name).then do |name|
|
247
|
+
@name = name;
|
248
|
+
state.loaded! true
|
249
|
+
end
|
250
|
+
end
|
251
|
+
```
|
252
|
+
|
253
|
+
Think hard about how you are using this, as HyperMesh already acts as flux store, and is managing state for you.
|
data/lib/active_record_base.rb
CHANGED
@@ -42,6 +42,10 @@ module ActiveRecord
|
|
42
42
|
pre_synchromesh_default_scope(opts[:server], &block)
|
43
43
|
end
|
44
44
|
|
45
|
+
def server_method(name, opts = {}, &block)
|
46
|
+
define_method name, &block
|
47
|
+
end
|
48
|
+
|
45
49
|
else
|
46
50
|
|
47
51
|
alias pre_synchromesh_method_missing method_missing
|
@@ -113,7 +117,7 @@ module ActiveRecord
|
|
113
117
|
after_commit :synchromesh_after_destroy, on: [:destroy]
|
114
118
|
|
115
119
|
def synchromesh_after_create
|
116
|
-
return if do_not_synchronize?
|
120
|
+
return if do_not_synchronize? #|| previous_changes.empty?
|
117
121
|
HyperMesh.after_commit :create, self
|
118
122
|
end
|
119
123
|
|
data/lib/hypermesh/version.rb
CHANGED
@@ -107,6 +107,10 @@ module ActiveRecord
|
|
107
107
|
[:belongs_to, :has_many, :has_one].each do |macro|
|
108
108
|
define_method(macro) do |*args| # is this a bug in opal? saying name, scope=nil, opts={} does not work!
|
109
109
|
name = args.first
|
110
|
+
define_method(name) { @backing_record.reactive_get!(name, nil) }
|
111
|
+
define_method("#{name}=") do |val|
|
112
|
+
@backing_record.reactive_set!(name, backing_record.convert(name, val))
|
113
|
+
end
|
110
114
|
opts = (args.count > 1 and args.last.is_a? Hash) ? args.last : {}
|
111
115
|
Associations::AssociationReflection.new(self, macro, name, opts)
|
112
116
|
end
|
@@ -114,16 +118,48 @@ module ActiveRecord
|
|
114
118
|
|
115
119
|
def composed_of(name, opts = {})
|
116
120
|
Aggregations::AggregationReflection.new(base_class, :composed_of, name, opts)
|
121
|
+
define_method(name) { @backing_record.reactive_get!(name, nil) }
|
122
|
+
define_method("#{name}=") do |val|
|
123
|
+
@backing_record.reactive_set!(name, backing_record.convert(name, val))
|
124
|
+
end
|
117
125
|
end
|
118
126
|
|
119
127
|
def column_names
|
120
|
-
|
128
|
+
HyperMesh::ClientDrivers.public_columns_hash.keys
|
121
129
|
end
|
122
130
|
|
123
131
|
def columns_hash
|
124
132
|
HyperMesh::ClientDrivers.public_columns_hash[name] || {}
|
125
133
|
end
|
126
134
|
|
135
|
+
def server_methods
|
136
|
+
@server_methods ||= {}
|
137
|
+
end
|
138
|
+
|
139
|
+
def server_method(name, default: nil)
|
140
|
+
server_methods[name] = { default: default }
|
141
|
+
define_method(name) do |*args|
|
142
|
+
vector = args.count.zero? ? name : [[name]+args]
|
143
|
+
@backing_record.reactive_get!(vector, nil)
|
144
|
+
end
|
145
|
+
define_method("#{name}!") do |*args|
|
146
|
+
vector = args.count.zero? ? name : [[name]+args]
|
147
|
+
@backing_record.reactive_get!(vector, true)
|
148
|
+
end
|
149
|
+
end
|
150
|
+
|
151
|
+
def define_attribute_methods
|
152
|
+
columns_hash.keys.each do |name|
|
153
|
+
next if name == :id
|
154
|
+
define_method(name) { @backing_record.reactive_get!(name, nil) }
|
155
|
+
define_method("#{name}!") { @backing_record.reactive_get!(name, true) }
|
156
|
+
define_method("#{name}=") do |val|
|
157
|
+
@backing_record.reactive_set!(name, backing_record.convert(name, val))
|
158
|
+
end
|
159
|
+
define_method("#{name}_changed?") { @backing_record.changed?(name) }
|
160
|
+
end
|
161
|
+
end
|
162
|
+
|
127
163
|
[
|
128
164
|
"table_name=", "before_validation", "with_options", "validates_presence_of", "validates_format_of",
|
129
165
|
"accepts_nested_attributes_for", "before_create", "after_create", "before_save", "after_save", "before_destroy", "where", "validate",
|
@@ -34,6 +34,14 @@ module ActiveRecord
|
|
34
34
|
self.class.primary_key
|
35
35
|
end
|
36
36
|
|
37
|
+
def type
|
38
|
+
@backing_record.reactive_get!(:type, nil)
|
39
|
+
end
|
40
|
+
|
41
|
+
def type=(val)
|
42
|
+
@backing_record.reactive_set!(:type, backing_record.convert(:type, val))
|
43
|
+
end
|
44
|
+
|
37
45
|
def id
|
38
46
|
@backing_record.reactive_get!(primary_key)
|
39
47
|
end
|
@@ -63,7 +71,12 @@ module ActiveRecord
|
|
63
71
|
@backing_record == ar_instance.instance_eval { @backing_record }
|
64
72
|
end
|
65
73
|
|
74
|
+
def method_missing_warning(name)
|
75
|
+
@backing_record.deprecation_warning("Server side method #{name} must be defined using the 'server_method' macro.")
|
76
|
+
end
|
77
|
+
|
66
78
|
def method_missing(name, *args, &block)
|
79
|
+
method_missing_warning("#{name}(#{args})")
|
67
80
|
if name =~ /\!$/
|
68
81
|
name = name.gsub(/\!$/,"")
|
69
82
|
force_update = true
|
@@ -7,6 +7,7 @@ module ReactiveRecord
|
|
7
7
|
include React::IsomorphicHelpers
|
8
8
|
|
9
9
|
before_first_mount do |context|
|
10
|
+
HyperMesh::ClientDrivers.on_first_mount
|
10
11
|
if RUBY_ENGINE != 'opal'
|
11
12
|
@server_data_cache = ReactiveRecord::ServerDataCache.new(context.controller.acting_user, {})
|
12
13
|
else
|
@@ -28,6 +29,19 @@ module ReactiveRecord
|
|
28
29
|
end
|
29
30
|
end
|
30
31
|
|
32
|
+
def self.deprecation_warning(model, message)
|
33
|
+
@deprecation_messages ||= []
|
34
|
+
message = "Warning: Deprecated feature used in #{model}. #{message}"
|
35
|
+
unless @deprecation_messages.include? message
|
36
|
+
@deprecation_messages << message
|
37
|
+
log message, :warning
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
def deprecation_warning(message)
|
42
|
+
self.class.deprecation_warning(model, message)
|
43
|
+
end
|
44
|
+
|
31
45
|
def records
|
32
46
|
self.class.instance_variable_get(:@records)
|
33
47
|
end
|
@@ -87,9 +101,16 @@ module ReactiveRecord
|
|
87
101
|
@pending_records << record if record
|
88
102
|
schedule_fetch
|
89
103
|
end
|
90
|
-
DummyValue.new(record && record.
|
104
|
+
DummyValue.new(record && record.get_columns_info_for_vector(vector))
|
105
|
+
end
|
106
|
+
|
107
|
+
def get_columns_info_for_vector(vector)
|
108
|
+
method_name = vector.last
|
109
|
+
method_name = method_name.first if method_name.is_a? Array
|
110
|
+
model.columns_hash[method_name] || model.server_methods[method_name]
|
91
111
|
end
|
92
112
|
|
113
|
+
|
93
114
|
class << self
|
94
115
|
|
95
116
|
attr_reader :pending_fetches
|
@@ -106,6 +106,7 @@ module ReactiveRecord
|
|
106
106
|
end
|
107
107
|
|
108
108
|
def self.[](models, associations, vectors, acting_user)
|
109
|
+
ActiveRecord::Base.public_columns_hash
|
109
110
|
result = nil
|
110
111
|
ActiveRecord::Base.transaction do
|
111
112
|
cache = new(acting_user, ReactiveRecord::Base.save_records(models, associations, acting_user, false, false))
|
@@ -272,8 +272,9 @@ module HyperMesh
|
|
272
272
|
"</script>\n"
|
273
273
|
end if RUBY_ENGINE != 'opal'
|
274
274
|
|
275
|
-
|
276
|
-
|
275
|
+
class << self
|
276
|
+
attr_reader :opts
|
277
|
+
attr_reader :public_columns_hash
|
277
278
|
end
|
278
279
|
|
279
280
|
isomorphic_method(:get_public_columns_hash) do |f|
|
@@ -282,10 +283,6 @@ module HyperMesh
|
|
282
283
|
f.when_on_server { ActiveRecord::Base.public_columns_hash }
|
283
284
|
end
|
284
285
|
|
285
|
-
def self.public_columns_hash
|
286
|
-
@public_columns_hash ||= get_public_columns_hash
|
287
|
-
end
|
288
|
-
|
289
286
|
def self.get_queued_data(operation, channel = nil, opts = {})
|
290
287
|
HTTP.get(polling_path(operation, channel), opts).then do |response|
|
291
288
|
response.json.each do |update|
|
@@ -294,10 +291,23 @@ module HyperMesh
|
|
294
291
|
end
|
295
292
|
end
|
296
293
|
|
297
|
-
|
298
|
-
|
294
|
+
def self.define_attribute_methods
|
295
|
+
public_columns_hash.keys.each do |model|
|
296
|
+
Object.const_get(model).define_attribute_methods rescue nil
|
297
|
+
end
|
298
|
+
end
|
299
|
+
|
300
|
+
# called from ReactiveRecord::Base before_first_mount hook
|
301
|
+
# to insure this is done first.
|
302
|
+
|
303
|
+
def self.on_first_mount
|
304
|
+
|
305
|
+
if RUBY_ENGINE == 'opal'
|
306
|
+
@opts = Hash.new(`window.HyperMeshOpts`)
|
307
|
+
@public_columns_hash = get_public_columns_hash
|
308
|
+
define_attribute_methods
|
309
|
+
end
|
299
310
|
|
300
|
-
before_first_mount do
|
301
311
|
if on_opal_client?
|
302
312
|
|
303
313
|
if opts[:transport] == :pusher
|
@@ -0,0 +1 @@
|
|
1
|
+
require_tree './public' if RUBY_ENGINE == 'opal'
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
@@ -50,7 +50,8 @@ module Dummy
|
|
50
50
|
# Enable the asset pipeline
|
51
51
|
config.assets.enabled = true
|
52
52
|
|
53
|
-
config.autoload_paths += %W(#{config.root}/app/
|
53
|
+
#config.autoload_paths += %W(#{config.root}/app/models/public)
|
54
|
+
config.assets.paths << ::Rails.root.join('app', 'models').to_s
|
54
55
|
|
55
56
|
# Version of your assets, change this if you want to expire all your assets
|
56
57
|
config.assets.version = '1.0'
|
@@ -21,7 +21,7 @@ describe "reactive-record edge cases", js: true do
|
|
21
21
|
FactoryGirl.create(:todo, title: "User #{i}'s todo", owner: user)
|
22
22
|
end
|
23
23
|
expect_promise do
|
24
|
-
|
24
|
+
HyperMesh.load do
|
25
25
|
Todo.all.collect do |todo|
|
26
26
|
todo.owner && todo.owner.first_name
|
27
27
|
end.compact
|
File without changes
|
File without changes
|
@@ -96,6 +96,9 @@ describe "column types on client", js: true do
|
|
96
96
|
|
97
97
|
isomorphic do
|
98
98
|
class TypeTest < ActiveRecord::Base
|
99
|
+
server_method :a_server_method, default: "hello" do |s|
|
100
|
+
s.reverse
|
101
|
+
end
|
99
102
|
end
|
100
103
|
class DefaultTest < ActiveRecord::Base
|
101
104
|
end
|
@@ -125,6 +128,19 @@ describe "column types on client", js: true do
|
|
125
128
|
end.to eq(TypeTest.columns_hash.as_json)
|
126
129
|
end
|
127
130
|
|
131
|
+
it 'defines the server method with a default value' do
|
132
|
+
expect_evaluate_ruby do
|
133
|
+
TypeTest.new.a_server_method('foo')
|
134
|
+
end.to eq('hello')
|
135
|
+
end
|
136
|
+
|
137
|
+
it 'loads the server method' do
|
138
|
+
TypeTest.create
|
139
|
+
expect_promise do
|
140
|
+
ReactiveRecord.load { TypeTest.find(1).a_server_method('hello') }
|
141
|
+
end.to eq('olleh')
|
142
|
+
end
|
143
|
+
|
128
144
|
it 'creates a dummy value of the appropriate type' do
|
129
145
|
t = Time.now
|
130
146
|
TypeTest.create(
|
@@ -0,0 +1,64 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'synchromesh/integration/test_components'
|
3
|
+
require 'rspec-steps'
|
4
|
+
|
5
|
+
describe "saving during commit", js: true do
|
6
|
+
|
7
|
+
before(:each) do
|
8
|
+
require 'pusher'
|
9
|
+
require 'pusher-fake'
|
10
|
+
Pusher.app_id = "MY_TEST_ID"
|
11
|
+
Pusher.key = "MY_TEST_KEY"
|
12
|
+
Pusher.secret = "MY_TEST_SECRET"
|
13
|
+
require "pusher-fake/support/base"
|
14
|
+
|
15
|
+
HyperMesh.configuration do |config|
|
16
|
+
config.transport = :pusher
|
17
|
+
config.channel_prefix = "synchromesh"
|
18
|
+
config.opts = {app_id: Pusher.app_id, key: Pusher.key, secret: Pusher.secret}.merge(PusherFake.configuration.web_options)
|
19
|
+
end
|
20
|
+
|
21
|
+
class CommitIssue < ActiveRecord::Base
|
22
|
+
def self.build_tables
|
23
|
+
connection.create_table :commit_issues, force: true do |t|
|
24
|
+
t.string :name
|
25
|
+
t.timestamps
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
isomorphic do
|
31
|
+
class CommitIssue < ActiveRecord::Base
|
32
|
+
after_create :save_again
|
33
|
+
def save_again
|
34
|
+
save
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
CommitIssue.build_tables rescue nil
|
40
|
+
|
41
|
+
stub_const 'ApplicationPolicy', Class.new
|
42
|
+
ApplicationPolicy.class_eval do
|
43
|
+
always_allow_connection
|
44
|
+
regulate_all_broadcasts { |policy| policy.send_all }
|
45
|
+
allow_change(to: :all, on: [:create, :update, :destroy]) { true }
|
46
|
+
end
|
47
|
+
size_window(:small, :portrait)
|
48
|
+
end
|
49
|
+
|
50
|
+
it "broadcast even if saving during after_save" do
|
51
|
+
CommitIssue.create(name: 1)
|
52
|
+
mount "CommitIssueTest" do
|
53
|
+
class CommitIssueTest < React::Component::Base
|
54
|
+
render do
|
55
|
+
"all: [#{CommitIssue.all.pluck(:name)}]"
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
59
|
+
page.should have_content('all: [1]')
|
60
|
+
CommitIssue.create(name: 2)
|
61
|
+
page.should have_content('all: [1,2]')
|
62
|
+
end
|
63
|
+
|
64
|
+
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: hyper-mesh
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.5.
|
4
|
+
version: 0.5.2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Mitch VanDuyn
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2016-11-
|
11
|
+
date: 2016-11-16 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: activerecord
|
@@ -1045,17 +1045,16 @@ files:
|
|
1045
1045
|
- reactive_record_test_app/app/controllers/test_controller.rb
|
1046
1046
|
- reactive_record_test_app/app/helpers/application_helper.rb
|
1047
1047
|
- reactive_record_test_app/app/mailers/.gitkeep
|
1048
|
-
- reactive_record_test_app/app/models
|
1048
|
+
- reactive_record_test_app/app/models/models.rb
|
1049
|
+
- reactive_record_test_app/app/models/public/address.rb
|
1050
|
+
- reactive_record_test_app/app/models/public/comment.rb
|
1051
|
+
- reactive_record_test_app/app/models/public/todo_item.rb
|
1052
|
+
- reactive_record_test_app/app/models/public/user.rb
|
1049
1053
|
- reactive_record_test_app/app/policies/application_policy.rb
|
1050
1054
|
- reactive_record_test_app/app/views/components.rb
|
1051
1055
|
- reactive_record_test_app/app/views/components/test.rb
|
1052
1056
|
- reactive_record_test_app/app/views/home/index.html.erb
|
1053
1057
|
- reactive_record_test_app/app/views/layouts/application.html.erb
|
1054
|
-
- reactive_record_test_app/app/views/models.rb
|
1055
|
-
- reactive_record_test_app/app/views/models/address.rb
|
1056
|
-
- reactive_record_test_app/app/views/models/comment.rb
|
1057
|
-
- reactive_record_test_app/app/views/models/todo_item.rb
|
1058
|
-
- reactive_record_test_app/app/views/models/user.rb
|
1059
1058
|
- reactive_record_test_app/config.ru
|
1060
1059
|
- reactive_record_test_app/config/application.rb
|
1061
1060
|
- reactive_record_test_app/config/boot.rb
|
@@ -1132,6 +1131,8 @@ files:
|
|
1132
1131
|
- spec/reactive_record/update_scopes_spec.rb
|
1133
1132
|
- spec/spec_helper.rb
|
1134
1133
|
- spec/support/component_helpers.rb
|
1134
|
+
- spec/synchromesh/aaa-unit_tests/connection_spec.rb
|
1135
|
+
- spec/synchromesh/aaa-unit_tests/dummy_value_spec.rb
|
1135
1136
|
- spec/synchromesh/column_types/column_type_spec.rb
|
1136
1137
|
- spec/synchromesh/crud_access_regulation/broadcast_controls_access_spec.rb
|
1137
1138
|
- spec/synchromesh/crud_access_regulation/model_policies_spec.rb
|
@@ -1143,6 +1144,7 @@ files:
|
|
1143
1144
|
- spec/synchromesh/integration/default_scope_spec.rb
|
1144
1145
|
- spec/synchromesh/integration/has_many_through_spec.rb
|
1145
1146
|
- spec/synchromesh/integration/relationships_spec.rb
|
1147
|
+
- spec/synchromesh/integration/saving_during_commit_spec.rb
|
1146
1148
|
- spec/synchromesh/integration/scope_spec.rb
|
1147
1149
|
- spec/synchromesh/integration/synchromesh_spec.rb
|
1148
1150
|
- spec/synchromesh/integration/test_components.rb
|
@@ -1154,8 +1156,6 @@ files:
|
|
1154
1156
|
- spec/synchromesh/policies/regulate_broadcast_spec.rb
|
1155
1157
|
- spec/synchromesh/policies/regulate_class_connection_spec.rb
|
1156
1158
|
- spec/synchromesh/policies/regulate_instance_connection_spec.rb
|
1157
|
-
- spec/synchromesh/unit_tests/connection_spec.rb
|
1158
|
-
- spec/synchromesh/unit_tests/dummy_value_spec.rb
|
1159
1159
|
- spec/test_app/Gemfile
|
1160
1160
|
- spec/test_app/Gemfile.lock
|
1161
1161
|
- spec/test_app/Rakefile
|
@@ -1259,6 +1259,8 @@ test_files:
|
|
1259
1259
|
- spec/reactive_record/update_scopes_spec.rb
|
1260
1260
|
- spec/spec_helper.rb
|
1261
1261
|
- spec/support/component_helpers.rb
|
1262
|
+
- spec/synchromesh/aaa-unit_tests/connection_spec.rb
|
1263
|
+
- spec/synchromesh/aaa-unit_tests/dummy_value_spec.rb
|
1262
1264
|
- spec/synchromesh/column_types/column_type_spec.rb
|
1263
1265
|
- spec/synchromesh/crud_access_regulation/broadcast_controls_access_spec.rb
|
1264
1266
|
- spec/synchromesh/crud_access_regulation/model_policies_spec.rb
|
@@ -1270,6 +1272,7 @@ test_files:
|
|
1270
1272
|
- spec/synchromesh/integration/default_scope_spec.rb
|
1271
1273
|
- spec/synchromesh/integration/has_many_through_spec.rb
|
1272
1274
|
- spec/synchromesh/integration/relationships_spec.rb
|
1275
|
+
- spec/synchromesh/integration/saving_during_commit_spec.rb
|
1273
1276
|
- spec/synchromesh/integration/scope_spec.rb
|
1274
1277
|
- spec/synchromesh/integration/synchromesh_spec.rb
|
1275
1278
|
- spec/synchromesh/integration/test_components.rb
|
@@ -1281,8 +1284,6 @@ test_files:
|
|
1281
1284
|
- spec/synchromesh/policies/regulate_broadcast_spec.rb
|
1282
1285
|
- spec/synchromesh/policies/regulate_class_connection_spec.rb
|
1283
1286
|
- spec/synchromesh/policies/regulate_instance_connection_spec.rb
|
1284
|
-
- spec/synchromesh/unit_tests/connection_spec.rb
|
1285
|
-
- spec/synchromesh/unit_tests/dummy_value_spec.rb
|
1286
1287
|
- spec/test_app/Gemfile
|
1287
1288
|
- spec/test_app/Gemfile.lock
|
1288
1289
|
- spec/test_app/Rakefile
|
File without changes
|
@@ -1 +0,0 @@
|
|
1
|
-
require_tree './models'
|