自己很初級,初級的不能再初級,所以初次接觸rails的時候,對於里面的create,new,build等方法不是很了解,用的很混亂,導致經常出現不必要的bug,很苦惱,決定,總結一下,結合網上已有資源,深入理解下 向數據庫插記錄時經常會用到new, build, create。這三個方法很容易混淆
save:rails中的save其實是create_or_update,新建或修改記錄!不一定是新建,切記 new :只是在內存中新建一個對象,操作數據庫要調用save方法。 create = new + 執行sql。 build:與new基本相同,多用於一對多情況下。還有一個不同請看使用示例 !:new!, create!, build!與new, create, build的區別是帶!的方法會執行validate,如果驗證失敗會拋出導常。 save是實例方法,而create, build, new是模型類的類方法
還有另外一種說法,也挺好,如下 首先說new吧,app = App.new(params[:app]),這個是用給定的params來實例化一個app對象,注意此時只是初始化了一個對象,ruby只是在內存里面給app分配了一個內存地址,但是,這 個地址還沒有指定任何的有效的內存,所以接下來ruby要做的就是調用model里面的initialize函數來根據給定的參數進行初始化這個對象,並將該對象保存到堆里面。 對於new!來說,這個跟new相比,就是在save到數據庫的時候,如果save失敗,就會報一個錯誤。 對於create來說,過程大致跟new差不多,唯一的區別是,create = new + save,即create一步操作等於new和save的兩部操作。 對於create!來說,類似於new! 過程大致也是跟new!差不多 區別是create! = new! + save 如果保存失敗的話會返回一個錯誤。 對於build來說,主要的混淆的地方在於與new的區別,其實,我認為build是new的一個別名,但是用的地方可能跟new有點區別,在我看來,build大多是用於有關聯關系的對象模型的時 候,用來創建子model用的,比如說 Person 與 Order是一對多的關系,那么我們可以用 @persion.build()方法來創建於該person對應的orders
下面有一個簡單的示例:
- 本來是想用accepts_nested_attributes_for寫一個nested form
本來是想用accepts_nested_attributes_for寫一個nested form
- class User < ActiveRecord::Base
- attr_accessible :email, :account_attributes
- has_one :account
- accepts_nested_attributes_for :account
- end
- class Account < ActiveRecord::Base
- attr_accessible :password, :password_confirmation
- has_secure_password
- belongs_to :user
- end
- class UsersController < ApplicationController
- defnew
- @user = User.new
- end
- end
class User < ActiveRecord::Base attr_accessible :email, :account_attributes has_one :account accepts_nested_attributes_for :account end class Account < ActiveRecord::Base attr_accessible :password, :password_confirmation has_secure_password belongs_to :user end class UsersController < ApplicationController def new @user = User.new end end
view里
- <%= form_for @userdo |f| %>
- email: <%= f.text_field :name %>
- <%= f.fields_for :accountdo |account_form| %>
- password: <%= account_form.password_field :password %>
- password_confirmation: <%= account_form.password_field :password_confirmation %>
- <% end %>
- <% end %>
<%= form_for @user do |f| %> email: <%= f.text_field :name %> <%= f.fields_for :account do |account_form| %> password: <%= account_form.password_field :password %> password_confirmation: <%= account_form.password_field :password_confirmation %> <% end %> <% end %>一開始無法顯示account里的內容,后來發現沒有在controller里build account, 於是
- class UsersController < ApplicationController
- defnew
- @user = User.new
- @user.account.build
- end
- end
class UsersController < ApplicationController def new @user = User.new @user.account.build end end報錯 undefined method `build' for nil:NilClass
剛開始怎么也想不通,隔了一天去翻http://api.rubyonrails.org/classes/ActiveRecord/Associations/ClassMethods.html 才發現原來has_one的build方法是build_association而不是collection.build。因為不常用has_one,rails里“約定”又比較多,才會當has_many的方法來寫。
把controller里改成
- class UsersController < ApplicationController
- defnew
- @user = User.new
- @user.build_account
- end
- end
class UsersController < ApplicationController def new @user = User.new @user.build_account end end
程序才正常跑起來
一言蔽之 在has_many中:User#accounts.build 在has_one中:User#build_account