Coder Social home page Coder Social logo

acts_as_follower's Introduction

acts_as_follower

acts_as_follower is a gem to allow any model to follow any other model. This is accomplished through a double polymorphic relationship on the Follow model. There is also built in support for blocking/un-blocking follow records.

Main uses would be for Users to follow other Users or for Users to follow Books, etc…

(Basically, to develop the type of follow system that GitHub has)

<img src=“https://travis-ci.org/tcocca/acts_as_follower.png” />

Installation

The master branch supports Rails 5

Add the gem to the gemfile:

gem 'acts_as_follower', github: 'tcocca/acts_as_follower', branch: 'master'

Other instructions same as for Rails 4.

Rails 4.x support

The first release that support Rails 4 is 0.2.0

Add the gem to the gemfile:

gem "acts_as_follower"

Run the generator:

rails generate acts_as_follower

This will generate a migration file as well as a model called Follow.

Rails 3.x support

Rails 3 is supports in the rails_3 branch github.com/tcocca/acts_as_follower/tree/rails_3 The last gem release for Rails 3 support was 0.1.1, so install the gem using ~> 0.1.1

Add the gem to the gemfile:

gem "acts_as_follower", '~> 0.1.1'

or install from the branch

gem "acts_as_follower", git: 'git://github.com/tcocca/acts_as_follower.git', branch: 'rails_3'

Run the generator:

rails generate acts_as_follower

This will generate a migration file as well as a model called Follow.

Rails 2.3.x support

Rails 2.3.x is supported in the rails_2.3.x branch github.com/tcocca/acts_as_follower/tree/rails_2.3.x but must be installed as a plugin. The gem version does not work with rails 2.3.x.

Run the following command:

script/plugin install git://github.com/tcocca/acts_as_follower.git -r rails_2.3.x

Run the generator:

script/generate acts_as_follower

Usage

Setup

Make your model(s) that you want to allow to be followed acts_as_followable, just add the mixin:

class User < ActiveRecord::Base
  ...
  acts_as_followable
  ...
end

class Book < ActiveRecord::Base
  ...
  acts_as_followable
  ...
end

Make your model(s) that can follow other models acts_as_follower

class User < ActiveRecord::Base
  ...
  acts_as_follower
  ...
end

acts_as_follower methods

To have an object start following another use the following:

book = Book.find(1)
user = User.find(1)
user.follow(book) # Creates a record for the user as the follower and the book as the followable

To stop following an object use the following

user.stop_following(book) # Deletes that record in the Follow table

You can check to see if an object that acts_as_follower is following another object through the following:

user.following?(book) # Returns true or false

To get the total number (count) of follows for a user use the following on a model that acts_as_follower

user.follow_count # Returns an integer

To get follow records that have not been blocked use the following

user.all_follows # returns an array of Follow records

To get all of the records that an object is following that have not been blocked use the following

user.all_following
# Returns an array of every followed object for the user, this can be a collection of different object types, eg: User, Book

To get all Follow records by a certain type use the following

user.follows_by_type('Book') # returns an array of Follow objects where the followable_type is 'Book'

To get all followed objects by a certain type use the following.

user.following_by_type('Book') # Returns an array of all followed objects for user where followable_type is 'Book', this can be a collection of different object types, eg: User, Book

There is also a method_missing to accomplish the exact same thing a following_by_type(‘Book’) to make you life easier

user.following_users # exact same results as user.following_by_type('User')

To get the count of all Follow records by a certain type use the following

user.following_by_type_count('Book') # Returns the sql count of the number of followed books by that user

There is also a method_missing to get the count by type

user.following_books_count # Calls the user.following_by_type_count('Book') method

There is now a method that will just return the Arel scope for follows so that you can chain anything else you want onto it:

book.follows_scoped

This does not return the actual follows, just the scope of followings including the followables, essentially: book.follows.unblocked.includes(:followable)

The following methods take an optional hash parameter of ActiveRecord options (:limit, :order, etc…)

follows_by_type, all_follows, all_following, following_by_type

acts_as_followable methods

To get all the followers of a model that acts_as_followable

book.followers  # Returns an array of all the followers for that book, a collection of different object types (eg. type User or type Book)

There is also a method that will just return the Arel scope for followers so that you can chain anything else you want onto it:

book.followers_scoped

This does not return the actual followers, just the scope of followings including the followers, essentially: book.followings.includes(:follower)

To get just the number of follows use

book.followers_count

To get the followers of a certain type, eg: all followers of type ‘User’

book.followers_by_type('User') # Returns an array of the user followers

There is also a method_missing for this to make it easier:

book.user_followers # Calls followers_by_type('User')

To get just the sql count of the number of followers of a certain type use the following

book.followers_by_type_count('User') # Return the count on the number of followers of type 'User'

Again, there is a method_missing for this method as well

book.count_user_followers # Calls followers_by_type_count('User')

To see is a model that acts_as_followable is followed by a model that acts_as_follower use the following

book.followed_by?(user)

