2013-09-16 113 views
0

我是Ruby新手,至今與我的正常編程語言C#相比,感到困惑。目前我掙扎的是我有一個擴展ActiveRecord::Base的類,但是代表了一個沒有保存到數據庫的模型,只在內存中使用。這樣做的目的是讓我可以使用ActiveRecord的驗證功能。如何創建類的空實例?

型號

class NewsletterSignup < ActiveRecord::Base 
    attr_accessible :first_name, :last_name, :email, :zip 

    def self.columns() 
    @columns ||= []; 
    end 

    def self.column(name, sql_type = nil, default = nil, null = true) 
    columns << ActiveRecord::ConnectionAdapters::Column.new(name, default, sql_type, null) 
    end 

    def persisted? 
    false 
    end 

    column :first_name, :string 
    column :last_name, :string 
    column :email, :string 
    column :zip, :string 

    validates :first_name, :last_name, :email, :zip, :presence => true 
    validates :email, :format => /^[-a-z0-9_+\.]+\@([-a-z0-9]+\.)+[a-z0-9]{2,4}$/i 
    validates :zip, :format => /^\d{5}$/ 
end 

管窺

<%= simple_form_for NewsletterSignup.new ... do |f| %> 
    <%= f.input :first_name, :label => "First Name:" %> 
    <%= f.input :last_name, :label => "Last Name:" %> 
    <%= f.input :email, :label => "Email:" %> 
    <%= f.input :zip, :label => "Zip:" %> 

    ... 
<% end %> 

我想這樣的驗證工作,以空模型傳遞到窗體。但是,這給了我嘗試實例化一個NewsletterSignup沒有提供屬性/值時出現錯誤:

::加載ActiveModel MissingAttributeError 缺少的屬性:FIRST_NAME

缺少什麼我在這裏?

+0

你使用的是什麼版本的Rails? – depa

回答

3

如果你沒有這個模型後面的數據庫表,你會回頭向後看。不要從ActiveRecord :: Base繼承,只需製作一個常規類,幷包含您需要從Rails獲得的組件。這是一個StackOverflow答案,顯示了這個:Ruby on Rails: Fully functional tableless model。或者,如果您使用Rails 4,那麼現在就更容易了,因爲您所要做的只是include ActiveModel::Model。這裏有一篇關於這方面的文章:http://blog.remarkablelabs.com/2012/12/activemodel-model-rails-4-countdown-to-2013

+1

此文章由Rails核心成員撰寫:http://blog.plataformatec.com.br/2012/03/barebone-models-to-use-with-action-withpackage-in-rails-4-0/ – depa

+0

@pdobb - 感謝那,它似乎運作良好。就像我說的,我是Ruby/Rails的新手 - 你能否詳細說明你所鏈接的答案中的'class << self'和'def initialize(attributes = {})'塊的用途?這些區塊有什麼功能來完成這項工作? –

+0

'class << self'是編寫類方法的替代方法。更常見的模式就是:'def self。 '。所以在這種情況下,他只是定義'def self.all'類方法來返回一個空數組。然後'def initialize(attributes = {})'是從一個類實例化一個新對象時調用的方法。因此'MyObject.new(a:1)'會調用'initialize'作爲屬性傳遞散列'{a:1}'給它。如果您想要在對象實例化上設置屬性,可以用這種方式重寫'initialize'方法。 – pdobb