<ruby id="bdb3f"></ruby>

    <p id="bdb3f"><cite id="bdb3f"></cite></p>

      <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
        <p id="bdb3f"><cite id="bdb3f"></cite></p>

          <pre id="bdb3f"></pre>
          <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

          <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
          <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

          <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                <ruby id="bdb3f"></ruby>

                ??一站式輕松地調用各大LLM模型接口,支持GPT4、智譜、豆包、星火、月之暗面及文生圖、文生視頻 廣告
                ## 模型 * <a name="model-classes"></a> 自由地引入不是 ActiveRecord 的模型類。 <sup>[[link](#model-classes)]</sup> * <a name="meaningful-model-names"></a> 模型的命名應有意義(但簡短)且不含縮寫。 <sup>[[link](#meaningful-model-names)]</sup> * <a name="activeattr-gem"></a> 如果需要模型類有與 ActiveRecord 類似的行為(如驗證),但又不想有 ActiveRecord 的數據庫功能,應使用 [ActiveAttr](https://github.com/cgriego/active_attr) 這個 gem。 <sup>[[link](#activeattr-gem)]</sup> ```Ruby class Message include ActiveAttr::Model attribute :name attribute :email attribute :content attribute :priority attr_accessible :name, :email, :content validates_presence_of :name validates_format_of :email, :with => /\A[-a-z0-9_+\.]+\@([-a-z0-9]+\.)+[a-z0-9]{2,4}\z/i validates_length_of :content, :maximum => 500 end ``` 更完整的示例請參考 [RailsCast on the subject](http://railscasts.com/episodes/326-activeattr)。 ### ActiveRecord * <a name="keep-ar-defaults"></a> 避免改動缺省的 ActiveRecord 慣例(表的名字、主鍵等),除非你有一個充分的理由(比如,不受你控制的數據庫)。 <sup>[[link](#keep-ar-defaults)]</sup> ```Ruby # 差 - 如果你能更改數據庫的 schema,那就不要這樣寫 class Transaction < ActiveRecord::Base self.table_name = 'order' ... end ``` * <a name="macro-style-methods"></a> 把宏風格的方法調用(`has_many`, `validates` 等)放在類定義語句的最前面。 <sup>[[link](#macro-style-methods)]</sup> ```Ruby class User < ActiveRecord::Base # 默認的 scope 放在最前(如果有的話) default_scope { where(active: true) } # 接下來是常量初始化 COLORS = %w(red green blue) # 然后是 attr 相關的宏 attr_accessor :formatted_date_of_birth attr_accessible :login, :first_name, :last_name, :email, :password # 緊接著是與關聯有關的宏 belongs_to :country has_many :authentications, dependent: :destroy # 以及與驗證有關的宏 validates :email, presence: true validates :username, presence: true validates :username, uniqueness: { case_sensitive: false } validates :username, format: { with: /\A[A-Za-z][A-Za-z0-9._-]{2,19}\z/ } validates :password, format: { with: /\A\S{8,128}\z/, allow_nil: true} # 下面是回調方法 before_save :cook before_save :update_username_lower # 其它的宏(如 devise)應放在回調方法之后 ... end ``` * <a name="has-many-through"></a> `has_many :through` 優于 `has_and_belongs_to_many`。 使用 `has_many :through` 允許 join 模型有附加的屬性及驗證。 <sup>[[link](#has-many-through)]</sup> ```Ruby # 不太好 - 使用 has_and_belongs_to_many class User < ActiveRecord::Base has_and_belongs_to_many :groups end class Group < ActiveRecord::Base has_and_belongs_to_many :users end # 更好 - 使用 has_many :through class User < ActiveRecord::Base has_many :memberships has_many :groups, through: :memberships end class Membership < ActiveRecord::Base belongs_to :user belongs_to :group end class Group < ActiveRecord::Base has_many :memberships has_many :users, through: :memberships end ``` * <a name="read-attribute"></a> `self[:attribute]` 比 `read_attribute(:attribute)` 更好。 <sup>[[link](#read-attribute)]</sup> ```Ruby # 差 def amount read_attribute(:amount) * 100 end # 好 def amount self[:amount] * 100 end ``` * <a name="write-attribute"></a> `self[:attribute] = value` 優于 `write_attribute(:attribute, value)`。 <sup>[[link](#write-attribute)]</sup> ```Ruby # 差 def amount write_attribute(:amount, 100) end # 好 def amount self[:amount] = 100 end ``` * <a name="sexy-validations"></a> 總是使用新式的 ["sexy" 驗證](http://thelucid.com/2010/01/08/sexy-validation-in-edge-rails-rails-3/)。 <sup>[[link](#sexy-validations)]</sup> ```Ruby # 差 validates_presence_of :email validates_length_of :email, maximum: 100 # 好 validates :email, presence: true, length: { maximum: 100 } ``` * <a name="custom-validator-file"></a> 當一個自定義的驗證規則使用次數超過一次時,或該驗證規則是基于正則表達式時,應該創建一個自定義的驗證規則文件。 <sup>[[link](#custom-validator-file)]</sup> ```Ruby # 差 class Person validates :email, format: { with: /\A([^@\s]+)@((?:[-a-z0-9]+\.)+[a-z]{2,})\z/i } end # 好 class EmailValidator < ActiveModel::EachValidator def validate_each(record, attribute, value) record.errors[attribute] << (options[:message] || 'is not a valid email') unless value =~ /\A([^@\s]+)@((?:[-a-z0-9]+\.)+[a-z]{2,})\z/i end end class Person validates :email, email: true end ``` * <a name="app-validators"></a> 自定義驗證規則應放在 `app/validators` 目錄下。 <sup>[[link](#app-validators)]</sup> * <a name="custom-validators-gem"></a> 如果你在維護數個相關的應用,或驗證規則本身足夠通用,可以考慮將自定義的驗證規則抽象為一個共用的 gem。 <sup>[[link](#custom-validators-gem)]</sup> * <a name="named-scopes"></a> 自由地使用命名 scope。 <sup>[[link](#named-scopes)]</sup> ```Ruby class User < ActiveRecord::Base scope :active, -> { where(active: true) } scope :inactive, -> { where(active: false) } scope :with_orders, -> { joins(:orders).select('distinct(users.id)') } end ``` * <a name="named-scope-class"></a> 當一個由 lambda 和參數定義的命名 scope 太過復雜時, 更好的方式是創建一個具有同樣用途并返回 `ActiveRecord::Relation` 對象的類方法。這很可能讓 scope 更加精簡。 <sup>[[link](#named-scope-class)]</sup> ```Ruby class User < ActiveRecord::Base def self.with_orders joins(:orders).select('distinct(users.id)') end end ``` 注意這種方式不允許命名 socpe 那樣的鏈式調用。例如: ```Ruby # 不能鏈式調用 class User < ActiveRecord::Base def User.old where('age > ?', 80) end def User.heavy where('weight > ?', 200) end end ``` 這種方式下 `old` 和 `heavy` 可以單獨工作,但不能執行 `User.old.heavy`。 若要鏈式調用,請使用下面的代碼: ```Ruby # 可以鏈式調用 class User < ActiveRecord::Base scope :old, -> { where('age > 60') } scope :heavy, -> { where('weight > 200') } end ``` * <a name="beware-update-attribute"></a> 注意 [`update_attribute`](http://api.rubyonrails.org/classes/ActiveRecord/Persistence.html#method-i-update_attribute) 方法的行為。它不運行模型驗證(與 `update_attributes` 不同),因此可能弄亂模型的狀態。 <sup>[[link](#beware-update-attribute)]</sup> * <a name="user-friendly-urls"></a> 應使用對用戶友好的 URL。URL 中應顯示模型的一些具有描述性的屬性,而不是僅僅顯示 `id`。有多種方法可以達到這個目的: <sup>[[link](#user-friendly-urls)]</sup> * 重寫模型的 `to_param` 方法。Rails 使用該方法為對象創建 URL。該方法默認會以字符串形式返回記錄的 `id` 項。 可以重寫該方法以包含其它可讀性強的屬性。 ```Ruby class Person def to_param "#{id} #{name}".parameterize end end ``` 為了將結果轉換為一個 URL 友好的值,字符串應該調用 `parameterize` 方法。 對象的 `id` 屬性值需要位于 URL 的開頭,以便使用 ActiveRecord 的 `find` 方法查找對象。 * 使用 `friendly_id` 這個 gem。它允許使用對象的一些描述性屬性而非 `id` 來創建可讀性強的 URL。 ```Ruby class Person extend FriendlyId friendly_id :name, use: :slugged end ``` 查看 [gem documentation](https://github.com/norman/friendly_id) 以獲得更多 `friendly_id` 的使用信息。 * <a name="find-each"></a> 應使用 `find_each` 來迭代一系列 ActiveRecord 對象。用循環來處理數據庫中的記錄集(如 `all` 方法)是非常低效率的,因為循環試圖一次性得到所有對象。而批處理方法允許一批批地處理記錄,因此需要占用的內存大幅減少。 <sup>[[link](#find-each)]</sup> ```Ruby # 差 Person.all.each do |person| person.do_awesome_stuff end Person.where('age > 21').each do |person| person.party_all_night! end # 好 Person.find_each do |person| person.do_awesome_stuff end Person.where('age > 21').find_each do |person| person.party_all_night! end ``` * <a name="before_destroy"></a> 因為 [Rails 為有依賴關系的關聯添加了回調方法](https://github.com/rails/rails/issues/3458),應總是調用 `before_destroy` 回調方法,調用該方法并啟用 `prepend: true` 選項會執行驗證。 <sup>[[link](#before_destroy)]</sup> ```Ruby # 差——即使 super_admin 返回 true,roles 也會自動刪除 has_many :roles, dependent: :destroy before_destroy :ensure_deletable def ensure_deletable fail "Cannot delete super admin." if super_admin? end # 好 has_many :roles, dependent: :destroy before_destroy :ensure_deletable, prepend: true def ensure_deletable fail "Cannot delete super admin." if super_admin? end ``` ### ActiveRecord 查詢 * <a name="avoid-interpolation"></a> 不要在查詢中使用字符串插值,它會使你的代碼有被 SQL 注入攻擊的風險。 <sup>[[link](#avoid-interpolation)]</sup> ```Ruby # 差——插值的參數不會被轉義 Client.where("orders_count = #{params[:orders]}") # 好——參數會被適當轉義 Client.where('orders_count = ?', params[:orders]) ``` * <a name="named-placeholder"></a> 當查詢中有超過 1 個占位符時,應考慮使用名稱占位符,而非位置占位符。 <sup>[[link](#named-placeholder)]</sup> ```Ruby # 一般般 Client.where( 'created_at >= ? AND created_at <= ?', params[:start_date], params[:end_date] ) # 好 Client.where( 'created_at >= :start_date AND created_at <= :end_date', start_date: params[:start_date], end_date: params[:end_date] ) ``` * <a name="find"></a> 當只需要通過 id 查詢單個記錄時,優先使用 `find` 而不是 `where`。 <sup>[[link](#find)]</sup> ```Ruby # 差 User.where(id: id).take # 好 User.find(id) ``` * <a name="find_by"></a> 當只需要通過屬性查詢單個記錄時,優先使用 `find_by` 而不是 `where`。 <sup>[[link](#find_by)]</sup> ```Ruby # 差 User.where(first_name: 'Bruce', last_name: 'Wayne').first # 好 User.find_by(first_name: 'Bruce', last_name: 'Wayne') ``` * <a name="find_each"></a> 當需要處理多條記錄時,應使用 `find_each`。 <sup>[[link](#find_each)]</sup> ```Ruby # 差——一次性加載所有記錄 # 當 users 表有成千上萬條記錄時,非常低效 User.all.each do |user| NewsMailer.weekly(user).deliver_now end # 好——分批檢索記錄 User.find_each do |user| NewsMailer.weekly(user).deliver_now end ``` * <a name="where-not"></a> `where.not` 比書寫 SQL 更好。 <sup>[[link](#where-not)]</sup> ```Ruby # 差 User.where("id != ?", id) # 好 User.where.not(id: id) ```
                  <ruby id="bdb3f"></ruby>

                  <p id="bdb3f"><cite id="bdb3f"></cite></p>

                    <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
                      <p id="bdb3f"><cite id="bdb3f"></cite></p>

                        <pre id="bdb3f"></pre>
                        <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

                        <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
                        <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

                        <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                              <ruby id="bdb3f"></ruby>

                              哎呀哎呀视频在线观看