# Returns true if the current instance is followed by the passed record
# Returns false if the current instance is blocked by the passed record or no follow is found

To block a follower call the following

book.block(user)
# Blocks the user from appearing in the followers list, and blocks the book from appearing in the user.all_follows or user.all_following lists

To unblock is just as simple

book.unblock(user)

To get all blocked records

book.blocks # Returns an array of blocked follower records (only unblocked) (eg. type User or type Book)

If you only need the number of blocks use the count method provided

book.blocked_followers_count

Unblocking deletes all records of that follow, instead of just the :blocked attribute => false the follow is deleted. So, a user would need to try and follow the book again. I would like to hear thoughts on this, I may change this to make the follow as blocked: false instead of deleting the record.

The following methods take an optional hash parameter of ActiveRecord options (:limit, :order, etc…)

followers_by_type, followers, blocks

Follow Model

The Follow model has a set of named_scope’s. In case you want to interface directly with the Follow model you can use them.

Follow.unblocked # returns all "unblocked" follow records

Follow.blocked # returns all "blocked" follow records

Follow.descending # returns all records in a descending order based on created_at datetime

This method pulls all records created after a certain date. The default is 2 weeks but it takes an optional parameter.

Follow.recent
Follow.recent(4.weeks.ago)

Follow.for_follower is a named_scope that is mainly there to reduce code in the modules but it could be used directly. It takes an object and will return all Follow records where the follower is the record passed in. Note that this will return all blocked and unblocked records.

Follow.for_follower(user)

If you don’t need the blocked records just use the methods provided for this:

user.all_follows
# or
user.all_following

Follow.for_followable acts the same as its counterpart (for_follower). It is mainly there to reduce duplication, however it can be used directly. It takes an object that is the followed object and return all Follow records where that record is the followable. Again, this returns all blocked and unblocked records.

Follow.for_followable(book)

Again, if you don’t need the blocked records use the method provided for this:

book.followers

If you need blocked records only

book.blocks

Comments/Requests

If anyone has comments or questions please let me know (tom dot cocca at gmail dot com). If you have updates or patches or want to contribute I would love to see what you have or want to add.

Note on Patches/Pull Requests

  • Fork the project.

  • Make your feature addition or bug fix.

  • Add tests for it. This is important so I don’t break it in a future version unintentionally (acts_as_follower uses Shoulda and Factory Girl)

  • Send me a pull request. Bonus points for topic branches.

Contributers

Thanks to everyone for their interest and time in committing to making this plugin better.

Please let me know if I missed you.

Copyright © 2008 - 2010 ( tom dot cocca at gmail dot com ), released under the MIT license.

acts_as_follower's People

Contributors

adhlssu07 avatar brchristian avatar dougal avatar drcapulet avatar james2m avatar jcoyne avatar jdg avatar joergbattermann avatar m3talsmith avatar merqlove avatar petergoldstein avatar rafael avatar tcocca avatar timpetricola avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

acts_as_follower's Issues

UUID

Here is a migration file for whoever use UUID, I really don't know How to Create an alternate generator to submit, but this could help someone!

class ActsAsFollowerMigration < ActiveRecord::Migration
  def self.up
    create_table :follows, id: :uuid do |t|
      #t.references :followable, :polymorphic => true, :null => false
      #t.references :follower,   :polymorphic => true, :null => false
      t.uuid :follower_id
      t.string :follower_type

      t.uuid :followable_id
      t.string :followable_type

      t.boolean :blocked, :default => false, :null => false
      t.timestamps
    end

    add_index :follows, ["follower_id", "follower_type"],     :name => "fk_follows"
    add_index :follows, ["followable_id", "followable_type"], :name => "fk_followables"
  end

  def self.down
    drop_table :follows
  end
end

acts_as_follower gem is not working in rails5

acts_as_follower gem working fine in Rails4 but it is not working Rails5.

When i integrate and try to use follow function in console i got following error.

user = User.find(1)
user2 = User.find(2)
user.follow(user2)

If you are using sqlite3 database,i got following error.
no table found error will be display

If you are using pg database,i got following error.
TypeError: no implicit conversion of nil into String

Using abstract, inherited model, without STI

When using a model that inherits from something other than ActiveRecord::Base the plugin does not work properly.

For instance:

class User < Omnisocial::User
  acts_as_followable
  acts_as_follower
end

In that case the type columns in the Follow model are populated with "Omnisocial::User" and in turn methods like user.followers_by_type('User') will not return anything - passing 'Omnisocial::User' to that method is not what I would expect to do. user.user_followers doesn't work either obviously, and again user.omnisocial_user_followers seems to be too cumbersome and wrong. On top of that path helpers wouldn't work with type 'Omnisocial::User'.

To make everything work I made the class Omnisocial::User abstract:

Omnisocial::User.abstract_class = true

but for this to make the plugin work I had to account for the abstract class in the parent_class_name method:

def parent_class_name(obj)
  if obj.class.superclass != ActiveRecord::Base && !obj.class.superclass.abstract_class?
    return obj.class.superclass.name
  end
  return obj.class.name
