Module: RenderSync::Model::ClassMethods
- Defined in:
- lib/render_sync/model.rb
Instance Attribute Summary collapse
-
#sync_default_scope ⇒ Object
Returns the value of attribute sync_default_scope.
-
#sync_scope_definitions ⇒ Object
Returns the value of attribute sync_scope_definitions.
-
#sync_touches ⇒ Object
Returns the value of attribute sync_touches.
Instance Method Summary collapse
-
#sync(*actions) ⇒ Object
Set up automatic syncing of partials when a record of this class is created, updated or deleted.
-
#sync_scope(name, lambda) ⇒ Object
Set up a sync scope for the model defining a set of records to be updated via sync.
-
#sync_touch(*args) ⇒ Object
Register one or more associations to be sync’d when this record changes.
Instance Attribute Details
#sync_default_scope ⇒ Object
Returns the value of attribute sync_default_scope.
30 31 32 |
# File 'lib/render_sync/model.rb', line 30 def sync_default_scope @sync_default_scope end |
#sync_scope_definitions ⇒ Object
Returns the value of attribute sync_scope_definitions.
30 31 32 |
# File 'lib/render_sync/model.rb', line 30 def sync_scope_definitions @sync_scope_definitions end |
#sync_touches ⇒ Object
Returns the value of attribute sync_touches.
30 31 32 |
# File 'lib/render_sync/model.rb', line 30 def sync_touches @sync_touches end |
Instance Method Details
#sync(*actions) ⇒ Object
Set up automatic syncing of partials when a record of this class is created, updated or deleted. Be sure to wrap your model actions inside a sync_enable block for sync to do its magic.
36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 |
# File 'lib/render_sync/model.rb', line 36 def sync(*actions) include ModelActions unless include?(ModelActions) include ModelChangeTracking unless include?(ModelChangeTracking) include ModelRenderSyncing if actions.last.is_a? Hash @sync_default_scope = actions.last.fetch :default_scope end actions = [:create, :update, :destroy] if actions.include? :all actions.flatten! if actions.include? :create after_create :prepare_sync_create, if: -> { RenderSync::Model.enabled? } end if actions.include? :update after_update :prepare_sync_update, if: -> { RenderSync::Model.enabled? } end if actions.include? :destroy after_destroy :prepare_sync_destroy, if: -> { RenderSync::Model.enabled? } end end |
#sync_scope(name, lambda) ⇒ Object
Set up a sync scope for the model defining a set of records to be updated via sync
name - The name of the scope lambda - A lambda defining the scope.
Has to return an ActiveRecord::Relation.
You can define the lambda with arguments (see examples). Note that the naming of the parameters is very important. Only use names of methods or ActiveRecord attributes defined on the model (e.g. user_id). This way sync will be able to pass changed records to the lambda and track changes to the scope.
Example:
class Todo < ActiveRecord::Base
belongs_to :user
belongs_to :project
scope :incomplete, -> { where(complete: false) }
sync :all
sync_scope :complete, -> { where(complete: true) }
sync_scope :by_project, ->(project_id) { where(project_id: project_id) }
sync_scope :my_incomplete_todos, ->(user) { incomplete.where(user_id: user.id) }
end
To subscribe to these scopes you would put these lines into your views:
<%= sync partial: "todo", collection: @todos, scope: Todo.complete %>
If the collection you want to render is exactly defined be the given scope the scope can be omitted:
<%= sync partial: "todo", collection: Todo.complete %>
For rendering my_incomplete_todos:
<%= sync partial: "todo", collection: Todo.my_incomplete_todos(current_user) %>
The render_new call has to look like this:
<%= sync_new partial: "todo", resource: Todo.new, scope: Todo.complete %>
Now when a record changes sync will use the names of the lambda parameters (project_id and user), get the corresponding attributes from the record (project_id column or user association) and pass it to the lambda. This way sync can identify if a record has been added or removed from a scope and will then publish the changes to subscribers on all scoped channels.
Beware that chaining of sync scopes in the view is currently not possible. So the following example would raise an exception:
<%= sync_new partial: "todo", Todo.new, scope: Todo.mine(current_user).incomplete %>
To work around this just create an explicit sync_scope for your problem:
sync_scope :my_incomplete_todos, ->(user) { incomplete.mine(current_user) }
And in the view:
<%= sync_new partial: "todo", Todo.new, scope: Todo.my_incomplete_todos(current_user) %>
126 127 128 129 130 131 132 133 134 135 136 |
# File 'lib/render_sync/model.rb', line 126 def sync_scope(name, lambda) if self.respond_to?(name) raise ArgumentError, "invalid scope name '#{name}'. Already defined on #{self.name}" end @sync_scope_definitions[name] = RenderSync::ScopeDefinition.new(self, name, lambda) singleton_class.send(:define_method, name) do |*args| RenderSync::Scope.new_from_args(@sync_scope_definitions[name], args) end end |
#sync_touch(*args) ⇒ Object
Register one or more associations to be sync’d when this record changes.
Example:
class Todo < ActiveRecord::Base
belongs_to :project
belongs_to :user
sync :all
sync_touch :project, :user
end
150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 |
# File 'lib/render_sync/model.rb', line 150 def sync_touch(*args) # Only load Modules and set up callbacks if sync_touch wasn't # called before if @sync_touches.blank? include ModelActions unless include?(ModelActions) include ModelChangeTracking unless include?(ModelChangeTracking) include ModelTouching @sync_touches ||= [] after_create :prepare_sync_touches, if: -> { RenderSync::Model.enabled? } after_update :prepare_sync_touches, if: -> { RenderSync::Model.enabled? } after_destroy :prepare_sync_touches, if: -> { RenderSync::Model.enabled? } end = args. args.each do |arg| @sync_touches.push(arg) end end |