- AngularJS : 1.6.5
- Bootstrap : 3.x
- UI Bootstrap : 2.5.0
Google Maps,AngularJS
1)Rails route
$ vi config/routes.rb
match '/app/relationships', to: 'relationships#create', via: 'post' match '/app/relationships', to: 'relationships#destroy', via: 'delete'
2)Rails controller
$ vi app/controllers/relationships_controller.rb
class RelationshipsController < ApplicationController
before_action :signed_in_user
def create
remember_token = User.encrypt(cookies[:remember_token])
current_user ||= User.find_by(remember_token: remember_token)
@user = User.find(user_params[:id])
current_user.follow!(@user)
head :no_content
end
def destroy
remember_token = User.encrypt(cookies[:remember_token])
current_user ||= User.find_by(remember_token: remember_token)
@user = User.find(user_params[:id])
current_user.unfollow!(@user)
head :no_content
end
private
def user_params
params.permit(:id)
end
def signed_in_user
remember_token = User.encrypt(cookies[:remember_token])
current_user ||= User.find_by(remember_token: remember_token)
if current_user.nil?
render status: :unauthorized
end
end
end
3)AngularJS "relationshipsResource" service
$ vi app/assets/javascripts/mymodule.js.erb
myModule.factory("relationshipsResource", function($resource) {
return $resource("/app/relationships",{},
{
'create': { method: 'POST' },
'destroy': { method: 'DELETE' }
}
);
});
4)AngularJS controller
$ vi app/assets/javascripts/mymodule.js.erb
myModule.controller("UsersShowCtrl", function($scope, $routeParams, userResource, flashService, $filter, micropostsResource, $q, sessionResource, relationshipsResource) {
.....
$scope.follow = function(id) {
function success(response) {
$scope.flg_unfollow = true;
sessionResource.current_user({}, function(response) {
flashService.setUser(response);
});
$scope.$emit("$routeChangeSuccess");
}
function failure(response) {
console.log("follow error");
}
var user_data = {
id: id
};
relationshipsResource.create(user_data, success, failure);
};
$scope.unfollow = function(id) {
relationshipsResource.destroy({ id: id }, function(response) {
$scope.flg_unfollow = false;
sessionResource.current_user({}, function(response) {
flashService.setUser(response);
});
$scope.$emit("$routeChangeSuccess");
});
};
1)AngularJS template view
$ vi app/assets/templates/users/show.html.erb
<div class="col-xs-6 col-sm-8">
<div ng-show="!flg_follers && chkSignin() &&
chkSignin().user.id != user_info.user.id" class="row">
<div ng-show="flg_unfollow">
<a class="btn btn-large btn-primary" href="#"
ng-click="unfollow(user_info.user.id)">
Unfollow
</a>
</div>
<div ng-hide="flg_unfollow">
<a class="btn btn-large btn-primary" href="#"
ng-click="follow(user_info.user.id)">follow</a>
</div>
</div>
2)AngularJS controller
$ vi app/assets/javascripts/mymodule.js.erb
myModule.controller("UsersShowCtrl", function($scope, $routeParams, userResource, flashService, $filter, micropostsResource, $q) {
var qgetUser = function(deferred) {
if (flashService.getUser()) {
var quser_info = flashService.getUser();
deferred.resolve(quser_info);
} else {
sessionResource.current_user({}, function(response) {
if (response.user.id) {
var quser_info = response;
} else {
var quser_info = { user: {id: 0} };
}
flashService.setUser(quser_info);
deferred.resolve(quser_info);
});
}
}
var chkUnfollow = function() {
$scope.flg_unfollow = false;
var deferred = $q.defer();
deferred.promise.then(function (result) {
var user_signin = result.user.id;
for (var i=0; i<=$scope.user_info.followers.length; i++) {
if ($scope.user_info.followers[i] && $scope.user_info.followers[i].id == user_signin) {
$scope.flg_unfollow = true;
}
}
},function (reason) {
console.log("user_signin-Error");
},function (reason) {
console.log("user_signin");
})
qgetUser(deferred);
};
userResource.show({ id: $routeParams.id }, function(response) {
$scope.user_info = response;
chkUnfollow();
........
});
(1)Home page
1)follower stats parts
$ vi app/assets/templates/static_pages/home.html.erb
<div class="stats">
<a href="#" ng-click="following()">
<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>2)following and followers list parts
$ vi app/assets/templates/static_pages/home.html.erb
.....
<div class="col-sm-8">
<div ng-show="flg_follers" class="row">
<h1 class="text-center">{{follow_title}}</h1>
<ul ng-repeat="f_user in f_users" class="users">
<li><img alt="{{f_user.name}}" src="https://secure.gravatar.com/avatar/{{hash(f_user.email)}}?s=52" />
<a href="/users/{{f_user.id}}">{{f_user.name}}</a>
</li>
</ul>
</div>
<h3>Micropost Feed</h3>
.....3)AngularJS controller
$ vi app/assets/javascripts/mymodule.js.erb
myModule.controller("HomeCtrl", function($scope, flashService, micropostsResource, sessionResource, $filter) {
.....
$scope.chkSignin = function() {
return flashService.getUser();
};
.....
$scope.flg_follers = false;
$scope.following = function() {
$scope.flg_follers = true;
$scope.follow_title = "Following";
$scope.f_users = $scope.chkSignin().followed_users;
};
$scope.followers = function() {
$scope.flg_follers = true;
$scope.follow_title = "Followers";
$scope.f_users = $scope.chkSignin().followers;
};
$scope.hash = function(email) {
return md5(email.toLowerCase());
};
(2)User Profile page
1)follower stats parts
$ vi app/assets/templates/users/show.html.erb
<div class="col-xs-6 col-sm-4">
<h3>
<img alt="{{user_info.user.name}}"
src="{{user_info.gravatar_url}}?s=60"
class="gravatar" />
{{user_info.user.name}}
</h3>
<span ng-show="flg_follers">
<a href="#" ng-click="viewProfile()">
view my profile
</a>
</span><br />
<div class="stats">
<a href="#" ng-click="following()">
<strong id="following" class="stat">
{{user_info.followed_users.length}}
</strong>
following
</a>
<a href="#" ng-click="followers()">
<strong id="followers" class="stat">
{{user_info.followers.length}}
</strong>
followers
</a>
</div>
</div>2)following and followers list parts
$ vi app/assets/templates/users/show.html.erb
<div class="col-xs-6 col-sm-8">
<div ng-show="flg_follers" class="row">
<h3>{{follow_title}}</h3>
<ul ng-repeat="f_user in f_users" class="users">
<li><img alt="{{f_user.name}}"
src="https://secure.gravatar.com/avatar/{{hash(f_user.email)}}?s=52" />
<a href="/users/{{f_user.id}}">{{f_user.name}}</a>
</li>
</ul>
</div>
<div ng-hide="flg_follers" class="row">
<h3>Microposts({{user_info.microposts.length}})</h3>
.......3)AngularJS controller
$ vi app/assets/javascripts/mymodule.js.erb
myModule.controller("UsersShowCtrl", function($scope, $routeParams, userResource, flashService, $filter, micropostsResource, $q) {
.....
userResource.show({ id: $routeParams.id }, function(response) {
$scope.user_info = response;
.......
});
$scope.flg_follers = false;
$scope.following = function() {
$scope.flg_follers = true;
$scope.follow_title = "Following";
$scope.f_users = $scope.user_info.followed_users;
};
$scope.followers = function() {
$scope.flg_follers = true;
$scope.follow_title = "Followers";
$scope.f_users = $scope.user_info.followers;
};
$scope.viewProfile = function() {
$scope.flg_follers = false;
};
$scope.hash = function(email) {
return md5(email.toLowerCase());
};
1)Rails controller
$ vi app/controllers/users_controller.rb
def show
user = User.find(params[:id])
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,
followed_users: user.followed_users,
followers: user.followers
}
render json: @user_info
end
2)AngularJS template view
$ vi app/assets/templates/users/show.html.erb
<div class="col-xs-6 col-sm-4">
<h3>
<img alt="{{user_info.user.name}}" src="{{user_info.gravatar_url}}" />
{{user_info.user.name}}
</h3>
<div class="stats">
<a href="#">
<strong id="following" class="stat">
{{user_info.followed_users.length}}
</strong>
following
</a>
<a href="#">
<strong id="followers" class="stat">
{{user_info.followers.length}}
</strong>
followers
</a>
</div>
</div>
(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;
}
}
(1)Rails controller
$ vi app/controllers/microposts_controller.rb
before_action :signed_in_user, only: [:create, :destroy]
before_action :correct_user, only: :destroy
def destroy
Micropost.find(params[:id]).destroy
head :no_content
end
(2)add link to views
$ vi app/assets/templates/static_pages/home.html.erb
$ vi app/assets/templates/users/show.html.erb
.....
<small class="text-muted">Posted {{mp.created_at | date:'medium'}}</sm
all>
<span ng-show="chkSignin().user.id == mp.user_id"><a href="" ng-click="delete(mp.id)">delete</a></span>
.....(3)AngularJS controller
1)User Profile page "UsersShowCtrl" controller
$ vi app/assets/javascripts/mymodule.js.erb
myModule.controller("UsersShowCtrl", function($scope, $routeParams, userResource,flashService,micropostsResource) {
$scope.chkSignin = function() {
return flashService.getUser();
};
$scope.delete = function(id) {
micropostsResource.destroy({ id: id });
userResource.show({ id: $routeParams.id }, function(response) {
$scope.user_info = response;
$scope.totalitems = $scope.user_info.microposts.length;
microposts = $filter('orderBy')($scope.user_info.microposts,'created_at',true);
$scope.currentitems = microposts.slice(start,end);
flashService.setUser(response);
});
};
});
2)Home page "HomeCtrl" controller
$scope.delete = function(id) {
micropostsResource.destroy({ id: id });
sessionResource.current_user({}, function(response) {
tmp_feed = response.feed;
$scope.totalitems = tmp_feed.length;
feed_items = $filter('orderBy')(tmp_feed,'created_at',true);
$scope.currentitems = feed_items.slice(start,end);
flashService.setUser(response);
});
};
1)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>
<div class="col-sm-8">
<h3>Micropost Feed</h3>
<ol class="microposts">
<li ng-repeat="mp in currentitems">
...........
</li>
</ol>
<pagination total-items="totalitems"
ng-model="currentpage"
max-size="maxsize"
items-per-page="itemsperpage"
class="pagination-sm"
previous-text="Previous"
next-text="Next"
first-text="First"
last-text="Last"
boundary-links="true">
</pagination>
</div>
</div>
2)AngularJS controller
$ vi app/assets/javascripts/mymodule.js.erb
myModule.controller("HomeCtrl", function($scope, flashService, micropostsResource, sessionResource, $filter) {
....
$scope.submit = function() {
function success(response) {
sessionResource.current_user({}, function(response1) {
var current_user = response1;
$scope.totalitems = current_user.feed.length;
feed_items = $filter('orderBy')(current_user.feed,'created_at',true);
$scope.currentitems = feed_items.slice(start,end);
flashService.setUser(current_user);
});
flashService.push(msg);
$scope.$emit("$routeChangeSuccess");
}
function failure(response) {
........
}
micropostsResource.create($scope.micropost, success, failure);
};
.........
var feed_items = [];
$scope.maxsize = 5;
$scope.itemsperpage = 8;
$scope.currentpage = 1;
var start = 0;
var end = start + $scope.itemsperpage;
sessionResource.current_user({}, function(response) {
if (response.feed) {
var tmp_feed = response.feed;
$scope.totalitems = tmp_feed.length;
feed_items = $filter('orderBy')(tmp_feed,'created_at',true);
$scope.currentitems = feed_items.slice(start,end);
}
});
$scope.$watch('currentpage', function() {
start = ($scope.currentpage - 1) * $scope.itemsperpage;
end = start + $scope.itemsperpage;
$scope.currentitems = feed_items.slice(start,end);
},true);
});