end

With that in place everything was working as expected for me (type columns are populated with 'User', user.user_followers etc.)

In short/general, apart from my issues (all of which I could workaround somehow and were just added for better explanation) - using an abstract model that is being inherited from, no STI, seems to be not supported currently.

Mongoid support

Hello @tcocca

I have used this gem with ActiveRecords and it works fine and Now I want this acts_as_follower gem into my project that has mongodb database, but I'm not able to add this.
Also I didn't found any documentation for mongoid support.

Is this gem support Mongoid ??

Composite Primary Keys

I am going to see if I can patch this to work with CPK unless you beat me to it.. heh

acts_as_follower and undefined method `following?' for #<User:0x007fca74c5aa58>

I've added acts_as_follower in my User model and I'm still getting undefined methodfollowing?' for #User:0x007fca74c5aa58`

I feel like this is such a silly place to get stuck on this but I've installed the gem and migrated db and the following? method isn't working for some reason... it does happen to be the current_user object that devise creates but don't know if that has something to do with it?

Error with to_json method

@world has acts_as_followable

> @world.to_json
NoMethodError:   Follow Load (39.9ms)  EXEC sp_executesql N'SELECT [follows].* FROM [follows] WHERE [follows].[followable_id] = 40 AND [follows].[followable_type] = N''World'''
undefined method `unblocked' for []:ActiveRecord::Relation
    from /home/davidm/.rvm/gems/ruby-1.9.2-p180@newpanel/gems/activerecord-3.2.8/lib/active_record/relation/delegation.rb:45:in `method_missing'
    from /home/davidm/.rvm/gems/ruby-1.9.2-p180@newpanel/gems/activerecord-3.2.8/lib/active_record/associations/collection_proxy.rb:100:in `method_missing'
    from /home/davidm/.rvm/gems/ruby-1.9.2-p180@newpanel/gems/acts_as_follower-0.1.1/lib/acts_as_follower/followable.rb:20:in `followers_count'
    from /home/davidm/.rvm/gems/ruby-1.9.2-p180@newpanel/gems/activemodel-3.2.8/lib/active_model/serialization.rb:82:in `block in serializable_hash'
    from /home/davidm/.rvm/gems/ruby-1.9.2-p180@newpanel/gems/activemodel-3.2.8/lib/active_model/serialization.rb:82:in `each'
    from /home/davidm/.rvm/gems/ruby-1.9.2-p180@newpanel/gems/activemodel-3.2.8/lib/active_model/serialization.rb:82:in `serializable_hash'
    from /home/davidm/.rvm/gems/ruby-1.9.2-p180@newpanel/gems/activerecord-3.2.8/lib/active_record/serialization.rb:13:in `serializable_hash'
    from /home/davidm/.rvm/gems/ruby-1.9.2-p180@newpanel/gems/activemodel-3.2.8/lib/active_model/serializers/json.rb:94:in `as_json'
    from /home/davidm/.rvm/gems/ruby-1.9.2-p180@newpanel/gems/activesupport-3.2.8/lib/active_support/json/encoding.rb:47:in `block in encode'
    from /home/davidm/.rvm/gems/ruby-1.9.2-p180@newpanel/gems/activesupport-3.2.8/lib/active_support/json/encoding.rb:77:in `check_for_circular_references'
    from /home/davidm/.rvm/gems/ruby-1.9.2-p180@newpanel/gems/activesupport-3.2.8/lib/active_support/json/encoding.rb:46:in `encode'
    from /home/davidm/.rvm/gems/ruby-1.9.2-p180@newpanel/gems/activesupport-3.2.8/lib/active_support/json/encoding.rb:31:in `encode'
    from /home/davidm/.rvm/gems/ruby-1.9.2-p180@newpanel/gems/activesupport-3.2.8/lib/active_support/core_ext/object/to_json.rb:16:in `to_json'
    from (irb):20
    from /home/davidm/.rvm/gems/ruby-1.9.2-p180@newpanel/gems/railties-3.2.8/lib/rails/commands/console.rb:47:in `start'
    from /home/davidm/.rvm/gems/ruby-1.9.2-p180@newpanel/gems/railties-3.2.8/lib/rails/commands/console.rb:8:in `start'
    from /home/davidm/.rvm/gems/ruby-1.9.2-p180@newpanel/gems/railties-3.2.8/lib/rails/commands.rb:41:in `<top (required)>'
    from script/rails:6:in `require'
    from script/rails:6:in `<main>'ruby-1.9.2-p180 :021 > 
> Rails.version
 => "3.2.8" 

* acts_as_follower (0.1.1)

Make the scopes play nice with other scopes...

Looking around the code there are a lot of hangovers from the Rails2.3 days where the scope chain ends with .find(:all, options). This effectively stops any scope being chained on the end as find and all return Arrays as opposed to ActiveRecord::Relation objects. e.g.;

      # Returns the follow records related to this instance with the followable included.
      def all_follows(options={})
        self.follows.unblocked.includes(:followable).all(options)
      end

Since scopes are far more flexible than an options hash are there any objections to breaking compatibility and removing the all / finds that are on the end of some scope chains?

NoMethodError: undefined method `relation_delegate_class' for Follow:Module

