tekeya 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.
Files changed (92) hide show
  1. data/.document +0 -0
  2. data/.gitignore +23 -0
  3. data/.rspec +3 -0
  4. data/.yardopts +1 -0
  5. data/Gemfile +39 -0
  6. data/Guardfile +40 -0
  7. data/LICENSE +22 -0
  8. data/README.md +37 -0
  9. data/Rakefile +13 -0
  10. data/TODO.todo +8 -0
  11. data/app/active_record/tekeya/activity.rb +7 -0
  12. data/app/active_record/tekeya/attachment.rb +5 -0
  13. data/app/active_record/tekeya/notification.rb +5 -0
  14. data/app/mongoid/tekeya/activity.rb +9 -0
  15. data/app/mongoid/tekeya/attachment.rb +6 -0
  16. data/app/mongoid/tekeya/notification.rb +10 -0
  17. data/db/migrate/00_create_activities.rb +11 -0
  18. data/db/migrate/01_create_attachments.rb +13 -0
  19. data/db/migrate/02_create_notifications.rb +14 -0
  20. data/lib/tasks/resque_tasks.rake +3 -0
  21. data/lib/tekeya.rb +81 -0
  22. data/lib/tekeya/configuration.rb +48 -0
  23. data/lib/tekeya/entity.rb +432 -0
  24. data/lib/tekeya/entity/group.rb +22 -0
  25. data/lib/tekeya/errors/tekeya_error.rb +11 -0
  26. data/lib/tekeya/errors/tekeya_fatal.rb +11 -0
  27. data/lib/tekeya/errors/tekeya_non_entity.rb +6 -0
  28. data/lib/tekeya/errors/tekeya_non_group.rb +6 -0
  29. data/lib/tekeya/errors/tekeya_relation_already_exists.rb +6 -0
  30. data/lib/tekeya/errors/tekeya_relation_non_existent.rb +6 -0
  31. data/lib/tekeya/feed/activity.rb +101 -0
  32. data/lib/tekeya/feed/activity/feed_item.rb +58 -0
  33. data/lib/tekeya/feed/activity/resque.rb +56 -0
  34. data/lib/tekeya/feed/activity/resque/activity_fanout.rb +61 -0
  35. data/lib/tekeya/feed/activity/resque/delete_activity.rb +43 -0
  36. data/lib/tekeya/feed/activity/resque/feed_copy.rb +34 -0
  37. data/lib/tekeya/feed/activity/resque/untrack_feed.rb +34 -0
  38. data/lib/tekeya/feed/attachable.rb +15 -0
  39. data/lib/tekeya/feed/attachment.rb +19 -0
  40. data/lib/tekeya/feed/notification.rb +93 -0
  41. data/lib/tekeya/railtie.rb +18 -0
  42. data/lib/tekeya/version.rb +3 -0
  43. data/spec/fabricators/attachment_fabricator.rb +3 -0
  44. data/spec/fabricators/group_fabricator.rb +4 -0
  45. data/spec/fabricators/status_fabricator.rb +3 -0
  46. data/spec/fabricators/user_fabricator.rb +3 -0
  47. data/spec/orm/active_record.rb +14 -0
  48. data/spec/orm/mongoid.rb +6 -0
  49. data/spec/rails_app/Rakefile +7 -0
  50. data/spec/rails_app/app/active_record/group.rb +3 -0
  51. data/spec/rails_app/app/active_record/status.rb +3 -0
  52. data/spec/rails_app/app/active_record/user.rb +3 -0
  53. data/spec/rails_app/app/controllers/application_controller.rb +3 -0
  54. data/spec/rails_app/app/helpers/application_helper.rb +2 -0
  55. data/spec/rails_app/app/mongoid/group.rb +6 -0
  56. data/spec/rails_app/app/mongoid/status.rb +6 -0
  57. data/spec/rails_app/app/mongoid/user.rb +7 -0
  58. data/spec/rails_app/app/views/layouts/application.html.erb +14 -0
  59. data/spec/rails_app/config.ru +4 -0
  60. data/spec/rails_app/config/application.rb +35 -0
  61. data/spec/rails_app/config/boot.rb +8 -0
  62. data/spec/rails_app/config/database.yml +21 -0
  63. data/spec/rails_app/config/environment.rb +5 -0
  64. data/spec/rails_app/config/environments/development.rb +18 -0
  65. data/spec/rails_app/config/environments/production.rb +33 -0
  66. data/spec/rails_app/config/environments/test.rb +33 -0
  67. data/spec/rails_app/config/initializers/backtrace_silencers.rb +7 -0
  68. data/spec/rails_app/config/initializers/configure_mongoid.rb +6 -0
  69. data/spec/rails_app/config/initializers/inflections.rb +15 -0
  70. data/spec/rails_app/config/initializers/resque.rb +1 -0
  71. data/spec/rails_app/config/initializers/secret_token.rb +7 -0
  72. data/spec/rails_app/config/locales/en.yml +5 -0
  73. data/spec/rails_app/config/routes.rb +58 -0
  74. data/spec/rails_app/db/migrate/100_create_users.rb +9 -0
  75. data/spec/rails_app/db/migrate/101_create_groups.rb +11 -0
  76. data/spec/rails_app/db/migrate/102_create_statuses.rb +9 -0
  77. data/spec/rails_app/db/seeds.rb +7 -0
  78. data/spec/rails_app/public/404.html +26 -0
  79. data/spec/rails_app/public/422.html +26 -0
  80. data/spec/rails_app/public/500.html +25 -0
  81. data/spec/rails_app/public/favicon.ico +0 -0
  82. data/spec/rails_app/public/index.html +241 -0
  83. data/spec/rails_app/public/robots.txt +5 -0
  84. data/spec/rails_app/script/rails +6 -0
  85. data/spec/spec_helper.rb +78 -0
  86. data/spec/tekeya/activity_spec.rb +170 -0
  87. data/spec/tekeya/entity_spec.rb +158 -0
  88. data/spec/tekeya/notification_spec.rb +49 -0
  89. data/spec/tekeya_helper.rb +7 -0
  90. data/spec/tekeya_spec.rb +51 -0
  91. data/tekeya.gemspec +22 -0
  92. metadata +231 -0
