1. we will first generate a micropost model.
$ rails generate model Micropost content:string user_id:integer
note, if you the content is longer, you can use type "text" instead of string
2. next, since we expect to retrieve all microposts associated with a user, we need to add index on user_id and created_at columns.
add_index :microposts, [:user_id, :created_at]
also, note this line
t.timestamps
4. next, we will specify attr_accessible attrs.
we don't want user to edit the user_id attr through web, so we only add :content to attr_accessible
attr_accessible :content
5. but this will create a difficulty for us, how to assign the user id when create a micropost?
go on with this question.
we will create user/micropost associations.
we start from test, TDD, yes.
describe Micropost do before(:each) do @user = Factory(:user) @attr = { :content => "value for content" } end it "should create a new instance given valid attributes" do @user.microposts.create!(@attr) end describe "user associations" do before(:each) do @micropost = @user.microposts.create!(@attr) end it "should have a user attribute" do @micropost.should respond_to(:user) end it "should have the right associated user" do @micropost.user_id.should == @user.id @micropost.user.should == @user end end end
describe User do . . . describe "micropost associations" do before(:each) do @user = User.create(@attr) end it "should have a microposts attribute" do @user.should respond_to(:microposts) end end end
6. all this test can pass after we add belongs_to and has_many methods to user.rb and micropost.rb.
after adding the two methods, we will have these methods for use:
micropost.user Return the User object associated with the micropost. user.microposts Return an array of the user’s microposts. user.microposts.create(arg) Create a micropost (user_id = user.id). user.microposts.create!(arg) Create a micropost (exception on failure). user.microposts.build(arg) Return a new Micropost object (user_id = user.id).
note the last method, it will return a new object that is not saved yet, but the user_id is already assigned.
7. to test the microposts that belong to a user, we need to factory some sample micropost records:
Factory.define :micropost do |micropost| micropost.content = "foo bar" micropost.association = :user end
then in the test code, we can
@mp1 = Factory(:micropost, :user => @user, :created_at => 1.day.ago) @mp2 = Factory(:micropost, :user => @user, :created_at => 1.hour.ago)
you can see, factory not only allow us to mass assign to bypass attr_accessible,
it also allow us to assign created_at and updated_at.
for normal ActiveRecord, it won't alow us to do so, rails magic will assign the timestamp automatically.
here is the test code in user_spec.rb:
describe "micropost associations" do before(:each) do @user = User.create(@attr) @mp1 = Factory(:micropost, :user => @user, :created_at => 1.day.ago) @mp2 = Factory(:micropost, :user => @user, :created_at => 1.hour.ago) end it "should have a microposts attribute" do @user.should respond_to :microposts end it "should have the right microposts in the right order" do @user.microposts.should == [@mp2, @mp1] end end
to make it pass, we need to order the microposts:
default_scope :order => 'microposts.created_at DESC'
this is the first time we encounter scope, we will get familiar later.
note, we use
microposts.created_at
instead of
micropost.created_at
8. next, we will add test code to test that after destroying a user, the related micropost will be destroed automatically too.
it "should destroy associated microposts" do @user.destroy [@mp1, @mp2].each do |micropost| Micropost.find_by_id(micropost.id).should be_nil end end
notes:
Micropost.find_by_id(micropost.id)
will return nil if not found.
But
Micropost.find(micropost.id)
will raise an exception
lambda do Micropost.find(micropost.id) end.should raise_error(ActiveRecord::RecordNotFound)
9. the code to make the dependent destroy is very simple:
has_many :microposts, :dependent => :destroy
10. micropost validations:
again, start from test:
describe "validations" do it "should require a user id" do Micropost.new(@attr.should_not be_valid) end it "should require nonblank content" do @user.Microposts.build(:content => " ").should_not be_valid end it "reject long content" do @user.Microposts.build(:content => "a" * 141).should_not be_valid end end
note, when contruct a new micropost object using associated user, we use
build()
instead of
Micropost.new
发表评论
-
12.3.3 scaling issue of the status feed
2011-10-30 17:54 814the problem of the implementati ... -
12.3 the status feed
2011-10-30 15:34 8521. we need to get all the micro ... -
12.2 a working follow button with Ajax
2011-10-29 18:10 9091. in the last chapter, in the ... -
12.2 a web interface for following and followers.
2011-10-28 22:14 8751.before we do the UI, we need ... -
12. following user, 12.1 relationship model
2011-10-18 14:29 7441. we need to use a relationshi ... -
11.3 manipulating microposts.
2011-10-17 15:31 8931. since all micropost actions ... -
11.2 show microposts.
2011-10-17 12:01 6961. add test to test the new use ... -
10.4 destroying users.
2011-10-16 15:47 732in this chapter, we will add de ... -
10.3 showing users list
2011-10-15 20:41 768in this chapter, we will do use ... -
10.2 protect pages.
2011-10-15 15:11 655again, we will start from TD ... -
10.1 updating users.
2011-10-14 18:30 7041. git checkout -b updating-use ... -
9.4 sign out
2011-10-13 15:21 730whew!!!, last chapter is a long ... -
9.3 sign in success.
2011-10-12 15:39 7411. we will first finish the cre ... -
9.1 about flash.now[:error] vs flash[:error]
2011-10-12 15:37 722There’s a subtle difference ... -
9.2 sign in failure
2011-10-12 12:19 655start from TDD!!! 1. requir ... -
9.1 sessions
2011-10-12 10:00 642a 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 714in integration test, you can te ... -
8.3 sign up success
2011-10-11 14:39 775Chapter 8.3 this part, we will ...
相关推荐
oracle-instantclient11.1-basic-11.1.0.7.0-1.x86_64.rpm
oracle-instantclient11.1-devel-11.1.0.7.0-1.x86_64.rpm
oracle-instantclient-basic-11.1.0.1-1.x86_64.rpm
oracle-instantclient-sqlplus-11.1.0.1-1.i386.rpm
标题 "cudnn-11.1-windows-x64-v8.0.5.39.zip" 提供的是一款适用于Windows 10 64位操作系统的深度学习库CuDNN(CUDA Deep Neural Network)的特定版本。CuDNN是由NVIDIA开发的,用于加速深度神经网络(DNN)计算的高...
官网太难下 遂下了老版本后,上传分享
wps-office-11.1.0.10920-1.x86_64.rpm
Oracle官网下载太慢,还下不下来,只能下个老版本的了
浏览器插件,用于解决浏览器不能播放动画的问题flash-plugin-11.1.102.62-release.i386.rpm
oracle-instantclient-basic-11.1.0.1-1.i386.rpm
标题中的“cudnn-11.1-windows-x64-v8.0.4.30.zip”是指NVIDIA CUDA深度神经网络库(CuDNN)的一个特定版本,适用于CUDA 11.1和Windows 10 64位操作系统。CuDNN是GPU加速深度学习应用程序的核心组件,它提供了高效的...
wps-office-11.1.0.10920-1.aarch64.rpm
oracle-instantclient-odbc-11.1.0.1-1.i386.rpm
TensorRT-7.2.3.4.Ubuntu-18.04.x86_64-gnu.cuda-11.1.cudnn8.1.zip使用需要的环境: ubuntu18.04 tensorrt==7.2.3.4 cuda==1.1 cudnn==8.1
这个压缩包 "instantclient-basic-win-x86-64-11.1.0.7.0.zip" 包含了Windows 64位平台上的基本组件,用于在没有完整Oracle客户端安装的情况下连接到Oracle 11g数据库。它由Oracle公司提供,适用于那些需要快速、...
里面有三个rpm文件 oracle-instantclient-basic-11.1.0.1-1.i386.rpm, oracle-instantclient-devel-11.1.0.1-1.i386.rpm, oracle-instantclient-sqlplus-11.1.0.1-1.i386.rpm
wps-office-11.1.0.10920-1.mips64el.rpm
### Hyperion 数据表结构分析 —— 11.1.2.1 版本 Financial Management (HFM) Hyperion Financial Management (HFM) 是一款强大的财务整合与报告工具,广泛应用于企业级财务管理领域。在 HFM 的 11.1.2.1 版本中,...