I'm trying to follow a user from a user. My User model has acts_as_followable and acts_as_follower. I'm on rails 5 so I have master on my Gemfile:

gem 'acts_as_follower', github: 'tcocca/acts_as_follower', branch: 'master'

I get this error when trying to follow a user:

2.3.0 :002 > User.first.follow User.second
User Load (0.6ms) SELECT "users".* FROM "users" ORDER BY "users"."id" ASC LIMIT $1 [["LIMIT", 1]]
User Load (0.4ms) SELECT "users".* FROM "users" ORDER BY "users"."id" ASC LIMIT $1 OFFSET $2 [["LIMIT", 1], ["OFFSET", 1]]
DEPRECATION WARNING: Setting custom parent classes is deprecated and will be removed in future versions. (called from parent_class_name at /usr/local/rvm/gems/ruby-2.3.0/bundler/gems/acts_as_follower-c5ac7b9601c4/lib/acts_as_follower/follower_lib.rb:10)
NoMethodError: undefined method relation_delegate_class' for Follow:Module from /usr/local/rvm/gems/ruby-2.3.0/gems/activerecord-5.0.2/lib/active_record/relation/delegation.rb:107:in relation_class_for'
from /usr/local/rvm/gems/ruby-2.3.0/gems/activerecord-5.0.2/lib/active_record/relation/delegation.rb:101:in create' from /usr/local/rvm/gems/ruby-2.3.0/gems/activerecord-5.0.2/lib/active_record/associations/collection_association.rb:47:in reader'
from /usr/local/rvm/gems/ruby-2.3.0/gems/activerecord-5.0.2/lib/active_record/associations/builder/association.rb:111:in follows' from /usr/local/rvm/gems/ruby-2.3.0/bundler/gems/acts_as_follower-c5ac7b9601c4/lib/acts_as_follower/follower.rb:33:in follow'
from (irb):2
from /usr/local/rvm/gems/ruby-2.3.0/gems/railties-5.0.2/lib/rails/commands/console.rb:65:in start' from /usr/local/rvm/gems/ruby-2.3.0/gems/railties-5.0.2/lib/rails/commands/console_helper.rb:9:in start'
from /usr/local/rvm/gems/ruby-2.3.0/gems/railties-5.0.2/lib/rails/commands/commands_tasks.rb:78:in console' from /usr/local/rvm/gems/ruby-2.3.0/gems/railties-5.0.2/lib/rails/commands/commands_tasks.rb:49:in run_command!'
from /usr/local/rvm/gems/ruby-2.3.0/gems/railties-5.0.2/lib/rails/commands.rb:18:in <top (required)>' from /usr/local/rvm/gems/ruby-2.3.0/gems/activesupport-5.0.2/lib/active_support/dependencies.rb:293:in require'
from /usr/local/rvm/gems/ruby-2.3.0/gems/activesupport-5.0.2/lib/active_support/dependencies.rb:293:in block in require' from /usr/local/rvm/gems/ruby-2.3.0/gems/activesupport-5.0.2/lib/active_support/dependencies.rb:259:in load_dependency'
from /usr/local/rvm/gems/ruby-2.3.0/gems/activesupport-5.0.2/lib/active_support/dependencies.rb:293:in require' from /home/ubuntu/workspace/drezr/drezr-api/bin/rails:9:in <top (required)>'
from /usr/local/rvm/gems/ruby-2.3.0/gems/activesupport-5.0.2/lib/active_support/dependencies.rb:287:in load' from /usr/local/rvm/gems/ruby-2.3.0/gems/activesupport-5.0.2/lib/active_support/dependencies.rb:287:in block in load'
from /usr/local/rvm/gems/ruby-2.3.0/gems/activesupport-5.0.2/lib/active_support/dependencies.rb:259:in load_dependency' from /usr/local/rvm/gems/ruby-2.3.0/gems/activesupport-5.0.2/lib/active_support/dependencies.rb:287:in load'
from /usr/local/rvm/gems/ruby-2.3.0/gems/spring-2.0.1/lib/spring/commands/rails.rb:6:in call' from /usr/local/rvm/gems/ruby-2.3.0/gems/spring-2.0.1/lib/spring/command_wrapper.rb:38:in call'
from /usr/local/rvm/gems/ruby-2.3.0/gems/spring-2.0.1/lib/spring/application.rb:191:in block in serve' from /usr/local/rvm/gems/ruby-2.3.0/gems/spring-2.0.1/lib/spring/application.rb:161:in fork'
from /usr/local/rvm/gems/ruby-2.3.0/gems/spring-2.0.1/lib/spring/application.rb:161:in serve' from /usr/local/rvm/gems/ruby-2.3.0/gems/spring-2.0.1/lib/spring/application.rb:131:in block in run'
from /usr/local/rvm/gems/ruby-2.3.0/gems/spring-2.0.1/lib/spring/application.rb:125:in loop' from /usr/local/rvm/gems/ruby-2.3.0/gems/spring-2.0.1/lib/spring/application.rb:125:in run'
from /usr/local/rvm/gems/ruby-2.3.0/gems/spring-2.0.1/lib/spring/application/boot.rb:19:in <top (required)>' from /usr/local/rvm/rubies/ruby-2.3.0/lib/ruby/2.3.0/rubygems/core_ext/kernel_require.rb:55:in require'
from /usr/local/rvm/rubies/ruby-2.3.0/lib/ruby/2.3.0/rubygems/core_ext/kernel_require.rb:55:in require' from -e:1:in

