1. we need to use a relationships table to stand for the following relationship:
has_many :following, :through => :relationships, :source => "followed_id"
2. then
$ rails generate model Relationship follower_id:integer followed_id:integer
3. we need to add index to the table
add_index :relationships, :follower_id add_index :relationships, :followed_id add_index :relationships, [:follower_id, :followed_id], :unique => true
note the last index is a composite one, and is unique.
4. then rake db:migrate
rake db:test:prepare
5. we will follow a good practice here:
remember, it is good to define attr_accessible for every model to avoid mass assignment to some attrs that you don't want user to touch.
so here, we know we only want user to modify the followed_id, never the follower_id.
so
attr_accessible :followed_id
6. how to create a relationship:
we should use the user association to create relationship:
user.relationships.create!(:followed_id => "")
7. below is the test spec of relationship model:
describe Relationship do before(:each) do @follower = Factory(:user) @followed = Factory(:user, :email => Factory.next(:email)) @relationship = @follower.relationships.build(:followed_id => @followed.id) end it "should create a new instance given valid attributes" do @relationship.save! end end
note, @relationship.save! will throw an exception if fail.
we user @follower.relationships.build() to create a relationship.
in the user model, we also need to test it respond to the relationships method.
describe "relationships" do before(:each) do @user = User.create!(@attr) @followed = Factory(:user) end it "should have a relationships method" do @user.should respond_to(:relationships) end end
8. when we define
class User has_many :microposts end class Micropost belongs_to :user end
because microposts table has a user_id to identify the user, so this is a foreign key, which is connecting two tables, and when the foreign key for a user object is user_id, rails can infer the association auto, by default, rails expects a foreign key of user_id, where user is the lower case of class User.
but now, although we are dealing with users, they are now identified with the foreign key follower_id, so we have to tell rails, that follower_id is a foreign key.
class User has_many :relationships, :foreign_key => "follower_id", :dependent = :destroy end
9. next, the relationship should belong to users, one relationship belong to 2 users.
a follower and a followed user.
let write test:
describe Relationship do . . . describe "follow methods" do before(:each) do @relationship.save end it "should have a follower attribute" do @relationship.should respond_to(:follower) end it "should have the right follower" do @relationship.follower.should == @follower end it "should have a followed attribute" do @relationship.should respond_to(:followed) end it "should have the right followed user" do @relationship.followed.should == @followed end end end
next, we will make this test pass:
belongs_to :follower, :class_name => "User" belongs_to :followed, :class_name => "User"
10. next we will add some validations to the relationship model:
the test is:
describe Relationship do . . . describe "validations" do it "should require a follower_id" do @relationship.follower_id = nil @relationship.should_not be_valid end it "should require a followed_id" do @relationship.followed_id = nil @relationship.should_not be_valid end end end
next, let's add the validations:
validates :follower_id, :presence => true validates :followed_id, :presence => true
11. following:
the user object should respond to following method:
describe User do . . . describe "relationships" do before(:each) do @user = User.create!(@attr) @followed = Factory(:user) end it "should have a relationships method" do @user.should respond_to(:relationships) end it "should have a following method" do @user.should respond_to(:following) end end end
to make it pass, we need this line of code:
has_many :followeds, :through => :relationships
rails then can deduce it should use "followed_id" assemble an array.
but as you see, followeds is awkward english, so we want to overwrite the default name:
has_many :following, :through => :relationships, :source => :followed
then we will add some utility methods:
describe User do . . . describe "relationships" do . . . it "should have a following? method" do @user.should respond_to(:following?) end it "should have a follow! method" do @user.should respond_to(:follow!) end it "should follow another user" do @user.follow!(@followed) @user.should be_following(@followed) end it "should include the followed user in the following array" do @user.follow!(@followed) @user.following.should include(@followed) end end end
@user.following.include?(@followed).should be_true
def following?(followed) relationships.find_by_followed_id(followed) end def follow!(followed) relationships.create!(:followed_id => followed.id) end
it "should have an unfollow! method" do @user.should respond_to :unfollow! end it "should unfollow a user" do @user.follow!(@followed) @user.unfollow!(@followed) @user.should_not be_following(@followed) end
def unfollow!(followed) relationships.find_by_followed_id(followed).destroy end
it "should have a reverse_relationships method" do @user.should respond_to(:reverse_relationships) end it "should have a followers method" do @user.should respond_to(:followers) end it "should include the follower in the followers array" do @user.follow!(@followed) @followed.followers.should include(@user) end
has_many :reverse_relationships, :foreign_key => "followed_id", :class_name => "Relationship", :dependent => :destroy
has_many :followers, :through => :reverse_relationships, :source => :follower
发表评论
-
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 8491. we need to get all the micro ... -
12.2 a working follow button with Ajax
2011-10-29 18:10 9021. in the last chapter, in the ... -
12.2 a web interface for following and followers.
2011-10-28 22:14 8681.before we do the UI, we need ... -
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 10941. 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 ...
相关推荐
Then the path coordinate model is converted into chained form and a controller is given to perform path following. The path coordinate model introduces a new parameter to the system: the curvature of...
首先,"car_following_model"是指汽车跟车模型,这是交通流理论中的一个重要组成部分,用来描述一辆车如何根据前方车辆的运动状态调整自己的速度和行驶距离。这类模型通常包括驾驶员的反应时间、车辆的动力学特性...
In the Entity-Relationship model, the degree of a relationship specifies which of the following? (a) The cardinality ratio of the relationship (b) The number of integrity constraints required to ...
3.4 A Patrol Bot Example.........................................................................................12 3.5 The Patrol Bot using a Standard Script.............................................
2.2.1 BaseGameController.cs.....................................12 2.2.1.1 Script Breakdown................................14 viii Contents 2.2.2 Scene Manager............................................
Chapter 12. Working with NoSQL databases 12.1. Persisting documents with MongoDB 12.1.1. Enabling MongoDB 12.1.2. Annotating model types for MongoDB persistence 12.1.3. Accessing MongoDB with Mongo...
, 3, 15, 12, 7, 2> , 2, 4, 15, 20, 5> Longest Common Subsequence (LCS). The following are some instances. X: xzyzzyx Y: zxyyzxz X:MAEEEVAKLEKHLMLLRQEYVKLQKKLAETEKRCALLAAQANKESSSESFISRLLAIVAD Y:...
following = user.following.all() # 更多逻辑... ``` #### 使用 Redis 存储和检索数据 对于需要高速读写操作的场景,如行为流中的实时更新,可以考虑使用 Redis 这样的键值存储数据库。Redis 提供了丰富的数据...
超强的电脑去广告软件,可以自定义规则 Licensor: Murray Hurps Software Pty Ltd, Australia Permission to use this software is conditional upon the user agreeing to the terms set ...12. This agreement shall
// The following changes were made to the default settings in the Device Editor: // // Select User Modules // o Select CSD_1 & SPIS_1 user modules. // o In this example, these UMs are renamed as...
The core utilities, known as userland, provide the interface that identifies FreeBSD, both user interface, shared libraries and external interfaces to connecting clients. Currently, 162 people are ...
It covers the following chapters: Database Systems,Database Systems Concepts and Architecture, Data Modelling Using ER Model, Relational Model, Normalization, Database Access and Security, SQL Using ...
Following projects source code is included in this package. 1. CyAPI C++ Static Library. 2. CyUSB C# DLL. Following directories are included this package. 1.CyAPI => library => cpp This directory ...
The pre-trained model of the convolutional neural network is able to detect pre-trained classes including the data set from VOC and COCO, or you can also create a network with your own detection ...
Following the traditional software development process, it first selects suitable development platforms and languages, conducts demand analysis, and designs the database structure. Based on the ...
As a new energy technology with distributed generation prospects, the load-following capability of solid oxide fuel cell (SOFC) systems is one of the main obstacles for commercial operation. This ...
have been proposed, following different philosophies and exhibiting varying performances. The purpose of this article is to bring a comprehensive overview of them, in terms of their motivation, ...