@@ -0,0 +1,15 @@
1
+ module Tekeya
2
+ module Feed
3
+ module Attachable
4
+ extend ActiveSupport::Concern
5
+
6
+ included do
7
+ has_many :attachments, as: :attachable, class_name: "Tekeya::Attachment"
8
+ end
9
+
10
+ def is_tekeya_attachable
11
+ true
12
+ end
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,19 @@
1
+ module Tekeya
2
+ module Feed
3
+ module Attachment
4
+ extend ActiveSupport::Concern
5
+
6
+ included do
7
+ belongs_to :attache, polymorphic: true, autosave: true
8
+ belongs_to :attachable, polymorphic: true, autosave: true
9
+ belongs_to :notification_attache, polymorphic: true, autosave: true
10
+
11
+ include ActiveModel::Serializers::JSON
12
+ end
13
+
14
+ module ClassMethods
15
+ end
16
+
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,93 @@
1
+ module Tekeya
2
+ module Feed
3
+ module Notification
4
+ extend ActiveSupport::Concern
5
+
6
+ included do
7
+ belongs_to :entity, polymorphic: true, autosave: true
8
+ belongs_to :subject, polymorphic: true, autosave: true
9
+ has_many :actors, as: :attache, class_name: 'Tekeya::Attachment'
10
+
11
+ before_create :group_notifications
12
+
13
+ accepts_nested_attributes_for :actors, :subject
14
+
15
+ validates_presence_of :actors
16
+
17
+ attr_writer :group_with_recent
18
+ end
19
+
20
+ module ClassMethods
21
+ def notify!(to_notify, notification_type, subject, *args)
22
+ options = args.extract_options!
23
+ options[:group] = options[:group].nil? ? true : options[:group]
24
+
25
+ actors = []
26
+ args.each do |attachable|
27
+ actors << ::Tekeya::Attachment.new(attachable: attachable)
28
+ end
29
+
30
+ to_notify.each do |entity|
31
+ entity.notifications.create notification_type: notification_type, subject: subject, actors: actors, group_with_recent: options[:group]
32
+ end
33
+ end
34
+ end
35
+
36
+ # Approximates the timestamp to the nearest 15 minutes for grouping activities
37
+ #
38
+ # @param [Datetime] from_time the time to approximate
39
+ # @return [Integer] the timestamp approximated to the nearest 15 minutes
40
+ def score(from_time = nil)
41
+ if from_time.present?
42
+ stamp = from_time.to_i
43
+
44
+ # floors the timestamp to the nearest 15 minute
45
+ return (stamp.to_f / 15.minutes).floor * 15.minutes
46
+ else
47
+ return current_time_from_proper_timezone.to_i
48
+ end
49
+ end
50
+
51
+ # Marks the notification as read
52
+ def read!
53
+ self.update_attribute :read, true
54
+ end
55
+
56
+ # @private
57
+ #
58
+ # returns if the notification should be grouped with similar recent activities
59
+ def group_with_recent
60
+ @group_with_recent.nil? ? true : @group_with_recent
61
+ end
62
+
63
+ private
64
+
65
+ # @private
66
+ # Checks if the notification should be grouped and aborts the creation of a new record
67
+ def group_notifications
68
+ if self.group_with_recent
69
+ self.created_at = current_time_from_proper_timezone
70
+ rel = self.class.where(created_at: self.created_at, notification_type: self.notification_type, entity_id: self.entity_id, entity_type: self.entity_type, subject_id: self.subject_id)
71
+ if rel.count > 0
72
+ notification = rel.first
73
+ notification.actors << self.actors
74
+ self.id = notification.id
75
+ self.reload
76
+ return false
77
+ end
78
+ end
79
+ end
80
+
81
+ # @private
82
+ # Override AR's default created_at calculation formula
83
+ def current_time_from_proper_timezone #:nodoc:
84
+ zone = self.class.respond_to?(:default_timezone) ? self.class.default_timezone : :utc
85
+ ctime = zone == :utc ? Time.now.utc : Time.now
86
+ stamp = ctime.to_i
87
+
88
+ # floors the timestamp to the nearest 15 minute
89
+ return Time.at((stamp.to_f / 15.minutes).floor * 15.minutes)
90
+ end
91
+ end
92
+ end
93
+ end
@@ -0,0 +1,18 @@
1
+ require "tekeya"
2
+ require "rails"
3
+
4
+ module Tekeya
5
+ class Engine < ::Rails::Engine
6
+ engine_name "tekeya"
7
+
8
+ config.before_configuration do
9
+ config.tekeya_orm = ::Tekeya::Configuration.instance.feed_storage_orm
10
+ config.eager_load_paths.reject!{ |p| p =~ /\/app\/(\w+)$/ && !%w(controllers helpers views workers).include?($1) }
11
+ config.autoload_paths += [ "#{config.root}/app/#{config.tekeya_orm}" ]
12
+ end
13
+
14
+ initializer "Configure Tekeya" do
15
+ ::Tekeya::Configuration.instance.setup_databases
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,3 @@
1
+ module Tekeya
2
+ VERSION = "0.0.1"
3
+ end
@@ -0,0 +1,3 @@
1
+ Fabricator :attachment, from: Tekeya::Attachment do
2
+ attachable { Fabricate(:status) }
3
+ end
@@ -0,0 +1,4 @@
1
+ Fabricator(:group) do
2
+ name { Faker::Name.name }
3
+ owner { Fabricate(:user) }
4
+ end
@@ -0,0 +1,3 @@
1
+ Fabricator :status do
2
+ content { Faker::Lorem.sentence }
3
+ end
@@ -0,0 +1,3 @@
1
+ Fabricator(:user) do
2
+ name { Faker::Name.name }
3
+ end
@@ -0,0 +1,14 @@
1
+ ActiveRecord::Migration.verbose = false
2
+ ActiveRecord::Base.logger = Logger.new(nil)
3
+
4
+ ActiveRecord::Migrator.migrate(File.expand_path("../../../db/migrate/", __FILE__))
5
+ puts "Migrating #{File.expand_path("../../../db/migrate/", __FILE__)}"
6
+ ActiveRecord::Migrator.migrate(File.expand_path("../../rails_app/db/migrate/", __FILE__))
7
+ puts "Migrating #{File.expand_path("../../rails_app/db/migrate/", __FILE__)}"
8
+
9
+ RSpec.configure do |config|
10
+ config.before(:suite) do
11
+ DatabaseCleaner.strategy = :truncation
12
+ DatabaseCleaner.orm = "active_record"
13
+ end
14
+ end
@@ -0,0 +1,6 @@
1
+ RSpec.configure do |config|
2
+ config.before(:suite) do
3
+ DatabaseCleaner.strategy = :truncation
4
+ DatabaseCleaner.orm = "mongoid"
5
+ end
6
+ end
@@ -0,0 +1,7 @@
1
+ #!/usr/bin/env rake
2
+ # Add your own tasks in files placed in lib/tasks ending in .rake,
3
+ # for example lib/tasks/capistrano.rake, and they will automatically be available to Rake.
4
+
5
+ require File.expand_path('../config/application', __FILE__)
6
+
7
+ RailsApp::Application.load_tasks
@@ -0,0 +1,3 @@
1
+ class Group < ActiveRecord::Base
2
+ include Tekeya::Entity::Group
3
+ end
@@ -0,0 +1,3 @@
1
+ class Status < ActiveRecord::Base
2
+ include Tekeya::Feed::Attachable
3
+ end
@@ -0,0 +1,3 @@
1
+ class User < ActiveRecord::Base
2
+ include Tekeya::Entity
3
+ end
@@ -0,0 +1,3 @@
1
+ class ApplicationController < ActionController::Base
2
+ protect_from_forgery
3
+ end
@@ -0,0 +1,2 @@
1
+ module ApplicationHelper
2
+ end
@@ -0,0 +1,6 @@
1
+ class Group
2
+ include Mongoid::Document
3
+ include Tekeya::Entity::Group
4
+
5
+ field :name, type: String
6
+ end
@@ -0,0 +1,6 @@
1
+ class Status
2
+ include Mongoid::Document
3
+ include Tekeya::Feed::Attachable
4
+
5
+ field :content, type: String
6
+ end
@@ -0,0 +1,7 @@
1
+ class User
2
+ include Mongoid::Document
3
+ include Mongoid::Timestamps
4
+ include Tekeya::Entity
5
+
6
+ field :name, type: String
7
+ end
@@ -0,0 +1,14 @@
1
+ <!DOCTYPE html>
2
+ <html>
3
+ <head>
4
+ <title>RailsApp</title>
5
+ <%= stylesheet_link_tag "application", :media => "all" %>
6
+ <%= javascript_include_tag "application" %>
7
+ <%= csrf_meta_tags %>
8
+ </head>
9
+ <body>
10
+
11
+ <%= yield %>
12
+
13
+ </body>
14
+ </html>
@@ -0,0 +1,4 @@
1
+ # This file is used by Rack-based servers to start the application.
2
+
3
+ require ::File.expand_path('../config/environment', __FILE__)
4
+ run RailsApp::Application
@@ -0,0 +1,35 @@
1
+ require File.expand_path('../boot', __FILE__)
2
+
3
+ require "action_controller/railtie"
4
+ require "action_mailer/railtie"
5
+ require "active_resource/railtie"
6
+
7
+ Bundler.require :default, :development
8
+
9
+ begin
10
+ require "#{TEKEYA_ORM}/railtie"
11
+ rescue LoadError
12
+ end
13
+
14
+ require "tekeya"
15
+
16
+ module RailsApp
17
+ class Application < Rails::Application
18
+ # Add additional load paths for your own custom dirs
19
+ config.eager_load_paths.reject!{ |p| p =~ /\/app\/(\w+)$/ && !%w(controllers helpers views).include?($1) }
20
+ config.autoload_paths += [ "#{config.root}/app/#{TEKEYA_ORM}" ]
21
+
22
+ # Configure generators values. Many other options are available, be sure to check the documentation.
23
+ # config.generators do |g|
24
+ # g.orm :active_record
25
+ # g.template_engine :erb
26
+ # g.test_framework :test_unit, :fixture => true
27
+ # end
28
+
29
+ # Configure sensitive parameters which will be filtered from the log file.
30
+ config.filter_parameters << :password
31
+ config.assets.enabled = false
32
+
33
+ config.action_mailer.default_url_options = { :host => "localhost:3000" }
34
+ end
35
+ end
@@ -0,0 +1,8 @@
1
+ unless defined?(TEKEYA_ORM)
2
+ TEKEYA_ORM = (ENV["TEKEYA_ORM"] || :active_record).to_sym
3
+ end
4
+
5
+ require 'rubygems'
6
+ require 'bundler/setup'
7
+
8
+ $:.unshift File.expand_path('../../../../lib', __FILE__)
@@ -0,0 +1,21 @@
1
+ # SQLite version 3.x
2
+ # gem install sqlite3
3
+ #
4
+ # Ensure the SQLite 3 gem is defined in your Gemfile
5
+ # gem 'sqlite3'
6
+ development:
7
+ adapter: sqlite3
8
+ database: db/development.sqlite3
9
+ pool: 5
10
+ timeout: 5000
11
+
12
+ # Warning: The database defined as "test" will be erased and
13
+ # re-generated from your development database when you run "rake".
14
+ # Do not set this db to the same as development or production.
15
+ test:
16
+ adapter: sqlite3
17
+ database: db/test.sqlite3
18
+
19
+ production:
20
+ adapter: sqlite3
21
+ database: ":memory:"
@@ -0,0 +1,5 @@
1
+ # Load the rails application
2
+ require File.expand_path('../application', __FILE__)
3
+
4
+ # Initialize the rails application
5
+ RailsApp::Application.initialize!
@@ -0,0 +1,18 @@
1
+ RailsApp::Application.configure do
2
+ # Settings specified here will take precedence over those in config/environment.rb
3
+
4
+ # In the development environment your application's code is reloaded on
5
+ # every request. This slows down response time but is perfect for development
6
+ # since you don't have to restart the webserver when you make code changes.
7
+ config.cache_classes = false
8
+
9
+ # Log error messages when you accidentally call methods on nil.
10
+ config.whiny_nils = true
11
+
12
+ # Show full error reports and disable caching
13
+ config.consider_all_requests_local = true
14
+ config.action_controller.perform_caching = false
15
+
16
+ # Don't care if the mailer can't send
17
+ config.action_mailer.raise_delivery_errors = false
18
+ end
@@ -0,0 +1,33 @@
1
+ RailsApp::Application.configure do
2
+ # Settings specified here will take precedence over those in config/environment.rb
3
+
4
+ # The production environment is meant for finished, "live" apps.
5
+ # Code is not reloaded between requests
6
+ config.cache_classes = true
7
+
8
+ # Full error reports are disabled and caching is turned on
9
+ config.consider_all_requests_local = false
10
+ config.action_controller.perform_caching = true
11
+
12
+ # See everything in the log (default is :info)
13
+ # config.log_level = :debug
14
+
15
+ # Use a different logger for distributed setups
16
+ # config.logger = SyslogLogger.new
17
+
18
+ # Use a different cache store in production
19
+ # config.cache_store = :mem_cache_store
20
+
21
+ # Disable Rails's static asset server
22
+ # In production, Apache or nginx will already do this
23
+ config.serve_static_assets = false
24
+
25
+ # Enable serving of images, stylesheets, and javascripts from an asset server
26
+ # config.action_controller.asset_host = "http://assets.example.com"
27
+
28
+ # Disable delivery errors, bad email addresses will be ignored
29
+ # config.action_mailer.raise_delivery_errors = false
30
+
31
+ # Enable threaded mode
32
+ # config.threadsafe!
33
+ end
@@ -0,0 +1,33 @@
1
+ RailsApp::Application.configure do
2
+ # Settings specified here will take precedence over those in config/environment.rb
3
+
4
+ # The test environment is used exclusively to run your application's
5
+ # test suite. You never need to work with it otherwise. Remember that
6
+ # your test database is "scratch space" for the test suite and is wiped
7
+ # and recreated between test runs. Don't rely on the data there!
8
+ config.cache_classes = true
9
+
10
+ # Log error messages when you accidentally call methods on nil.
11
+ config.whiny_nils = true
12
+
13
+ # Show full error reports and disable caching
14
+ config.consider_all_requests_local = true
15
+ config.action_controller.perform_caching = false
16
+
17
+ # Disable request forgery protection in test environment
18
+ config.action_controller.allow_forgery_protection = false
19
+
20
+ # Tell Action Mailer not to deliver emails to the real world.
21
+ # The :test delivery method accumulates sent emails in the
22
+ # ActionMailer::Base.deliveries array.
23
+ config.action_mailer.delivery_method = :test
24
+
25
+ # Use SQL instead of Active Record's schema dumper when creating the test database.
26
+ # This is necessary if your schema can't be completely dumped by the schema dumper,
27
+ # like if you have constraints or database-specific column types
28
+ # config.active_record.schema_format = :sql
29
+
30
+ config.action_dispatch.show_exceptions = false
31
+
32
+ config.active_support.deprecation = :stderr
33
+ end
@@ -0,0 +1,7 @@
1
+ # Be sure to restart your server when you modify this file.
2
+
3
+ # You can add backtrace silencers for libraries that you're using but don't wish to see in your backtraces.
4
+ # Rails.backtrace_cleaner.add_silencer { |line| line =~ /my_noisy_library/ }
5
+
6
+ # You can also remove all the silencers if you're trying to debug a problem that might stem from framework code.
7
+ # Rails.backtrace_cleaner.remove_silencers!