'2.3.0 :003 >

GEM?

Why not having this nice plugin as a gem file?

there seems to be an issue with parent_class_name

my classes look like the following

class User < ApplicationRecord
  include Clearance::User
  ...
  acts_as_follower
  ...
end
class Policy < ApplicationRecord
  include Searchable
  ...
  acts_as_followable
  ...
end
class ApplicationRecord < ActiveRecord::Base
  self.abstract_class = true
end

For some reason when I call this method user.follow(policy), the followable_type is not set to 'Policy' but to 'ApplicationRecord' which makes user.following?(policy) always return false. I looked at the parent_class_name method. the code below executes because the include? method returns false even if obj.class.superclass.name == 'ApplicationRecord'

unless parent_classes.include?(obj.class.superclass)
  return obj.class.superclass.name
end

I use Rails 5 and the master branch as indicated in another issue #79

follows.followable_id may not be NULL: INSERT INTO "follows"

hello.
First of all I want to say that the gem is fantastic.
Here is my configuration.

class FollowsController < ApplicationController

def create
    @user = User.find(params[:user_id])
    current_user.follow(@user)
  end

  def destroy
    @user = User.find(params[:user_id])
    current_user.stop_following(@user)
  end
end
class User < ActiveRecord::Base
  # Include default devise modules. Others available are:
  # :token_authenticatable, :confirmable,
  # :lockable, :timeoutable and :omniauthable
  devise :database_authenticatable, :registerable,
         :recoverable, :rememberable, :trackable, :validatable,
         :confirmable, :token_authenticatable
before_save :ensure_authentication_token
acts_as_follower
acts_as_followable
  # Setup accessible (or protected) attributes for your model
  attr_accessible :name, :email, :password, :password_confirmation, :remember_me


end

_follow_user.html.erb

<% unless user == current_user %>
  <% if current_user.following?(user) %>
    <%= button_to("Un-Follow #{user.name}", user_follow_path(user.to_param, current_user.get_follow(user).id), :method => :delete, :remote => true) %>
  <% else %>
    <%= button_to("Follow #{user.name}", user_follows_path(user.to_param), :remote => true) %>
  <% end %>
<% end %>

routes.rb

 devise_for :users

    root :to => 'home#index'


  # The priority is based upon order of creation: first created -> highest priority.
  # See how all your routes lay out with "rake routes".


  # You can have the root of your site routed with "root"
  # root 'welcome#index'

 resources :users, :only => [:index, :show] do
    resources :follows, :only => [:create, :destroy]
  end

and here the error that I get from the server

Started POST "/users/1/follows" for 127.0.0.1 at 2014-05-23 20:57:12 +0200
Processing by FollowsController#create as JS
  Parameters: {"authenticity_token"=>"R/8+MoKc/WUhLUzKskc3iWCdvE9cpf7TpuYHpXa7Jig=", "user_id"=>"1"}
  User Load (0.1ms)  SELECT "users".* FROM "users" WHERE "users"."id" = ? LIMIT 1  [["id", "1"]]
  User Load (0.2ms)  SELECT "users".* FROM "users" WHERE "users"."id" = 2 ORDER BY "users"."id" ASC LIMIT 1
  Follow Load (0.1ms)  SELECT "follows".* FROM "follows" WHERE "follows"."followable_id" = ? AND "follows"."followable_type" = ? AND "follows"."followable_id" = 1 AND "follows"."followable_type" = 'User' LIMIT 1  [["followable_id", 2], ["followable_type", "User"]]
   (0.0ms)  begin transaction
WARNING: Can't mass-assign protected attributes for Follow: followable_id, followable_type
    app/controllers/follows_controller.rb:5:in `create'
  SQL (0.4ms)  INSERT INTO "follows" ("created_at", "followable_id", "followable_type", "updated_at") VALUES (?, ?, ?, ?)  [["created_at", Fri, 23 May 2014 18:57:12 UTC +00:00], ["followable_id", 2], ["followable_type", "User"], ["updated_at", Fri, 23 May 2014 18:57:12 UTC +00:00]]
SQLite3::ConstraintException: follows.follower_id may not be NULL: INSERT INTO "follows" ("created_at", "followable_id", "followable_type", "updated_at") VALUES (?, ?, ?, ?)
   (0.1ms)  rollback transaction
Completed 500 Internal Server Error in 28ms

ActiveRecord::StatementInvalid (SQLite3::ConstraintException: follows.follower_id may not be NULL: INSERT INTO "follows" ("created_at", "followable_id", "followable_type", "updated_at") VALUES (?, ?, ?, ?)):
  app/controllers/follows_controller.rb:5:in `create'

