redis-friendships 0.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,3 @@
1
+ 0.1 (January 25, 2010)
2
+ Doing initial Redis friendship generator, will be a swift move to 1.0
3
+ Tests are done, but need refactoring. Need to make banners/descriptions to the generators
data/Gemfile ADDED
@@ -0,0 +1,2 @@
1
+ source "http://rubygems.org"
2
+ gemspec
data/LICENSE ADDED
@@ -0,0 +1,23 @@
1
+ Copyright (c) 2010 Seivan Heidari
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.
21
+ By reading this fine print your soul is now the exclusive property of WeDoBDD Productions and its Subsidiaries.
22
+ Unauthorized use of seivan gems, images, materials, souls, odors and oxygen is strongly discouraged. We know where you sleep.
23
+ Also, your mum & bring back prop8
@@ -0,0 +1,51 @@
1
+ == What is redis-friendship
2
+ A friendship library with a certain follower/following system utilizing the power of both Redis and SQL. Using SQL for the users and Redis for the followers and the followings. Redis uses sets of usernames for both your followers and followings. And can be used to retrieve more information about your e.g. followers from SQL with those unique usernames.
3
+
4
+ == Install
5
+
6
+ gem install redis-friendships
7
+
8
+ == Rails 3
9
+
10
+ To use redis-friendships with Rails 3 you will need to include it in your Gemfile.
11
+
12
+ group :development do
13
+ gem "redis-friendships"
14
+ end
15
+
16
+ == Usage
17
+ * rails g redis_friendships : Will name the models User and Friendship and the Redis constant to R
18
+
19
+ * rails g redis_friendships fellowship user : Assuming the User model already exist, this will inject code into it and create a Fellowship model
20
+
21
+ * rails g redis_friendships fellowship hobbit Red : Creates the models Fellowship and Hobbit and name the Redis constant to Red
22
+
23
+ * And don't forget to run your migrations since we also utilize SQL here, the user model will be SQL - anything else would be stupid, right?
24
+
25
+ == Code
26
+ == READ
27
+ Assuming we use standard naming the user model will have two lookup scopes
28
+ The first two are
29
+ user.followers and user.followings
30
+ Where we do a SQL lookup with the list of usernames from the SET to get a list of user objects
31
+
32
+ If you don't want the user objects but just their (unique) usernames
33
+ Friendship.followings_for(username)
34
+ Friendship.followers_for(username)
35
+
36
+ == WRITE
37
+ To follow someone you just need to call
38
+ user.follow!(other_user)
39
+ This will just push the username into a SET.
40
+ It will also make that user a following to the other_user_
41
+ other_user.followings.include? user
42
+
43
+ To unfollow someone (or have someone unfollowed, just edit it to your hearts desire)
44
+ user.stop_following!(other_user)
45
+ This will remove it from user's SET. There are no limits to what you can do.
46
+ Will also remove the user as a following from other_user
47
+ other_user.followings.include?(user) == false
48
+
49
+ PS
50
+ You can also alter the methods to auto follow new followers or have requests before being stalked
51
+ DS
@@ -0,0 +1,10 @@
1
+ require 'rubygems'
2
+ require 'rake'
3
+ require 'cucumber'
4
+ require 'cucumber/rake/task'
5
+
6
+ Cucumber::Rake::Task.new(:features) do |t|
7
+ t.cucumber_opts = "features --format progress"
8
+ end
9
+
10
+ task :default => :features
@@ -0,0 +1,60 @@
1
+ Feature: Redis Friendships Generator With Named Models
2
+ In order to send befriend people
3
+ As a rails developer
4
+ I want to generate a fellowship library using fellowship as a name and hobbits as users
5
+
6
+
7
+ Scenario: Generate named messages
8
+ Given a new Rails app
9
+ When I run "rails g redis_friendships fellowships hobbit Red"
10
+ Then I should see the following files
11
+ | app/models/fellowship.rb |
12
+ And I should see "class Fellowship" in file "app/models/fellowship.rb"
13
+
14
+ And I should see "def self.follow!(username, followed_username)" in file "app/models/fellowship.rb"
15
+ And I should see "Red.sadd("fellowship:#{username}:followings", followed_username)" in file "app/models/fellowship.rb"
16
+ And I should see "Red.sadd("fellowship:#{followed_username}:followings", username)" in file "app/models/fellowship.rb"
17
+
18
+ And I should see "def self.stop_following!(username, followed_username)" in file "app/models/fellowship.rb"
19
+ And I should see "Red.srem("fellowship:#{username}:followings", followed_username)" in file "app/models/fellowship.rb"
20
+ And I should see "Red.srem("fellowship:#{followed_username}:followings", username)" in file "app/models/fellowship.rb"
21
+
22
+ And I should see "def self.follows?(username, followed_username)" in file "app/models/fellowship.rb"
23
+ And I should see "Red.sismember("fellowship:#{username}:followings", followed_username)" in file "app/models/fellowship.rb"
24
+
25
+ And I should see "def self.followed_by?(user, following_user)" in file "app/models/fellowship.rb"
26
+ And I should see "Red.sismember("fellowship:#{username}:followers", following_username)" in file "app/models/fellowship.rb"
27
+
28
+ And I should see "def self.followings_for(username)" in file "app/models/fellowship.rb"
29
+ And I should see "Red.smembers("fellowship:#{username}:followings")" in file "app/models/fellowship.rb"
30
+
31
+ And I should see "def self.followers_for(username)" in file "app/models/fellowship.rb"
32
+ And I should see "Red.smembers("fellowship:#{username}:followers")" in file "app/models/fellowship.rb"
33
+
34
+ And I should see the following files
35
+ |app/models/hobbit.rb|
36
+ And I should see "class Hobbit < ActiveRecord::Base" in file "app/models/hobbit.rb"
37
+
38
+ And I should see "def followed_by?(user)" in file "app/models/hobbit.rb"
39
+ And I should see "Fellowship.followed_by?(self.username, user.username)" in file "app/models/hobbit.rb"
40
+
41
+ And I should see "def follows?(user)" in file "app/models/hobbit.rb"
42
+ And I should see "Fellowship.follows?(self.username, user.username)" in file "app/models/hobbit.rb"
43
+
44
+ And I should see "def follow!(user)" in file "app/models/hobbit.rb"
45
+ And I should see "return false if self.username == user.username" in file "app/models/hobbit.rb"
46
+ And I should see "Fellowship.follow!(self.username, user.username)" in file "app/models/hobbit.rb"
47
+ And I should see "true" in file "app/models/hobbit.rb"
48
+
49
+ And I should see "def stop_following!(user)" in file "app/models/hobbit.rb"
50
+ And I should see "Fellowship.stop_following!(self.username, user.username)" in file "app/models/hobbit.rb"
51
+
52
+ And I should see "def followers" in file "app/models/hobbit.rb"
53
+ And I should see "followers = Fellowship.followers_for(self.username)" in file "app/models/hobbit.rb"
54
+ And I should see "Hobbit.where(:username => followers)" in file "app/models/hobbit.rb"
55
+
56
+ And I should see "def followings" in file "app/models/hobbit.rb"
57
+ And I should see "followings = Fellowship.followings_for(self.username)" in file "app/models/hobbit.rb"
58
+ And I should see "Hobbit.where(:username => followings)" in file "app/models/hobbit.rb"
59
+ And I should not see file "temp_file.rb"
60
+
@@ -0,0 +1,59 @@
1
+ Feature: Redis Friendship Generator
2
+ In order to befriend multiple users
3
+ As a rails developer
4
+ I want to generate a Friendship library
5
+
6
+ Scenario: Generate default Friendship
7
+ Given a new Rails app
8
+ When I run "rails g redis_friendships"
9
+ Then I should see the following files
10
+ | app/models/friendship.rb |
11
+ And I should see "class Friendship" in file "app/models/friendship.rb"
12
+
13
+ And I should see "def self.follow!(username, followed_username)" in file "app/models/friendship.rb"
14
+ And I should see "R.sadd("friendship:#{username}:followings", followed_username)" in file "app/models/friendship.rb"
15
+ And I should see "R.sadd("friendship:#{followed_username}:followings", username)" in file "app/models/friendship.rb"
16
+
17
+ And I should see "def self.stop_following!(username, followed_username)" in file "app/models/friendship.rb"
18
+ And I should see "R.srem("friendship:#{username}:followings", followed_username)" in file "app/models/friendship.rb"
19
+ And I should see "R.srem("friendship:#{followed_username}:followings", username)" in file "app/models/friendship.rb"
20
+
21
+ And I should see "def self.follows?(username, followed_username)" in file "app/models/friendship.rb"
22
+ And I should see "R.sismember("friendship:#{username}:followings", followed_username)" in file "app/models/friendship.rb"
23
+
24
+ And I should see "def self.followed_by?(user, following_user)" in file "app/models/friendship.rb"
25
+ And I should see " R.sismember("friendship:#{username}:followers", following_username)" in file "app/models/friendship.rb"
26
+
27
+ And I should see "def self.followings_for(username)" in file "app/models/friendship.rb"
28
+ And I should see "R.smembers("friendship:#{username}:followings")" in file "app/models/friendship.rb"
29
+
30
+ And I should see "def self.followers_for(username)" in file "app/models/friendship.rb"
31
+ And I should see "R.smembers("friendship:#{username}:followers")" in file "app/models/friendship.rb"
32
+
33
+ And I should see the following files
34
+ |app/models/user.rb|
35
+ And I should see "class User < ActiveRecord::Base" in file "app/models/user.rb"
36
+
37
+ And I should see "def followed_by?(user)" in file "app/models/user.rb"
38
+ And I should see "Friendship.followed_by?(self.username, user.username)" in file "app/models/user.rb"
39
+
40
+ And I should see "def follows?(user)" in file "app/models/user.rb"
41
+ And I should see "Friendship.follows?(self.username, user.username)" in file "app/models/user.rb"
42
+
43
+ And I should see "def follow!(user)" in file "app/models/user.rb"
44
+ And I should see "return false if self.username == user.username" in file "app/models/user.rb"
45
+ And I should see "Friendship.follow!(self.username, user.username)" in file "app/models/user.rb"
46
+ And I should see "true" in file "app/models/user.rb"
47
+
48
+ And I should see "def stop_following!(user)" in file "app/models/user.rb"
49
+ And I should see "Friendship.stop_following!(self.username, user.username)" in file "app/models/user.rb"
50
+
51
+ And I should see "def followers" in file "app/models/user.rb"
52
+ And I should see "followers = Friendship.followers_for(self.username)" in file "app/models/user.rb"
53
+ And I should see "User.where(:username => followers)" in file "app/models/user.rb"
54
+
55
+ And I should see "def followings" in file "app/models/user.rb"
56
+ And I should see "followings = Friendship.followings_for(self.username)" in file "app/models/user.rb"
57
+ And I should see "User.where(:username => followings)" in file "app/models/user.rb"
58
+ And I should not see file "temp_file.rb"
59
+
@@ -0,0 +1,37 @@
1
+ Feature: Redis Messages Generator With Existing User Model
2
+ In order to blablablab this makes testing boring I need to refactor this anyway and I have a cold
3
+ As a rails developer
4
+ I want to inject the messaging code into the existing User model
5
+
6
+
7
+ Scenario: Generate injected code into existing User Model
8
+ Given a new Rails app
9
+ When I run "rails g model hobbit username:string"
10
+ When I run "rails g redis_friendships fellowships hobbit Red"
11
+ And I should see the following files
12
+ |app/models/hobbit.rb|
13
+ And I should see "class Hobbit < ActiveRecord::Base" in file "app/models/hobbit.rb"
14
+
15
+ And I should see "def followed_by?(user)" in file "app/models/hobbit.rb"
16
+ And I should see "Fellowship.followed_by?(self.username, user.username)" in file "app/models/hobbit.rb"
17
+
18
+ And I should see "def follows?(user)" in file "app/models/hobbit.rb"
19
+ And I should see "Fellowship.follows?(self.username, user.username)" in file "app/models/hobbit.rb"
20
+
21
+ And I should see "def follow!(user)" in file "app/models/hobbit.rb"
22
+ And I should see "return false if self.username == user.username" in file "app/models/hobbit.rb"
23
+ And I should see "Fellowship.follow!(self.username, user.username)" in file "app/models/hobbit.rb"
24
+ And I should see "true" in file "app/models/hobbit.rb"
25
+
26
+ And I should see "def stop_following!(user)" in file "app/models/hobbit.rb"
27
+ And I should see "Fellowship.stop_following!(self.username, user.username)" in file "app/models/hobbit.rb"
28
+
29
+ And I should see "def followers" in file "app/models/hobbit.rb"
30
+ And I should see "followers = Fellowship.followers_for(self.username)" in file "app/models/hobbit.rb"
31
+ And I should see "Hobbit.where(:username => followers)" in file "app/models/hobbit.rb"
32
+
33
+ And I should see "def followings" in file "app/models/hobbit.rb"
34
+ And I should see "followings = Fellowship.followings_for(self.username)" in file "app/models/hobbit.rb"
35
+ And I should see "Hobbit.where(:username => followings)" in file "app/models/hobbit.rb"
36
+ And I should not see file "temp_file.rb"
37
+
@@ -0,0 +1,47 @@
1
+ When /^I run "([^\"]*)"$/ do |command|
2
+ system("cd #{@current_directory} && #{command}").should be_true
3
+ end
4
+
5
+ When /^I add "([^\"]*)" to file "([^\"]*)"$/ do |content, short_path|
6
+ path = File.join(@current_directory, short_path)
7
+ File.should exist(path)
8
+ File.open(path, 'a') { |f| f.write(content + "\n") }
9
+ end
10
+
11
+ When /^I replace "([^\"]*)" with "([^\"]*)" in file "([^\"]*)"$/ do |old_content, new_content, short_path|
12
+ path = File.join(@current_directory, short_path)
13
+ File.should exist(path)
14
+ content = File.read(path).gsub(old_content, new_content)
15
+ File.open(path, 'w') { |f| f.write(content) }
16
+ end
17
+
18
+ Then /^I should see file "([^\"]*)"$/ do |path|
19
+ File.should exist(File.join(@current_directory, path))
20
+ end
21
+
22
+ Then /^I should not see file "([^\"]*)"$/ do |path|
23
+ File.should_not exist(File.join(@current_directory, path))
24
+ end
25
+ Then /^I should see "(.*)" in file "([^\"]*)"$/ do |content, short_path|
26
+ path = File.join(@current_directory, short_path)
27
+ File.should exist(path)
28
+ File.readlines(path).join.should include(content)
29
+ end
30
+
31
+ Then /^I should see the following files$/ do |table|
32
+ table.raw.flatten.each do |path|
33
+ File.should exist(File.join(@current_directory, path))
34
+ end
35
+ end
36
+
37
+ Then /^I should see the following in file "([^\"]*)"$/ do |short_path, table|
38
+ path = File.join(@current_directory, short_path)
39
+ File.should exist(path)
40
+ table.raw.flatten.each do |content|
41
+ File.readlines(path).join.should include(content)
42
+ end
43
+ end
44
+
45
+ Then /^I should successfully run "([^\"]*)"$/ do |command|
46
+ system("cd #{@current_directory} && #{command}").should be_true
47
+ end
@@ -0,0 +1,6 @@
1
+ Given /^a new Rails app$/ do
2
+ FileUtils.mkdir_p("tmp")
3
+ system("rails new tmp/rails_app").should be_true
4
+ system("ln -s ../../../lib/generators tmp/rails_app/lib/generators").should be_true
5
+ @current_directory = File.expand_path("tmp/rails_app")
6
+ end
@@ -0,0 +1,6 @@
1
+ require 'cucumber'
2
+ require 'rspec'
3
+
4
+ Before do
5
+ FileUtils.rm_rf "tmp/rails_app"
6
+ end
@@ -0,0 +1,7 @@
1
+ RSpec::Matchers.define :exist do |path|
2
+ match do
3
+ File.exist?(path)
4
+ end
5
+ failure_message_for_should { "Expected #{path} to exist but no file found" }
6
+ failure_message_for_should_not { "Expected #{path} to not exist but file was found" }
7
+ end
@@ -0,0 +1,53 @@
1
+ Have to edit this....
2
+
3
+ == What is redis-friendship
4
+ A friendship library with a certain follower/following system utilizing the power of both Redis and SQL. Using SQL for the users and Redis for the followers and the followings. Redis uses sets of usernames for both your followers and followings. And can be used to retrieve more information about your e.g. followers from SQL with those unique usernames.
5
+
6
+ == Install
7
+
8
+ gem install redis-friendships
9
+
10
+ == Rails 3
11
+
12
+ To use redis-friendships with Rails 3 you will need to include it in your Gemfile.
13
+
14
+ group :development do
15
+ gem "redis-friendships"
16
+ end
17
+
18
+ == Usage
19
+ * rails g redis_friendships : Will name the models User and Friendship and the Redis constant to R
20
+
21
+ * rails g redis_friendships fellowship user : Assuming the User model already exist, this will inject code into it and create a Fellowship model
22
+
23
+ * rails g redis_friendships fellowship hobbit Red : Creates the models Fellowship and Hobbit and name the Redis constant to Red
24
+
25
+ * And don't forget to run your migrations since we also utilize SQL here, the user model will be SQL - anything else would be stupid, right?
26
+
27
+ == Code
28
+ == READ
29
+ Assuming we use standard naming the user model will have two lookup scopes
30
+ The first two are
31
+ user.followers and user.followings
32
+ Where we do a SQL lookup with the list of usernames from the SET to get a list of user objects
33
+
34
+ If you don't want the user objects but just their (unique) usernames
35
+ Friendship.followings_for(username)
36
+ Friendship.followers_for(username)
37
+
38
+ == WRITE
39
+ To follow someone you just need to call
40
+ user.follow!(other_user)
41
+ This will just push the username into a SET.
42
+ It will also make that user a following to the other_user_
43
+ other_user.followings.include? user
44
+
45
+ To unfollow someone (or have someone unfollowed, just edit it to your hearts desire)
46
+ user.stop_following!(other_user)
47
+ This will remove it from user's SET. There are no limits to what you can do.
48
+ Will also remove the user as a following from other_user
49
+ other_user.followings.include?(user) == false
50
+
51
+ PS
52
+ You can also alter the methods to auto follow new followers or have requests before being stalked
53
+ DS
@@ -0,0 +1,90 @@
1
+ require 'rails/generators/base'
2
+ require 'rails/generators/migration'
3
+
4
+ class RedisFriendshipsGenerator < Rails::Generators::Base #:nodoc:
5
+ include Rails::Generators::Migration
6
+ source_root File.expand_path('../templates', __FILE__)
7
+
8
+ argument :friendship_name, :type => :string, :default => 'friendship', :banner => 'friendship_name'
9
+ argument :user_name, :type => :string, :default => 'user', :banner => 'user_name'
10
+ argument :redis_constant_name, :type => :string, :default => "R", :banner => "redis_constant_name"
11
+
12
+
13
+ def create_model_files
14
+ if File.exist?(File.join(Dir.pwd, "app", "models", "#{user_singular_name}.rb"))
15
+ template('user_injection_code.rb', "temp_file.rb") #I need to READ this with the erb in it
16
+ code = IO.read(File.join(Dir.pwd,"temp_file.rb"))
17
+ inject_into_class(File.join(Dir.pwd, "app", "models", "#{user_singular_name}.rb"), user_class_name, code)
18
+ File.delete(File.join(Dir.pwd,"temp_file.rb"))
19
+ else
20
+ template 'user.rb', "app/models/#{user_singular_name}.rb"
21
+ end
22
+ template 'friendship.rb', "app/models/#{friendship_singular_name}.rb"
23
+ end
24
+
25
+ def create_migration
26
+ migration_template 'user_migration.rb', "db/migrate/create_#{user_plural_name}.rb" if File.exist?(File.join(Dir.pwd, "app", "models", "#{user_singular_name}.rb"))
27
+ end
28
+
29
+ def add_gems_and_initializer
30
+ unless File.read(destination_path("Gemfile")).include? "redis"
31
+ gem "redis"
32
+ template"redis.rb", "config/initializers/redis.rb"
33
+ end
34
+ end
35
+
36
+ private
37
+ def friendship_singular_name
38
+ friendship_name.underscore.singularize
39
+ end
40
+
41
+ def friendshipplural_name
42
+ friendship_singular_name.pluralize
43
+ end
44
+
45
+ def friendship_class_name
46
+ friendship_name.singularize.camelize
47
+ end
48
+
49
+ def friendship_plural_class_name
50
+ friendship_plural_name.camelize
51
+ end
52
+
53
+ def user_singular_name
54
+ user_name.underscore.singularize
55
+ end
56
+
57
+ def user_plural_name
58
+ user_singular_name.pluralize
59
+ end
60
+
61
+ def user_class_name
62
+ user_name.singularize.camelize
63
+ end
64
+
65
+ def user_plural_class_name
66
+ user_plural_name.camelize
67
+ end
68
+
69
+ def destination_path(path)
70
+ File.join(destination_root, path)
71
+ end
72
+
73
+ # FIXME: Should be proxied to ActiveRecord::Generators::Base
74
+ # Implement the required interface for Rails::Generators::Migration.
75
+
76
+ def self.next_migration_number(dirname) #:nodoc:
77
+ if ActiveRecord::Base.timestamped_migrations
78
+ Time.now.utc.strftime("%Y%m%d%H%M%S")
79
+ else
80
+ "%.3d" % (current_migration_number(dirname) + 1)
81
+ end
82
+ end
83
+
84
+
85
+ #
86
+ # def self.banner
87
+ # "#{$0} seivan:#{generator_name} #{self.arguments.map{ |a| a.usage }.join(' ')} [options]"
88
+ # end
89
+
90
+ end