1.before we do the UI, we need to populate database.
we will write a rake task to do this:
namespace :db do desc "populate database" task :populate => :environment do Rake:Task["db:reset"].invoke make_users make_microposts make_relationships end end def make_users admin = User.create!(:name => "fdf", :email => "fjds@jfd.com", :pass...) admin.toggle!(:admin) # add 99 sample users end def make _microposts User.all(:limit => 6).each do |u| 50.times do content = ...... u.microposts.create!(:content => content) end end end def make_relationships users = User.all user = users.first following = users[1..50] followers = users[3..40] following.each { |followed| user.follow!(followed) } followers.each { |follower| follower.follow!(user)} end
2. next, we will do the partial showing the following and followers number of a user.
since the two numbers are links, the following number will link to the following user list page.
the followers number link will link to the follower list, so we first prepare the url for the two pages.
both the page belong to :users resources.
here is how we define the REST route:
resources :users do member do get :following, followers end end
this part of code will create ulr like this:
users/1/following users/1/followers
and the following named routes:
following_user_path(1) followers_user_path(1)
to make the url work, we still need to define
def following
render 'show_follow'
end
def followers
render 'show_follow'
end
in users controller.
and of course, the show_follow.html.erb should be in app/views/users
another kind of resoures routes is called collection:
resources :users do collection do get :tigers end end
this will create url:
users/tigers tigers_users_path
3. after preparing routes, we will write test for the partial, since it will appear on user profile page and home page, so we will take this chance to refactor the test code in home page controller test, taking into account user signing in.
describe "when signed in" do before :each do @user = test_sign_in(Factory(:user)) other_user = Factory(:user, :email => Factory.next(:email)) other_user.follow! @user end it "should have the right following and followers count" do get :home response.should have_selector('a', :href => following_user_path(@user), :content => "0 following") response.should have_selector('a', :href => followers_user_path(@user), :content => "1 follower") end end
4. next we will do the stats partial:
<% @user ||= current_user %> <div class="stats"> <table summary="User stats"> <tr> <td> <a href="<%= following_user_path(@user) %>"> <span id="following" class="stats"> <%= @user.following.count %> following </span> </a> </td> <td> <a href="<%= followers_user_path(@user) %>"> <span id="followers" class="stats"> <%= pluralize(@user.followers.count, "follower") %> </span> </a> </td> </tr> </table> </div>
pay special attention to the css id attr, it will be used for ajax, which access elements using their unique ids.
5. next, we can include the partial into the home page:
<% if signed_in? %> . . . <%= render 'shared/user_info' %> <%= render 'shared/stats' %> </td> </tr> </table> <% else %> . . . <% end %>
6. next, we will prepare the follow/unfollow form button partial:
<% unless current_user?(@user) %> <div id="follow_form"> <% if current_user.following?(@user) %> <%= render 'unfollow' %> <% else %> <%= render 'follow' %> <% end %> </div> <% end %>
7. next, we will prepare the routes for relationship resource:
resources :relationships, :only => [:create, :destroy]
8. ok now we can do the follow/unfollow partial.
<%= form_for current_user.relationships.build(:followed_id => @user.id) do |f| %> <div><%= f.hidden_field :followed_id %></div> <div class="actions"><%= submit_tag 'follow' %></div> <% end %>
note, in the follow partial:
a. we new a relationship object, pass it as the param of form_for.
b. in this form, we only have a follow button.
c. but when user click this button, we need to make sure the form data include a param of
relationship[followed_id],
so we have to add a hidden field.
you may wondering, why I didn't input value into the hidden field, but it has data of user.id?
because of the build method, you already assign value to :followed_id, so the hidden field already has value of @user.id.
then is the unfollow partial:
<%= form_for current_user.relationships.find_by_followed_id(@user), :html => { :method => :delete } do |f| %> <div class="actions"><%= f.submit "Unfollow" %></div> <% end %>
note, we don't need to hidden field here, since we only need the id to delete a object.
next we can put the stats partial and follow/unfollow partials into profile pages.
9. next, we will make following page and followers page.
first, we will make the link to following and followers page work, so first write test:
describe UsersController do . . . describe "follow pages" do describe "when not signed in" do it "should protect 'following'" do get :following, :id => 1 response.should redirect_to(signin_path) end it "should protect 'followers'" do get :followers, :id => 1 response.should redirect_to(signin_path) end end describe "when signed in" do before(:each) do @user = test_sign_in(Factory(:user)) @other_user = Factory(:user, :email => Factory.next(:email)) @user.follow!(@other_user) end it "should show user following" do get :following, :id => @user response.should have_selector("a", :href => user_path(@other_user), :content => @other_user.name) end it "should show user followers" do get :followers, :id => @other_user response.should have_selector("a", :href => user_path(@user), :content => @user.name) end end end end
next, we will write code to make the test pass.
we need to add two new actions to users controller.
def following @title = "Following" @user = User.find(params[:id]) @users = @user.following.paginate(:page => params[:page]) render 'show_follow' end def followers @title = "Followers" @user = User.find(params[:id]) @users = @user.followers.paginate(:page => params[:page]) render 'show_follow' end .
next, we will do the show_follw view:
<table summary="Information about following/followers"> <tr> <td class="main"> <h1><%= @title %></h1> <% unless @users.empty? %> <ul class="users"> <%= render @users %> </ul> <%= will_paginate @users %> <% end %> </td> <td class="sidebar round"> <strong>Name</strong> <%= @user.name %><br /> <strong>URL</strong> <%= link_to user_path(@user), @user %><br /> <strong>Microposts</strong> <%= @user.microposts.count %> <%= render 'shared/stats' %> <% unless @users.empty? %> <% @users.each do |user| %> <%= link_to gravatar_for(user, :size => 30), user %> <% end %> <% end %> </td> </tr> </table>
another thing to note, in the users controller, for the before filter of :authenticate,
we change from :only to :except.
before_filter :authenticate, :except => [:show, :new, :create]
10. next, we will try to make follow and unfollow button work.
since follow is creating a relationship, and unfollow is destroying a relationship, so we just need to add
create and destroying methods to relationships controller.
let's start from TDD!!!
require 'spec_helper' describe RelationshipsController do describe "access control" do it "should require signin for create" do post :create response.should redirect_to(signin_path) end it "should require sign in for destroy" do delete :destroy, :id => 1 response.should redirect_to(signin_path) end end describe "POST 'create'" do before :each do @user = test_sign_in(Factory(:user)) @followed = Factory(:user, :email => Factory.next(:email)) end it "should create a relationship" do lambda do post :create, :relationship => { :followed_id => @followed } response.should be_redirect end.should change(Relationship, :count).by(1) end end describe "DELETE 'destroy'" do before :each do @user = test_sign_in(Factory(:user)) @followed = Factory(:user, :email => Factory.next(:email)) @user.follow!(@followed) @relationship = @user.relationships.find_by_followed_id(@followed) end it "should destroy a relationship" do lambda do delete :destroy, :id => @relationship response.should be_redirect end.should change(Relationship, :count).by(-1) end end end
now we can write create and destroy method to make this test pass:
class RelationshipsController < ApplicationController before_filter :authenticate def create @user = User.find(params[:relationship][:followed_id]) current_user.follow!(@user) redirect_to @user end def destroy @user = Relationship.find(params[:id]).followed current_user.unfollow!(@user) redirect_to @user end end
发表评论
-
12.3.3 scaling issue of the status feed
2011-10-30 17:54 801the problem of the implementati ... -
12.3 the status feed
2011-10-30 15:34 8501. we need to get all the micro ... -
12.2 a working follow button with Ajax
2011-10-29 18:10 9031. in the last chapter, in the ... -
12. following user, 12.1 relationship model
2011-10-18 14:29 7371. we need to use a relationshi ... -
11.3 manipulating microposts.
2011-10-17 15:31 8861. since all micropost actions ... -
11.2 show microposts.
2011-10-17 12:01 6941. add test to test the new use ... -
11.1 user micropost -- a micropost model.
2011-10-17 10:43 10951. we will first generate a mic ... -
10.4 destroying users.
2011-10-16 15:47 724in this chapter, we will add de ... -
10.3 showing users list
2011-10-15 20:41 762in this chapter, we will do use ... -
10.2 protect pages.
2011-10-15 15:11 645again, we will start from TD ... -
10.1 updating users.
2011-10-14 18:30 6971. git checkout -b updating-use ... -
9.4 sign out
2011-10-13 15:21 724whew!!!, last chapter is a long ... -
9.3 sign in success.
2011-10-12 15:39 7351. we will first finish the cre ... -
9.1 about flash.now[:error] vs flash[:error]
2011-10-12 15:37 714There’s a subtle difference ... -
9.2 sign in failure
2011-10-12 12:19 652start from TDD!!! 1. requir ... -
9.1 sessions
2011-10-12 10:00 640a session is a semi-permanent c ... -
what test framework should you use?
2011-10-11 16:56 0for integration test, i have no ... -
what test framework should you use?
2011-10-11 16:56 0<p>for integration test, ... -
8.4 rspec integration tests
2011-10-11 16:53 707in integration test, you can te ... -
8.3 sign up success
2011-10-11 14:39 772Chapter 8.3 this part, we will ...
相关推荐
`User`模型中定义`followers`和`following`方法,表示一个用户可以关注多个用户,也可以被多个用户关注。 7. **中间件(Middleware)** 可以创建自定义中间件,用于验证用户是否登录才能进行关注操作。例如,`auth...
This is beneficial for engagement, obtaining followers and increasing marketshare as people love to participate in cool and useful sites. Engagement of other people and building your coupon tribe ...
The API for social features, such as followers and notifications, is also explained. Chapter 7, Business Logic – Supporting Business Processes, explains how to program business logic on the server ...
With the spread of fast internet connections streaming television gains more and more followers. Consequently the DVBViewer features not only playback and recording of DVB-S/C/T but also IPTV. Are ...
粉丝(followers),关注(following),和帖子(updates). . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 54 身份验证(Authentication) . . . . . . . . . . . . . . . . . . . . . . . ...
粉丝(followers),关注(following),和帖子(updates). . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 54 身份验证(Authentication) . . . . . . . . . . . . . . . . . . . . . . ....
They do, by choice, largely omit the theory of graph minors (developed by Paul Seymour and Neil Robertson and followers), which certainly now deserves a monographic treatment of its own. Summing up: ...
each embodies a hypothesis about the nature of meaning making and creativity that encourages its followers to become willing test subjects and eager consumers of automated creation. Some bots are as ...
@endforeach ``` 通过以上步骤,我们已经在Laravel5中构建了一个基本的多形跟随系统。这个系统允许用户关注其他用户和内容,同时也方便地查询关注关系。在实际项目中,可能还需要处理更多的细节,比如添加通知功能...
在PyPI官网上,我们可以找到名为"free-soundcloud-followers-generator-1.2.0.tar.gz"的资源,这是一款专门针对音乐分享平台SoundCloud的工具,用于生成关注者。这个压缩包包含了该工具的1.2.0版本。 该资源的完整...
[工作,2019年9月]使用Like4Like和Follow4Follow的免费Instagram Likes和Followers网络应用程序 通过与其他用户交换喜欢数来获得免费的Instagram喜欢数。 1.通过喜欢的帖子赚钱2.在您的帖子上花钱购买喜欢的商品3.在...
### 领导者/跟随者模式 (Leader/Followers Pattern) #### 模式概述 领导者/跟随者架构模式提供了一种高效的并发模型,在该模型中,多个线程轮流共享一组事件源,以便检测、解复用、分发并处理在这些事件源上发生的...
"Leader-Followers多机器人编队控制方法" 本文主要介绍了一种Leader-Followers多机器人编队控制方法,该方法利用距离-角度(/飞)控制方案,仅利用跟随机器人(Followers)观测(Leader)领航机器人的纯角度信息,...
github activity, check for news and updates. The application implements secure login with OAuth to access user data. In the main screen user is able to monitor daily contributions activity placed in ...
- The *religion* provides guidance and comfort to its followers. #### religious 宗教的、虔诚的 (pious) - **定义与用法**:与宗教相关的或表现出极大虔诚态度的。 - **例句**: - The *religious* ...
secondaryjoin=(followers.c.followed_id == id), backref=db.backref('followers', lazy='dynamic'), lazy='dynamic' ) ``` 3. **数据库变更迁移** 使用Flask-SQLAlchemy的命令`flask db migrate`和`flask ...