can anyone help me?
thank you!!!!!i use rails 4.0.0

New Rails3 Branch

Hey,

Thanks for putting together a Rails3 branch of the plugin. When I was using this before you made the new plugin, I noticed that the methods for returning followers (following_by_type, followers_by_type) return an array instead of collection which makes it impossible to extend. Since Rails3 has scopes and chaining, you can rewrite these methods to return a collection that can still be modified. You may want to add that to the Rails3 plugin since it's a lot more flexible.

Is this still being maintained?

Sorry to post such an issue again, but it seems that over a year with no updates..

@tcocca maybe its best to add more maintainers, since this gem has valuable functionality that everyone gain by cooperating than using in-house, closed source solutions

Following more than one

Hi, I have it setup and working fine with following a single group of items... using your ajax gist.

So In my project there are apples, and there are bananas, users can follow as many apples as they want.. and it works.. I also have a different model/controller for Bananas, now I'm wondering inside the FollowsController example you have setup a create and destroy function.

I am wondering how I can modify this so that It is aware of if I am on an Apple view clicking follow, then execute the apple create/destroy functions, OR if I am on a Banana view.

Also finally, The same goes for the create.js.erb/destroy.js.erb

I have tried checking what page it came from, and also checking the param[:controller] .. with no success.

MongoDB/Mongoid version?

Does anything exist for Mongo here or elsewhere? MySQL seems like a limited datastore for graph data like this.

Follow date

hello,

When a model follows another model is there a timestamp for that follow?

The reason I ask is that I want to make a graph of (for example) number of user's following another user over time.

So, unless there is another way of generating a cumulative sum for each day of the number of users who follow, I need to to check each day how many followed..

thanks

Add short description

Hello @tcocca

There is a file i.e lib/acts_as_follower/follow_scopes.rb which has methods, but users not able to understand what the methods returns, so we need to add short description on the top of each method.
I'm adding short description for each method.

Ability to Track which Classes are Followable

In our application we do a few checks against an array of classes that are followable. Is this something that others would find useful? If so I'll submit a patch.

Basically it looks like this:

ActsAsFollower::Followable.followable_classes
# => [Post, Comment, Foo, Bar, ... ]

.follow method seems to work, but the following? method always return false...

Hi,
Sorry for asking help here, but I'm really stuck.
I installed the gem on my rails app.

let's say:
user = User.first
u = User.last

When I call user.follow(u), it seems to work :

Follow Load (0.3ms)  SELECT  "follows".* FROM "follows" WHERE "follows"."follower_id" = $1 AND "follows"."follower_type" = $2 AND "follows"."followable_id" = $3 AND "follows"."followable_type" = $4 LIMIT $5  [["follower_id", 1], ["follower_type", "User"], ["followable_id", 2], ["followable_type", "ApplicationRecord"], ["LIMIT", 1]]
   (0.1ms)  BEGIN
  SQL (0.4ms)  INSERT INTO "follows" ("followable_type", "followable_id", "follower_type", "follower_id", "created_at", "updated_at") VALUES ($1, $2, $3, $4, $5, $6) RETURNING "id"  [["followable_type", "ApplicationRecord"], ["followable_id", 2], ["follower_type", "User"], ["follower_id", 1], ["created_at", 2016-09-12 15:08:32 UTC], ["updated_at", 2016-09-12 15:08:32 UTC]]
   (3.0ms)  COMMIT
=> #<Follow:0x0055dd1c2b12c8
 id: 5,
 followable_type: "ApplicationRecord",
 followable_id: 2,
 follower_type: "User",
 follower_id: 1,
 blocked: false,
 created_at: Mon, 12 Sep 2016 15:08:32 UTC +00:00,
 updated_at: Mon, 12 Sep 2016 15:08:32 UTC +00:00>

