model_updates 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.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 526e7e7db14d2a876ff88a99ae866fa13134fa7a
4
+ data.tar.gz: c589e3b8d720c13ae377b0592d4798f61ac0dd00
5
+ SHA512:
6
+ metadata.gz: 46cd8b93ea8e032210048db5b961d5e6d86048a2473e1e5c5647ecc0f39e491bf8c2ce4ef239f60537dee0982e44b20ab2f5dc72748e410d7cac72648e558623
7
+ data.tar.gz: 406ddae50931f9a9d8ac38e4f80844582975de5685d4f86eb50fadf37fd04c4ffe9d4f154d7824eeea1fc14167b5649ef262403f76b63d9b04af3546b601b5db
data/MIT-LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ Copyright 2017 kaspernj
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.md ADDED
@@ -0,0 +1,73 @@
1
+ # ModelUpdates
2
+
3
+ Rails gem to push updates to models into the frontend through ActionCable.
4
+
5
+
6
+ ## Installation
7
+ Add this line to your application's Gemfile:
8
+
9
+ ```ruby
10
+ gem 'model_updates'
11
+ ```
12
+
13
+ And then execute:
14
+ ```bash
15
+ $ bundle
16
+ ```
17
+
18
+ Or install it yourself as:
19
+ ```bash
20
+ $ gem install model_updates
21
+ ```
22
+
23
+
24
+ ## Usage
25
+
26
+ Include it in your JavaScript:
27
+
28
+ ```javascript
29
+ //= require model_updates
30
+ ```
31
+
32
+ Include the helper in your models:
33
+
34
+ ```ruby
35
+ class ApplicationRecord < ActiveRecord::Base
36
+ include ModelUpdates::ModelExtensions
37
+ end
38
+ ```
39
+
40
+ Choose which attributes should be broadcasted automatically:
41
+
42
+ ```ruby
43
+ class Model < ApplicationRecord
44
+ model_updates_broadcast_attributes attributes: [:updated_at]
45
+ end
46
+ ```
47
+
48
+ Do like this in your views if you are using HAML:
49
+
50
+ ```haml
51
+ .model-updates{data: {model_updates: model.model_updates_data_attrs(:updated_at)}}
52
+ = model.updated_at
53
+ ```
54
+
55
+ Or like this in ERB:
56
+
57
+ ```erb
58
+ <div class="model-updates" data-model-updates-model="Model" data-model-updates-id="1" data-model-updates-key="updated_at">
59
+ <%= model.updated_at %>
60
+ </div>
61
+ ```
62
+
63
+ Now that element should update automatically when the model is changed
64
+
65
+
66
+ ## Contributing
67
+
68
+ Contribution directions go here.
69
+
70
+
71
+ ## License
72
+
73
+ The gem is available as open source under the terms of the [MIT License](http://opensource.org/licenses/MIT).
data/Rakefile ADDED
@@ -0,0 +1,26 @@
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
+ require "rdoc/task"
8
+
9
+ RDoc::Task.new(:rdoc) do |rdoc|
10
+ rdoc.rdoc_dir = "rdoc"
11
+ rdoc.title = "ModelUpdates"
12
+ rdoc.options << "--line-numbers"
13
+ rdoc.rdoc_files.include("README.md")
14
+ rdoc.rdoc_files.include("lib/**/*.rb")
15
+ end
16
+
17
+ APP_RAKEFILE = File.expand_path("../spec/dummy/Rakefile", __FILE__)
18
+ load "rails/tasks/engine.rake"
19
+ load "rails/tasks/statistics.rake"
20
+
21
+ require "bundler/gem_tasks"
22
+
23
+ if Rails.env.development? || Rails.env.test?
24
+ require "best_practice_project"
25
+ BestPracticeProject.load_tasks
26
+ end
@@ -0,0 +1,2 @@
1
+ //= link_directory ../javascripts/model_updates .js
2
+ //= link_directory ../stylesheets/model_updates .css
@@ -0,0 +1,45 @@
1
+ $(document).ready(function() {
2
+ // Find all models that should be subscribed to
3
+ model_subscriptions = {}
4
+
5
+ $(".model-updates").each(function() {
6
+ model_type = $(this).data("model-updates-model")
7
+ model_id = $(this).data("model-updates-id")
8
+
9
+ if (!model_subscriptions[model_type])
10
+ model_subscriptions[model_type] = {}
11
+
12
+ model_subscriptions[model_type][model_id] = {}
13
+ })
14
+
15
+ // Subscribe to the found models
16
+ for(var model_type in model_subscriptions) {
17
+ for(var model_id in model_subscriptions[model_type]) {
18
+ App.cable.subscriptions.create(
19
+ {channel: "ModelUpdates::ModelChannel", id: model_id, model: model_type},
20
+ {
21
+ received: function(json) {
22
+ for(key in json.changes) {
23
+ element = $(".model-updates[data-model-updates-model='" + json.model + "'][data-model-updates-id='" + json.id + "'][data-model-updates-key='" + key + "']")
24
+
25
+ if (element.data("model-updates-callback")) {
26
+ function_to_call = element.data("model-updates-callback")
27
+
28
+ window[function_to_call]({
29
+ changes: json.changes,
30
+ element: element,
31
+ id: json.id,
32
+ key: key,
33
+ model: json.model,
34
+ value: json.changes[key]
35
+ })
36
+ } else {
37
+ element.text(json.changes[key])
38
+ }
39
+ }
40
+ }
41
+ }
42
+ )
43
+ }
44
+ }
45
+ })
@@ -0,0 +1,3 @@
1
+ function model_updates_date_time_formatter(data) {
2
+ element.text(moment(data.value).format("LLLL"))
3
+ }
@@ -0,0 +1,2 @@
1
+ //= require model_updates/activate_elements
2
+ //= require model_updates/formatters
@@ -0,0 +1,15 @@
1
+ /*
2
+ * This is a manifest file that'll be compiled into application.css, which will include all the files
3
+ * listed below.
4
+ *
5
+ * Any CSS and SCSS file within this directory, lib/assets/stylesheets, vendor/assets/stylesheets,
6
+ * or any plugin's vendor/assets/stylesheets directory can be referenced here using a relative path.
7
+ *
8
+ * You're free to add application-wide styles to this file and they'll appear at the bottom of the
9
+ * compiled file so the styles you add here take precedence over styles defined in any other CSS/SCSS
10
+ * files in this directory. Styles in this file should be added after the last require_* statement.
11
+ * It is generally better to create a new file per style scope.
12
+ *
13
+ *= require_tree .
14
+ *= require_self
15
+ */
@@ -0,0 +1,6 @@
1
+ class ModelUpdates::ModelChannel < ApplicationCable::Channel
2
+ def subscribed
3
+ model = params[:model].constantize.find(params[:id])
4
+ stream_for model
5
+ end
6
+ end
@@ -0,0 +1,5 @@
1
+ module ModelUpdates; end
2
+
3
+ class ModelUpdates::ApplicationController < ActionController::Base
4
+ protect_from_forgery with: :exception
5
+ end
@@ -0,0 +1,2 @@
1
+ module ModelUpdates::ApplicationHelper
2
+ end
@@ -0,0 +1,2 @@
1
+ class ModelUpdates::ApplicationJob < ActiveJob::Base
2
+ end
@@ -0,0 +1,4 @@
1
+ class ModelUpdates::ApplicationMailer < ActionMailer::Base
2
+ default from: "from@example.com"
3
+ layout "mailer"
4
+ end
@@ -0,0 +1,3 @@
1
+ class ModelUpdates::ApplicationRecord < ActiveRecord::Base
2
+ self.abstract_class = true
3
+ end
@@ -0,0 +1,14 @@
1
+ <!DOCTYPE html>
2
+ <html>
3
+ <head>
4
+ <title>Model updates</title>
5
+ <%= stylesheet_link_tag "model_updates/application", media: "all" %>
6
+ <%= javascript_include_tag "model_updates/application" %>
7
+ <%= csrf_meta_tags %>
8
+ </head>
9
+ <body>
10
+
11
+ <%= yield %>
12
+
13
+ </body>
14
+ </html>
data/config/routes.rb ADDED
@@ -0,0 +1,2 @@
1
+ ModelUpdates::Engine.routes.draw do
2
+ end
@@ -0,0 +1,23 @@
1
+ class ModuleUpdates::AttributeGenerator
2
+ def self.generate(args)
3
+ data_attributes = {
4
+ "model-updates-id" => args.fetch(:model).id,
5
+ "model-updates-key" => args.fetch(:key),
6
+ "model-updates-model" => args.fetch(:model).class.name
7
+ }
8
+
9
+ data_attributes.merge!(args.fetch(:attributes)) if args[:attributes]
10
+ data_attributes
11
+ end
12
+
13
+ def self.short(args)
14
+ data_attributes = {
15
+ "id" => args.fetch(:model).id,
16
+ "key" => args.fetch(:key),
17
+ "model" => args.fetch(:model).class.name
18
+ }
19
+
20
+ data_attributes.merge!(args.fetch(:attributes)) if args[:attributes]
21
+ data_attributes
22
+ end
23
+ end
@@ -0,0 +1,3 @@
1
+ class ModelUpdates::Engine < ::Rails::Engine
2
+ isolate_namespace ModelUpdates
3
+ end
@@ -0,0 +1,36 @@
1
+ module ModelUpdates::ModelExtensions
2
+ def self.included(base)
3
+ base.extend(ClassMethods)
4
+ end
5
+
6
+ module ClassMethods
7
+ def model_updates_broadcast_attributes(args)
8
+ after_save do
9
+ changes = {}
10
+
11
+ args.fetch(:attributes).each do |attribute_name|
12
+ method_changed = "saved_change_to_#{attribute_name}?"
13
+ next unless __send__(method_changed)
14
+ changes[attribute_name] = __send__(attribute_name)
15
+ end
16
+
17
+ if changes.any?
18
+ ModelUpdates::ModelChannel.broadcast_to(
19
+ self,
20
+ id: id,
21
+ model: self.class.name,
22
+ changes: changes
23
+ )
24
+ end
25
+ end
26
+ end
27
+ end
28
+
29
+ def model_updates_data_attrs(key, more = {})
30
+ {
31
+ id: id,
32
+ model: self.class.name,
33
+ key: key
34
+ }.merge(more)
35
+ end
36
+ end
@@ -0,0 +1,3 @@
1
+ module ModelUpdates
2
+ VERSION = "0.0.1".freeze
3
+ end
@@ -0,0 +1,8 @@
1
+ require "model_updates/engine"
2
+
3
+ module ModelUpdates
4
+ path = "#{File.dirname(__FILE__)}/model_updates"
5
+
6
+ autoload :AttributeGenerator, "#{path}/attribute_generator"
7
+ autoload :ModelExtensions, "#{path}/model_extensions"
8
+ end
@@ -0,0 +1,4 @@
1
+ # desc "Explaining what the task does"
2
+ # task :model_updates do
3
+ # # Task goes here
4
+ # end
metadata ADDED
@@ -0,0 +1,80 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: model_updates
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ platform: ruby
6
+ authors:
7
+ - kaspernj
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2017-05-24 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: rails
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ">="
18
+ - !ruby/object:Gem::Version
19
+ version: 5.0.0
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ">="
25
+ - !ruby/object:Gem::Version
26
+ version: 5.0.0
27
+ description: Rails gem to push updates to models into the frontend through ActionCable
28
+ email:
29
+ - kaspernj@gmail.com
30
+ executables: []
31
+ extensions: []
32
+ extra_rdoc_files: []
33
+ files:
34
+ - MIT-LICENSE
35
+ - README.md
36
+ - Rakefile
37
+ - app/assets/config/model_updates_manifest.js
38
+ - app/assets/javascripts/model_updates.js
39
+ - app/assets/javascripts/model_updates/activate_elements.js
40
+ - app/assets/javascripts/model_updates/formatters.js
41
+ - app/assets/stylesheets/model_updates/application.css
42
+ - app/channels/model_updates/model_channel.rb
43
+ - app/controllers/model_updates/application_controller.rb
44
+ - app/helpers/model_updates/application_helper.rb
45
+ - app/jobs/model_updates/application_job.rb
46
+ - app/mailers/model_updates/application_mailer.rb
47
+ - app/models/model_updates/application_record.rb
48
+ - app/views/layouts/model_updates/application.html.erb
49
+ - config/routes.rb
50
+ - lib/model_updates.rb
51
+ - lib/model_updates/attribute_generator.rb
52
+ - lib/model_updates/engine.rb
53
+ - lib/model_updates/model_extensions.rb
54
+ - lib/model_updates/version.rb
55
+ - lib/tasks/model_updates_tasks.rake
56
+ homepage: https://github.com/kaspernj/model_updates
57
+ licenses:
58
+ - MIT
59
+ metadata: {}
60
+ post_install_message:
61
+ rdoc_options: []
62
+ require_paths:
63
+ - lib
64
+ required_ruby_version: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - ">="
67
+ - !ruby/object:Gem::Version
68
+ version: '0'
69
+ required_rubygems_version: !ruby/object:Gem::Requirement
70
+ requirements:
71
+ - - ">="
72
+ - !ruby/object:Gem::Version
73
+ version: '0'
74
+ requirements: []
75
+ rubyforge_project:
76
+ rubygems_version: 2.6.8
77
+ signing_key:
78
+ specification_version: 4
79
+ summary: Rails gem to push updates to models into the frontend through ActionCable
80
+ test_files: []