Web Programming examples

Google Maps,AngularJS

Ruby on Rails Tutorial show follower stats with AngularJS

(1)Rails model, association, validation

1)"Relationship" model

$ rails generate model Relationship follower_id:integer followed_id:integer

2)add indices for the relationships table

$ vi db/migrate/…._create_relationships.rb

class CreateRelationships < ActiveRecord::Migration
  def change
    create_table :relationships do |t|
      t.integer :follower_id
      t.integer :followed_id

      t.timestamps
    end
    add_index :relationships, :follower_id
    add_index :relationships, :followed_id
    add_index :relationships, [:follower_id, :followed_id], unique: true
  end
end

3)migrate

$ bundle exec rake db:migrate

4)validation

$ vi app/models/relationship.rb

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

(2)User/followed_users associations

1)"relationship" model

$ vi app/models/relationship.rb

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

2)"user" model

$ vi app/models/user.rb

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

3)Utility methods for following

$ vi app/models/user.rb

  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

(3)User/followers associations

1)"relationship" model

$ more app/models/relationship.rb

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

2)"user" model

$ vi app/models/user.rb

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

(3)check by console

1.user instance

> user2=User.find_by(id: 2)
> user6=User.find_by(id: 6)

2."following?"

> user2.following?(user6)
 => nil
> user6.following?(user2)
 => nil

3."follow!"

> user2.follow!(user6)
   (0.2ms)  begin transaction
  SQL (0.3ms)  INSERT INTO "relationships" ("created_at", "followed_id", "follower_id", "updated_at") VALUES (?, ?, ?, ?)  [["created_at", "2015-07-24 08:17:13.716171"], ["followed_id", 6], ["follower_id", 2], ["updated_at", "2015-07-24 08:17:13.716171"]]
   (3.4ms)  commit transaction
 => #<Relationship id: 1, follower_id: 2, followed_id: 6, created_at: "2015-07-24 08:17:13", updated_at: "2015-07-24 08:17:13">

> user6.follow!(user2)

4."relationships", "reverse_relationships" association

> user2.relationships
 => #<ActiveRecord::Associations::CollectionProxy [#<Relationship id: 1, follower_id: 2, followed_id: 6, created_at: "2015-07-24 08:17:13", updated_at: "2015-07-24 08:17:13">]>

> user2.reverse_relationships
  Relationship Load (0.2ms)  SELECT "relationships".* FROM "relationships"  WHERE "relationships"."followed_id" = ?  [["followed_id", 2]]
 => #<ActiveRecord::Associations::CollectionProxy [#<Relationship id: 2, follower_id: 6, followed_id: 2, created_at: "2015-07-24 08:17:54", updated_at: "2015-07-24 08:17:54">]>

> Relationship.all
  Relationship Load (0.2ms)  SELECT "relationships".* FROM "relationships"
 => #<ActiveRecord::Relation [#<Relationship id: 1, follower_id: 2, followed_id: 6, created_at: "2015-07-24 08:17:13", updated_at: "2015-07-24 08:17:13">, #<Relationship id: 2, follower_id: 6, followed_id: 2, created_at: "2015-07-24 08:17:54", updated_at: "2015-07-24 08:17:54">]>

> user2.relationships.find_by(followed_id: user6)
  Relationship Load (0.1ms)  SELECT  "relationships".* FROM "relationships"  WHERE "relationships"."follower_id" = ? AND "relationships"."followed_id" = 6 LIMIT 1  [["follower_id", 2]]
 => #<Relationship id: 1, follower_id: 2, followed_id: 6, created_at: "2015-07-24 08:17:13", updated_at: "2015-07-24 08:17:13">

5."followed_users", "followers" association

> user2.followed_users.count
 => 1
> user2.followers.count
 => 1
> user6.followed_users.count
 => 1
> user6.followers.count
 => 1
> user2.followers.all

> user2.followed_users.all

(4)show following and followers

1)Rails controller

$ vi app/controllers/sessions_controller.rb

  def create
    user = User.find_by(email: session_params[:email].downcase)
    if user && user.authenticate(session_params[:password])
      remember_token = User.new_remember_token
      cookies.permanent[:remember_token] = remember_token
      user.update_attribute(:remember_token, User.encrypt(remember_token))
      gravatar_id = Digest::MD5::hexdigest(user.email.downcase)
      microposts = user.microposts
      @user_info = {
        user: user,
        gravatar_url: "https://secure.gravatar.com/avatar/#{gravatar_id}",
        microposts: microposts,
        feed: user.feed,
        followed_users: user.followed_users,
        followers:  user.followers
      }
      render json: @user_info, status: :accepted, location: user
    else
......
  def current_user
    remember_token = User.encrypt(cookies[:remember_token])
    current_user ||= User.find_by(remember_token: remember_token)
    if current_user
      gravatar_id = Digest::MD5::hexdigest(current_user.email.downcase)
      microposts = current_user.microposts
      @user_info = {
        user: current_user,
        gravatar_url: "https://secure.gravatar.com/avatar/#{gravatar_id}",
        microposts: microposts,
        feed: current_user.feed,
        followed_users: current_user.followed_users,
        followers:  current_user.followers
      }
      render json: @user_info, status: :accepted
    else
      head :no_content
    end
  end

2)AngularJS template view

$ vi app/assets/templates/static_pages/home.html.erb

<div ng-controller="HomeCtrl">
  <div ng-show="chkSignin().user.id > 0" class="row">
......
    <div class="col-sm-4">
.........
      <div class="stats">
        <a href="#">
          <strong id="following" class="stat">
            {{chkSignin().followed_users.length}}
          </strong>
          following
        </a>
        <a href="#">
          <strong id="followers" class="stat">
            {{chkSignin().followers.length}}
          </strong>
          followers
        </a>
      </div>

3)css

$ vi app/assets/stylesheets/custom.css.scss

.stats {
  overflow: auto;
  border-top: 1px solid $grayLighter;
  a {
    float: left;
    padding: 0 10px;
    border-left: 1px solid $grayLighter;
    color: gray;
    &:first-child {
      padding-left: 0;
      border: 0;
    }
    &:hover {
      text-decoration: none;
      color: blue;
    }
  }
  strong {
    display: block;
  }
}