But then, when I call `user.following?(u), this is what i got:

(0.6ms)  SELECT COUNT(*) FROM "follows" WHERE "follows"."blocked" = $1 AND "follows"."follower_id" = $2 AND "follows"."follower_type" = $3 AND "follows"."followable_id" = $4 AND "follows"."followable_type" = $5  [["blocked", false], ["follower_id", 1], ["follower_type", "ApplicationRecord"], ["followable_id", 2], ["followable_type", "ApplicationRecord"]]
=> false

Any idea where I should be looking to solve this ?
Thx

Strange ActiveRecord behavior #<Follow:0x104fce2c0>

Hi,

First of all, thanks for the plug in, I did a simple follow system on my own but I want to try with polymorphic association so here I am !

Everything is working fine but when I want to put following / followers in my views, I got this :

Follow:0x104fce2c0 for <%= current_user.follows_by_type('Group')%>

<ActiveRecord::Relation for <%= group.user_followers %>

I normally have this error when a forgot to delete a = in a loop but it's not the case here.

Any ideas ?

Regards

Félix

Regarding sending request to following user

Hi,
For example i'm having list of users. so when i logged in as X user and click on Y user follow button. At that time the user X didn't follow Y user, That Y user has to accept or reject X. Then only X has to follow Y. How to implement this feature.

#followers should be a Relation, not array

The followers method uses .to_a:

      def followers(options={})
        followers_scope = followers_scoped.unblocked
        followers_scope = apply_options_to_scope(followers_scope, options)
        followers_scope.to_a.collect{|f| f.follower}
      end

It'd be better if this returned a relation so I can do, say, post.followers.to_sql or post.followers.select(:id).

following_by_type & followers_by_type seems to be broken in rails 4.2

Hello.

I build app with rails 4.2(rc2) + mysql5.6 and found regression.

In rails 4.1.7, this code works well.

user.following_by_type('User').pluck(:id)

But in rails 4.2, this code throws error like this.

ActiveRecord::StatementInvalid: Mysql2::Error: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'WHERE `follows`.`blocked` = 0 AND `follows`.`follower_id` = XX AND `follows`.`fo' at line 1: SELECT `users`.`id` FROM `users` INNER JOIN `follows` ON `follows`.`followable_id` = `users`.`id` AND `follows`.`followable_type` =  WHERE `follows`.`blocked` = 0 AND `follows`.`follower_id` = XX AND `follows`.`follower_type` = 'User' AND `follows`.`followable_type` = 'User'

Maybe, change of AR implementation causes this error.
Any idea to solve this?

Thanks.

The gem is spamming deprecation warnings in tests

ruby 2.4.0
rails 5.0.1
acts_as_follower master@c5ac7b9
rspec 3.5.0

When I run rspec I get a lot of these deprecation warnings (a lot is one per test):

DEPRECATION WARNING: Setting custom parent classes is deprecated and will be removed in future versions. (called from parent_class_name at /home/maurizio/.asdf/installs/ruby/2.4.0/lib/ruby/gems/2.4.0/bundler/gems/acts_as_follower-c5ac7b9601c4/lib/acts_as_follower/follower_lib.rb:10)

User should not be able to block himself.

Hello,
I'm using this gem and I found problem with blocking functionality, that is the user(follower) is able to block himself.

Example:
follower.block(follower)

This create new record into "Follow" model.

But I think this should not be happen, the user can not be able to block himself.

@tcocca Is this issue??

Conflicts with paranoia/acts_as_paranoid gems..

With paranoids you can just mark record as deleted without real deletion..
In this case acts_as_follower should not delete associations.. so that after restoration it would be possible to have same followers/followables

Rails 5 followable_type

Hi there

Firstly, just to say thanks for putting this gem together and taking the time to look at this.

I'm building something in Rails 5 and have come up against a slight problem. When selecting objects a user is following, the follower_type is coming up "user" but followable_type is coming up as "ApplicationRecord". I guess acts_as_followable is not working in the model.

Is there a quick fix for this?

Thanks again

Jimboqu

Problem using current_user.following?(user)

I am using acts_as_follower with Devise
So I notice something funny with current_user.following?(user)

current_user.following?(user) will always resolve to false, even when it's true, unless I restart my rails server

any thoughts?

all_following method doesn't work with different types

Just noticed this.. I'm on Rails 3.0.9, ruby 1.9.2 If you set a User as a follower, and have it follow several Products and Companies, you can't then use the method

user.all_following

it seems to be that when you try to create an array of different active record types, it throws an error. Perhaps this is a bug somewhere in Rails. Even when I try something like

[User.new, Product.new]

there seems to be a problem in the console [User.new, User.new] or [Product.new, Product.new] seem to work.

so instead of using user.all_following, I have to use the following_by_type methods

Issues with block functionality (Rails 2.3.x)

First off i'd like to say that this plugin is a godsend. I was able to implement a comment notification system for my website in minutes. One of the features for the notification system is to let the user block himself from receiving notifications for a particular topic.

But the block system in the plugin did not seem to work, so i added a few patches to my local code. I have to say that im not very proficient with rails coding, so do ignore the chunky code.

Issue1: follow method should check if there is a blocked entry before creating a new Follow record

def follow(followable) #SARAV-PATCH-START #if a blocked record exists then do not follow unless get_blocked_follow(followable).blank? return end #PATCH-END
      follow = get_follow(followable)
      if follow.blank? && self != followable
        Follow.create(:followable => followable, :follower => self)
      end
    end

    def get_blocked_follow(followable)
      Follow.blocked.find(:first, :conditions => ["follower_id = ? AND follower_type = ? AND followable_id = ? AND followable_type = ?", self.id, parent_class_name(self), followable.id, parent_class_name(followable)])
    end

The next 2 issues could be something to do with my environment. But as i said im not very familiar with rails, so i just patched it.

