friendis 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: 80e47954eaed926ce7a99b5df712e2987fde5d3e
4
+ data.tar.gz: c31a0bbbd24c01eea567cee59838e2c686dee86b
5
+ SHA512:
6
+ metadata.gz: 42192b191c3d689ddb376fc21c008abd3b17f0933f7b65f696e6f959f94c60f5671cd51a00130e172a82a29382958bffd7782f249642e9d54ccd5f2f12a78bbf
7
+ data.tar.gz: 8c1fd15605d81f5f1c0d3b3f844f016d7be6c6191a188c6bfd6ad965750417ae60e3dde64b973f1c09c0d730e3e3ff6401441a56462e0a11e725eeee80af4f05
data/.gitignore ADDED
@@ -0,0 +1,17 @@
1
+ *.gem
2
+ *.rbc
3
+ .bundle
4
+ .config
5
+ .yardoc
6
+ Gemfile.lock
7
+ InstalledFiles
8
+ _yardoc
9
+ coverage
10
+ doc/
11
+ lib/bundler/man
12
+ pkg
13
+ rdoc
14
+ spec/reports
15
+ test/tmp
16
+ test/version_tmp
17
+ tmp
data/.rspec ADDED
@@ -0,0 +1,2 @@
1
+ --color
2
+ --format documentation
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in friendis.gemspec
4
+ gemspec
data/LICENSE.txt ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2014 Elad Meidar
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,110 @@
1
+ # Friendis
2
+
3
+ TODO: Write a gem description
4
+
5
+ ## Installation
6
+
7
+ Add this line to your application's Gemfile:
8
+
9
+ gem 'friendis'
10
+
11
+ And then execute:
12
+
13
+ $ bundle
14
+
15
+ Or install it yourself as:
16
+
17
+ $ gem install friendis
18
+
19
+ ## Usage
20
+
21
+ ### Configuration
22
+
23
+ create an initializer in `config/initializers/friendis.rb`:
24
+
25
+ Friendis.configure do |c|
26
+ #...
27
+ end
28
+
29
+ The following options exist:
30
+
31
+ * redis_connection: an existing Redis connection, defaults to a `Redis.new` instance.
32
+
33
+ ### Adding to a Model
34
+
35
+ All you need to do is to include the `Friendable` module:
36
+
37
+ include Friendis::Friendable
38
+
39
+ and to choose which attributes or methods will be cached in Redis for that user:
40
+
41
+ friend_this track: [:name, :picture]
42
+
43
+ Those fields will be changed in Redis after everytime you save the instance, note that
44
+ your ORM needs to implement `after_save` and `after_destroy` since Friendis utilizes those callbacks to update and remove
45
+ the cached data from Redis.
46
+
47
+ The `id` attribute will automatically be cached.
48
+
49
+
50
+ ## Examples
51
+
52
+ class User < ActiveRecord::Base
53
+ include Friendis::Friendable
54
+
55
+ friend_this track: [:name, :picture]
56
+ end
57
+
58
+ ### Friend Requests
59
+
60
+ @user1 = User.create(name: "Elad Meidar", picture: "http://picturez.com/elad.jpg")
61
+ @user2 = User.create(name: "Miki Bergin", picture: "http://picturez.com/miki.jpg")
62
+
63
+ @user1.send_friend_request(@user2)
64
+
65
+ ### Pending Friend Request
66
+
67
+ @user2.pending_friend_requests
68
+
69
+ `pending_friend_requests` will return the cached attributes for the pending friend requests, in this case
70
+
71
+ [{"name" => "Elad Meidar", "picture" => "http://picturez.com/elad.jpg", "id" => 1}]
72
+
73
+ ### Sent Friend Request
74
+
75
+ @user2.sent_friend_requests
76
+
77
+ `sent_friend_requests` will return the cached attributes for the sent friend requests, in this case
78
+
79
+ [{"name" => "Miki Bergin", "picture" => "http://picturez.com/miki.jpg", "id" => 2}]
80
+
81
+ ### Approving Friend Requests
82
+
83
+ @user2.approve_friend_request(@user1)
84
+
85
+ ### Lisiting Friends
86
+
87
+ @user1.friends
88
+
89
+ `friends` will return the cached attributes of the currently approved friends, in this case
90
+
91
+ [{"name" => "Miki Bergin", "picture" => "http://picturez.com/miki.jpg", "id" => 2}]
92
+
93
+
94
+ ### Check Friendship
95
+
96
+ @user1.is_friends_with?(@user2) #= true
97
+ @user1.is_friends_with?(@user3) #= false
98
+
99
+ ### Unfriend
100
+
101
+ @user1.unfriend(@user2)
102
+
103
+
104
+ ## Contributing
105
+
106
+ 1. Fork it ( http://github.com/<my-github-username>/friendis/fork )
107
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
108
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
109
+ 4. Push to the branch (`git push origin my-new-feature`)
110
+ 5. Create new Pull Request
data/Rakefile ADDED
@@ -0,0 +1 @@
1
+ require "bundler/gem_tasks"
data/friendis.gemspec ADDED
@@ -0,0 +1,25 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'friendis/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = "friendis"
8
+ spec.version = Friendis::VERSION
9
+ spec.authors = ["Elad Meidar"]
10
+ spec.email = ["elad@eizesus.com"]
11
+ spec.summary = "Friendis implements friendship relationship between objects on Redis"
12
+ spec.description = "Friendis keeps all your friends close by!"
13
+ spec.homepage = ""
14
+ spec.license = "MIT"
15
+
16
+ spec.files = `git ls-files -z`.split("\x0")
17
+ spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
18
+ spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
19
+ spec.require_paths = ["lib"]
20
+
21
+ spec.add_development_dependency "bundler", "~> 1.5"
22
+ spec.add_development_dependency "rake"
23
+ spec.add_development_dependency "rspec"
24
+ spec.add_dependency 'redis'
25
+ end
@@ -0,0 +1,6 @@
1
+ module Friendis
2
+ class Configuration
3
+ attr_accessor :redis_connection
4
+
5
+ end
6
+ end
@@ -0,0 +1,127 @@
1
+ module Friendis
2
+ module Friendable
3
+ def self.included(base)
4
+ base.class_eval do
5
+
6
+ include InstanceMethods
7
+ extend ClassMethods
8
+
9
+ after_save :_update_friendis_meta_data
10
+ after_destroy :clear_friendis_data
11
+
12
+ @friendis_fields
13
+ end
14
+
15
+ end
16
+
17
+ module ClassMethods
18
+
19
+ # Mark the list of fields to track in redis for fast access.
20
+ def friend_this(options = {})
21
+ configuration = {
22
+ track: [:id]
23
+ }.merge(options)
24
+ configuration[:track] << :id
25
+ self.friendis_fields = configuration[:track]
26
+ end
27
+
28
+ # Set trackable fields
29
+ def friendis_fields=(new_field_list)
30
+ @friendis_fields = new_field_list
31
+ end
32
+
33
+ # Retrieve trackable fields
34
+ def friendis_fields
35
+ @friendis_fields ||= []
36
+ end
37
+
38
+ end
39
+
40
+ module InstanceMethods
41
+
42
+
43
+
44
+ def get_friendis_meta(uuid = nil)
45
+ Friendis.redis.hgetall friendis_meta_key(uuid)
46
+ end
47
+
48
+ def send_friend_request(friend)
49
+ Friendis.redis.multi do
50
+ Friendis.redis.sadd friendis_outgoing_friend_requests_key, friend.id.to_s
51
+ Friendis.redis.sadd friend.friendis_incoming_friend_requests_key, self.id.to_s
52
+ end
53
+ end
54
+
55
+ def approve_friend_request(friend)
56
+ if !(Friendis.redis.sismember(friendis_incoming_friend_requests_key, friend.id.to_s))
57
+ return false
58
+ else
59
+ Friendis.redis.multi do
60
+ Friendis.redis.srem friend.friendis_outgoing_friend_requests_key, self.id.to_s
61
+ Friendis.redis.srem friendis_incoming_friend_requests_key, friend.id.to_s
62
+ Friendis.redis.sadd friendis_my_friends_key, friend.id.to_s
63
+ Friendis.redis.sadd friend.friendis_my_friends_key, self.id.to_s
64
+ end
65
+ return true
66
+ end
67
+ end
68
+
69
+ def unfriend(friend)
70
+ Friendis.redis.multi do
71
+ Friendis.redis.srem friendis_my_friends_key, friend.id
72
+ Friendis.redis.srem friend.friendis_my_friends_key, self.id
73
+ end
74
+ end
75
+
76
+ def friends
77
+ Friendis.redis.smembers(friendis_my_friends_key).collect {|friend_id| get_friendis_meta(friend_id)}
78
+ end
79
+
80
+ def is_friends_with?(friend)
81
+ Friendis.redis.sismember friendis_my_friends_key, friend.id.to_s
82
+ end
83
+
84
+ def pending_friend_requests
85
+ Friendis.redis.smembers(friendis_incoming_friend_requests_key).collect {|friend_id| get_friendis_meta(friend_id)}
86
+ end
87
+
88
+ def sent_friend_requests
89
+ Friendis.redis.smembers(friendis_outgoing_friend_requests_key).collect {|friend_id| get_friendis_meta(friend_id)}
90
+ end
91
+
92
+ def clear_friendis_data
93
+ [friendis_meta_key, friendis_my_friends_key, friendis_incoming_friend_requests_key, friendis_outgoing_friend_requests_key].each do |friendis_key|
94
+ Friendis.redis.del friendis_key
95
+ end
96
+ end
97
+
98
+ def _update_friendis_meta_data
99
+ Friendis.redis.multi do
100
+ attr_hash = {}
101
+
102
+ self.class.friendis_fields.each do |field|
103
+ attr_hash[field] = self.send(field)
104
+ end
105
+ Friendis.redis.hmset friendis_meta_key, *attr_hash.to_a
106
+ end
107
+ true
108
+ end
109
+
110
+ def friendis_meta_key(uuid = nil)
111
+ "#{self.class.name.downcase}:#{uuid || self.id}:friendis_meta"
112
+ end
113
+
114
+ def friendis_my_friends_key
115
+ "#{self.class.name.downcase}:#{self.id}:friends"
116
+ end
117
+
118
+ def friendis_incoming_friend_requests_key
119
+ "#{self.class.name.downcase}:#{self.id}:friend_requests"
120
+ end
121
+
122
+ def friendis_outgoing_friend_requests_key
123
+ "#{self.class.name.downcase}:#{self.id}:requested_friendship"
124
+ end
125
+ end
126
+ end
127
+ end
@@ -0,0 +1,3 @@
1
+ module Friendis
2
+ VERSION = "0.0.1"
3
+ end
data/lib/friendis.rb ADDED
@@ -0,0 +1,20 @@
1
+ require 'redis'
2
+ require "friendis/version"
3
+ require 'friendis/configuration'
4
+ require 'friendis/friendable'
5
+
6
+ module Friendis
7
+
8
+ attr_reader :configuration
9
+
10
+ def self.configure(&block)
11
+ @configuration = Friendis::Configuration.new
12
+ yield(@configuration)
13
+ end
14
+
15
+ def self.redis
16
+ @configuration.redis_connection ||= Redis.new
17
+ end
18
+
19
+ # Your code goes here...
20
+ end
@@ -0,0 +1,22 @@
1
+ require 'spec_helper'
2
+
3
+ describe Friendis do
4
+
5
+ describe '#configure' do
6
+
7
+ it "should respond to #configure" do
8
+ Friendis.should respond_to(:configure)
9
+ end
10
+ end
11
+
12
+ describe "#redis" do
13
+ it "should return a default connection if no redis connection specified in configuration" do
14
+ Friendis.configure do |c|
15
+ c.redis_connection = nil
16
+ end
17
+ Friendis.redis.should_not be_nil
18
+ end
19
+
20
+ end
21
+
22
+ end
@@ -0,0 +1,16 @@
1
+ require 'spec_helper.rb'
2
+
3
+ describe Friendis::Configuration do
4
+
5
+ before(:each) do
6
+ @configuration = Friendis::Configuration.new
7
+ end
8
+
9
+ describe "#redis_connection" do
10
+ it "should have accessors for #redis_connection" do
11
+ @configuration.should respond_to(:redis_connection)
12
+ @configuration.should respond_to(:redis_connection=)
13
+ end
14
+ end
15
+
16
+ end
@@ -0,0 +1,95 @@
1
+ require 'spec_helper'
2
+ require 'models/user'
3
+
4
+ describe Friendis::Friendable do
5
+
6
+ describe "#send_friend_request" do
7
+ before(:each) do
8
+ @user1 = User.new(1)
9
+ @user2 = User.new(2)
10
+ @user1.clear_friendis_data
11
+ @user2.clear_friendis_data
12
+
13
+ @user1.save
14
+ @user2.save
15
+ @user1.send_friend_request(@user2)
16
+ end
17
+
18
+ it "should indicate a friend request was sent" do
19
+ @user1.sent_friend_requests.should_not be_empty
20
+ @user1.sent_friend_requests.first["name"].should eq(@user2.name)
21
+ end
22
+
23
+ it "should indicate an incoming friend request" do
24
+ @user2.pending_friend_requests.should_not be_empty
25
+ end
26
+ end
27
+
28
+ describe "#approve_friend_request" do
29
+ before(:each) do
30
+ @user1 = User.new(1)
31
+ @user2 = User.new(2)
32
+ @user1.clear_friendis_data
33
+ @user2.clear_friendis_data
34
+
35
+ @user1.save
36
+ @user2.save
37
+ @user1.send_friend_request(@user2)
38
+ end
39
+
40
+ it "should show friend on friends list after approval" do
41
+ @user2.approve_friend_request(@user1).should be_truthy
42
+ @user2.friends.first["name"].should eq(@user1.name)
43
+ @user1.friends.first["name"].should eq(@user2.name)
44
+ end
45
+ end
46
+
47
+ describe "#unfriend" do
48
+ before(:each) do
49
+ @user1 = User.new(1)
50
+ @user2 = User.new(2)
51
+ @user1.clear_friendis_data
52
+ @user2.clear_friendis_data
53
+
54
+ @user1.save
55
+ @user2.save
56
+ @user1.send_friend_request(@user2)
57
+ @user2.approve_friend_request(@user1)
58
+ end
59
+
60
+ it "should show friend on friends list after approval" do
61
+ @user1.unfriend(@user2).should be_truthy
62
+ @user1.friends.should be_empty
63
+ @user2.friends.should be_empty
64
+ end
65
+ end
66
+
67
+ describe "#is_friends_with?" do
68
+ before(:each) do
69
+ @user1 = User.new(1)
70
+ @user2 = User.new(2)
71
+ @user3 = User.new(3)
72
+
73
+ @user1.clear_friendis_data
74
+ @user2.clear_friendis_data
75
+ @user3.clear_friendis_data
76
+
77
+ @user1.save
78
+ @user2.save
79
+ @user3.save
80
+
81
+ @user1.send_friend_request(@user2)
82
+ @user2.approve_friend_request(@user1)
83
+ end
84
+
85
+ it "should return true if users are friends" do
86
+ @user1.is_friends_with?(@user2).should be_truthy
87
+ end
88
+
89
+ it "should return false if users aren't friends" do
90
+ @user1.is_friends_with?(@user3).should be_falsy
91
+ end
92
+
93
+ end
94
+
95
+ end
@@ -0,0 +1,39 @@
1
+ class User
2
+
3
+ @after_save_method = nil
4
+
5
+ def User.after_save(method)
6
+ @after_save_method = method
7
+ end
8
+
9
+ def User.after_destroy(method)
10
+ end
11
+
12
+ include Friendis::Friendable
13
+
14
+ attr_accessor :id, :name, :picture
15
+
16
+
17
+
18
+ friend_this track: [:name, :picture]
19
+
20
+
21
+
22
+ def User.after_save_method
23
+ @after_save_method
24
+ end
25
+
26
+ def initialize(id)
27
+ @id = id
28
+ @name = "Test #{rand(9000)+ 1000}"
29
+ @picture = "http:/picturez.com/user/#{id}.jpg"
30
+ end
31
+
32
+ def save
33
+ self.send(User.after_save_method)
34
+ end
35
+
36
+ def after_save(method)
37
+
38
+ end
39
+ end
@@ -0,0 +1,10 @@
1
+ require 'bundler/setup'
2
+ Bundler.setup
3
+
4
+ require 'friendis' # and any other gems you need
5
+
6
+ RSpec.configure do |config|
7
+ config.expect_with :rspec do |c|
8
+ c.syntax = :should
9
+ end
10
+ end
metadata ADDED
@@ -0,0 +1,121 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: friendis
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ platform: ruby
6
+ authors:
7
+ - Elad Meidar
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2014-07-27 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: bundler
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ~>
18
+ - !ruby/object:Gem::Version
19
+ version: '1.5'
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ~>
25
+ - !ruby/object:Gem::Version
26
+ version: '1.5'
27
+ - !ruby/object:Gem::Dependency
28
+ name: rake
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - '>='
32
+ - !ruby/object:Gem::Version
33
+ version: '0'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - '>='
39
+ - !ruby/object:Gem::Version
40
+ version: '0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: rspec
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - '>='
46
+ - !ruby/object:Gem::Version
47
+ version: '0'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - '>='
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
55
+ - !ruby/object:Gem::Dependency
56
+ name: redis
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - '>='
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ type: :runtime
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - '>='
67
+ - !ruby/object:Gem::Version
68
+ version: '0'
69
+ description: Friendis keeps all your friends close by!
70
+ email:
71
+ - elad@eizesus.com
72
+ executables: []
73
+ extensions: []
74
+ extra_rdoc_files: []
75
+ files:
76
+ - .gitignore
77
+ - .rspec
78
+ - Gemfile
79
+ - LICENSE.txt
80
+ - README.md
81
+ - Rakefile
82
+ - friendis.gemspec
83
+ - lib/friendis.rb
84
+ - lib/friendis/configuration.rb
85
+ - lib/friendis/friendable.rb
86
+ - lib/friendis/version.rb
87
+ - spec/friendis_spec.rb
88
+ - spec/lib/configuration_spec.rb
89
+ - spec/lib/friendable_spec.rb
90
+ - spec/models/user.rb
91
+ - spec/spec_helper.rb
92
+ homepage: ''
93
+ licenses:
94
+ - MIT
95
+ metadata: {}
96
+ post_install_message:
97
+ rdoc_options: []
98
+ require_paths:
99
+ - lib
100
+ required_ruby_version: !ruby/object:Gem::Requirement
101
+ requirements:
102
+ - - '>='
103
+ - !ruby/object:Gem::Version
104
+ version: '0'
105
+ required_rubygems_version: !ruby/object:Gem::Requirement
106
+ requirements:
107
+ - - '>='
108
+ - !ruby/object:Gem::Version
109
+ version: '0'
110
+ requirements: []
111
+ rubyforge_project:
112
+ rubygems_version: 2.2.0
113
+ signing_key:
114
+ specification_version: 4
115
+ summary: Friendis implements friendship relationship between objects on Redis
116
+ test_files:
117
+ - spec/friendis_spec.rb
118
+ - spec/lib/configuration_spec.rb
119
+ - spec/lib/friendable_spec.rb
120
+ - spec/models/user.rb
121
+ - spec/spec_helper.rb