Question

I have created a BETA Invitation system by following this tutorial. http://railscasts.com/episodes/124-beta-invitations. Users can also follow one another in my Rails app.

How can I have the Invitee follow the person who Invited him on sign up?

Currently, I am trying to establish this in my User Model using a method, but I am having trouble creating the method that allows the Invitee to follow the Inviter via sender_id/user_id.

This is the code I have used so far.

SCHEMA

  create_table "users", :force => true do |t|
    t.string   "name"
    t.string   "email"
    t.integer  "invitation_id"
    t.integer  "invitation_limit"
    t.timestamp "created_at",                                :null => false
    t.timestamp "updated_at",                                :null => false
    t.string    "password_reset_token"
    t.timestamp "password_reset_sent_at"
  end

  create_table "invitations", :force => true do |t|
    t.integer  "sender_id"
    t.string   "recipient_email"
    t.string   "token"
    t.datetime "sent_at"
    t.datetime "created_at",      :null => false
    t.datetime "updated_at",      :null => false
  end

MODELS

USER

class User < ActiveRecord::Base
  attr_accessible :name, :email, :password, :password_confirmation, :invitation_token

  has_many :relationships, foreign_key: "follower_id", dependent: :destroy
  has_many :followed_users, through: :relationships, source: :followed

  has_many :reverse_relationships, foreign_key: "followed_id",
                               class_name:  "Relationship",
                               dependent:   :destroy
  has_many :followers, through: :reverse_relationships, source: :follower

  has_many :sent_invitations, :class_name => 'Invitations', :foreign_key => 'sender_id'

  belongs_to :invitation

  after_create :follow_inviter      #---------- HERE!!

  def follow_inviter                #---------- HERE!!
    inviters = Invitation.find_by_sender_id
    inviters.each do |invite|
      self.follow!(invite)
    end
  end

  def invitation_token
    invitation.token if invitation
  end

  def invitation_token=(token)
    self.invitation = Invitation.find_by_token(token)
  end

  def following?(other_user)
    relationships.find_by_followed_id(other_user.id)
  end

 def follow!(other_user)
    relationships.create!(followed_id: other_user.id)
  end

  def unfollow!(other_user)
    relationships.find_by_followed_id(other_user.id).destroy
  end

end

RELATIONSHIPS

class Relationship < ActiveRecord::Base

  attr_accessible :followed_id

  belongs_to :follower, class_name: "User"
  belongs_to :followed, class_name: "User"

  validates :follower_id, presence: true
  validates :followed_id, presence: true
end

INVITATION

class Invitation < ActiveRecord::Base
  attr_accessible :recipient_email, :sender_id, :sent_at, :token

  belongs_to :sender, :class_name => "User"
  has_one :recipient, :class_name => "User"

  VALID_EMAIL_REGEX = /\A[\w+\-.]+@[a-z\d\-.]+\.[a-z]+\z/i

  before_create :generate_token

  private

    def generate_token
      self.token = Digest::SHA1.hexdigest([Time.now, rand].join)
    end

end
Was it helpful?

Solution

This should work.

def follow_inviter
  if invitation = Invitation.find_by_recipient_email(email)
    follow!(invitation.sender)
  end
end

But your models associations are not well defined. For example has_one :recipient, :class_name => "User" in the Invitation expects that there is a recipient_id in the table, but is not. You should review that.

OTHER TIPS

I might be wrong, I'm a junior rails developer, but it looks like where you have inviters = Invitation.find_by_sender_id you should have something like this inviters = Invitation.find_by_sender_id(id_of_sender) where id_of_sender is the id of the person who sent the invitation.

The find_by_sender_id takes 1 argument (the ID of the sender to be found) and that is why you get the error wrong number of arguments (0 for 1).

Also for what it's worth, I'm pretty sure the find_by_*_id methods, where * is a model in your database, are deprecated. Rails 4 uses something like Invitation.find(id_of_sender). When you call the find method on an active record model, it takes an id as a parameter.

You can also use Invitation.find_by(email: 'user@example.com') to find records based on any property you give them.

Apologies if I am misunderstanding your question... I have a similar requirement, where one user can mark another as a 'favorite' user (i.e. users table has a self-relationship)

To implement this, I added a table called user_favorite like this:

db\schema.rb

  create_table "user_favorites", :id => false, :force => true do |t|
    t.integer "user_id"
    t.integer "favorite_user_id"
  end

  add_index "user_favorites", ["user_id"], :name => "index_user_favorites_on_user_id"

app\models\user.rb

class User < ActiveRecord::Base
  has_and_belongs_to_many       :favorite_users, :class_name => 'User', :join_table => "user_favorites", :foreign_key => "user_id", :association_foreign_key => "favorite_user_id"

  def is_favorite?(user)
    self.favorite_users.include?(user)
  end

  def toggle_favorite(favorite_user)
    if favorite_user
      if self.favorite_users.include?(favorite_user)
        self.favorite_users.delete favorite_user
      else
        self.favorite_users << favorite_user
      end
    end  
  end
end
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top