Issue 2: NameError: undefined local variable or method `follows' in In block_future_follow

def block_future_follow(follower)
#SARAV-PATCH-START
#follows.create(:followable => self, :follower => follower, :blocked => true)
Follow.create(:followable => self, :follower => follower, :blocked => true)
#PATCH-END
end

Issue 3: NoMethodError: undefined method `try' in unblock method

def unblock(follower)
#SARAV-PATCH-START
#get_follow_for(follower).try(:delete)
follow = get_follow_for(follower)
if follow
follow.destroy
end
#PATCH-END
end

Please let me know if my changes are alright.. And thanks again for this wonderful plugin

Use base_class rather than superclass

I've had some issues with this gem after updating to rails 5.

Upon installation, the object.follow(thing) works fine the first time, but every time thereafter, it fails with:

TypeError: no implicit conversion of nil into String

It's because ApplicationRecord is the class that parent_class_name is returning. You can see by this query:

INSERT INTO "follows" ("followable_id", "followable_type", "follower_id", "follower_type", "created_at", "updated_at") VALUES (14829, 'ApplicationRecord', 1, 'User', '2017-01-15 09:49:16.098371', '2017-01-15 09:49:16.098371') RETURNING "id"

I've done all the recommended steps with the config and I was about to give up until I saw that you're using superclass, which doesn't always provide the right class in a rails environment:

class A < ActiveRecord::Base
end

class B < A
end

> A.superclass
=> ActiveRecord::Base
> B.superclass
=> A

> A.base_class
=> A
> B.base_class
=> A

I added this commit to my own forked branch and it now works as expected: bufordtaylor@43ad8ae

Why parent class name saved in case of STI ?

I have STI for user, who can for e.g. follow other users and books.
User has two subclasses as admin and visitor via STI. Visitor has - acts_as_followable and acts_as_follower.

Now, when i do -

visitor1.follow(visitor2)

It creates a follow record with followable_type and follower_type as 'User'. But because of this, below command returns empty array -

visitor1.following_visitors

While below method gives error saying - association 'following' was not found.

visitor1.following_user

Only options that remains to use is - visitor1.following_by_type('User').

So, I would like to know why it was decided to store superclass name while saving entries in Follow table? Rather, saving them as is, would solve above issue. Correct me if I am wrong.

Unblock should not delete record

Hey,
I just spent an hour trying to figure out why the records had been disappearing until i finally got across this line

Unblocking deletes all records of that follow, instead of just the :blocked attribute => false the follow is deleted. So, a user would need to try and follow the book again. I would like to hear thoughts on this, I may change this to make the follow as :blocked => false instead of deleting the record.

i feel like an idiot now, but then again, it's 1130pm and i've been working since 9am!

This is definitely not the intuitive way to do it. is there any particular reason you went this route vs just setting the field to false?

Too many queries on follow

user.follow(user2)

In this case we already have the two records and all of their information. So why does it do two SELECT statements to get them again before doing the INSERT into the follows table? We're doing one query to see if the follow already exists, two more queries to get the follower and followable, and then the insert. Four queries on every follow seems excessive.

Demo Solution

Can you please update the solution and AJAX code that posted for demonstration purposes? Your new approach for Rails 4 is quite different than the one you posted in 2011. Also, I receive a template error while routing to the [GET] method for the follow button. Thank you very much, @tcocca.

License missing from gemspec

RubyGems.org doesn't report a license for your gem. This is because it is not specified in the gemspec of your last release.

via e.g.

spec.license = 'MIT'
# or
spec.licenses = ['MIT', 'GPL-2']

Including a license in your gemspec is an easy way for rubygems.org and other tools to check how your gem is licensed. As you can imagine, scanning your repository for a LICENSE file or parsing the README, and then attempting to identify the license or licenses is much more difficult and more error prone. So, even for projects that already specify a license, including a license in your gemspec is a good practice. See, for example, how rubygems.org uses the gemspec to display the rails gem license.

There is even a License Finder gem to help companies/individuals ensure all gems they use meet their licensing needs. This tool depends on license information being available in the gemspec. This is an important enough issue that even Bundler now generates gems with a default 'MIT' license.

I hope you'll consider specifying a license in your gemspec. If not, please just close the issue with a nice message. In either case, I'll follow up. Thanks for your time!

Appendix:

If you need help choosing a license (sorry, I haven't checked your readme or looked for a license file), GitHub has created a license picker tool. Code without a license specified defaults to 'All rights reserved'-- denying others all rights to use of the code.
Here's a list of the license names I've found and their frequencies

p.s. In case you're wondering how I found you and why I made this issue, it's because I'm collecting stats on gems (I was originally looking for download data) and decided to collect license metadata,too, and make issues for gemspecs not specifying a license as a public service :). See the previous link or my blog post about this project for more information.

acts_as_follower doesn't play nice with searchlogic

Hi,

I have Users following Companies, and that works very well using the irb.
When I try to integrate that setup with SearchLogic tho, it returns to me an error:

>> User.find(1).following_companies.count
2
>> User.find(1).following_companies.search
NoMethodError: undefined method `search' for #<Array:0x107465db8>
    from (irb):16
>> 

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.