2011-10-11 23 views
3

我一直在尋找無處不在,但似乎無法找到一個很好的解決方案。導入多個字段到一個模型屬性

我的表單有一個日期(帶datepicker的textfield)和一個時間(textfield with timepicker),我想要映射到名爲due_at的模型字段。

到目前爲止,我一直在我的控制器中使用單獨的參數處理它,以便將它連接到日期時間,然後手動設置模型字段,但這很麻煩,並且真的認爲這個邏輯應該保存在模型/視圖中。

我想能夠處理兩個表單域模型中的一個屬性,然後把它分解背出錯誤,編輯操作等,基本上執行什麼標準datetime_select做的定製方式,但把我自己的觸摸。

有什麼我可以放在我的模型中嗎?

def due_at=(date, time) 
... 
end 

我一直在尋找一些地方,但無法找到你如何做到這一點。人們說使用javascript來填充隱藏的字段,但似乎並不是最簡單的問題的最乾淨的解決方案。

任何意見/幫助將不勝感激。

謝謝。

回答

6

首先:請重命名您的字段,因爲created_at可能會導致與ActiveRecord發生衝突。

我確實做到了這與格式M/d/YYYY H A場:M(小時/分鐘在24小時格式)

在你的模型:

attr_accessor :due_date, :due_time 

before_validation :make_due_at 


def make_due_at 
    if @due_date.present? && @due_time.present? 
    self.due_at = DateTime.new(@due_date.year, @due_date.month, @due_date.day, @due_time.hour, @due_time.min) 
    end 
end 


def due_date 
    return @due_date if @due_date.present? 
    return @due_at if @due_at.present? 
    return Date.today 
end 

def due_time 
    return @due_time if @due_time.present? 
    return @due_at if @due_at.present? 
    return Time.now 
end 


def due_date=(new_date) 
    @due_date = self.string_to_datetime(new_date, I18n.t('date.formats.default')) 
end 


def due_time=(new_time) 
    @due_time = self.string_to_datetime(new_time, I18n.t('time.formats.time')) 
end 

protected 

def string_to_datetime(value, format) 
    return value unless value.is_a?(String) 

    begin 
    DateTime.strptime(value, format) 
    rescue ArgumentError 
    nil 
    end 
end 
現在

的觀點:

<%= text_field_tag :due_time, I18n.l(@mymodel.due_time, :format => :time) %> 
<%= text_field_tag :due_date, I18n.l(@mymodel.due_date, :format => :default) %> 
現在

在config /區域設置/ en.yml(如果英語)

date: 
    formats: 
     default: "%m/%d/%Y" 
    time: 
    formats: 
     time: "%H:%M" 

您可以更改當然的日期格式。

+0

當你有一個帶有日期時間的文本框時,這非常適用,但是當你有兩個文本框時,其中一個與其他時間一起使用時,我需要一個解決方案。 –

+0

添加兩個不支持數據庫的變量,確保他們進入參數並構建「實際值」並分配給「實際變量」?這是你必須添加到模型中的代碼,而不是kickass Rails的魔法,但它應該做到這一點...... – jaydel

+0

謝謝jaydel,我很確定我知道你的意思是使用虛擬屬性。我試圖在我的例子中實現這一點,你能否提供一個例子? –

0

我覺得date_time_attribute gem是一個不錯的選擇:

class Task < ActiveRecord::Base 
    include DateTimeAttribute 

    date_time_attribute :due_at 
end 

它可以讓你設置due_at_datedue_at_time分開:

form_for @event do |f| 
    f.text_field :due_at_date 
    f.text_field :due_at_time 
    f.submit 
end 

# this will work too: 
form_for @event do |f| 
    f.date_select :due_at_date 
    f.time_select :due_at_time, :ignore_date => true 
    f.text_field :due_at_time_zone 
    f.submit 
end 

# or 
form_for @event do |f| 
    f.date_select :due_at_date 
    f.text_field :due_at_time 
    f.submit 
end 

下面是一個例子:

task = Task.new 
task.due_at      # => nil 

# Date set 
task.due_at_date = '2001-02-03' 
task.due_at_date     # => 2001-02-03 00:00:00 +0700 
task.due_at_time     # => 2001-02-03 00:00:00 +0700 
task.due_at      # => 2001-02-03 00:00:00 +0700 

# Time set 
task.due_at_time = '10:00pm' 
task.due_at_time     # => 2013-12-02 22:00:00 +0800 
task.due_at_date     # => 2001-02-03 00:00:00 +0700 
task.due_at      # => 2001-02-03 22:00:00 +0700 

# Time zone is applied as set 
task.due_at_time_zone = 'Moscow' 
task.due_at      # => Mon, 03 Feb 2013 22:00:00 MSK +04:00 
task.due_at_time_zone = 'London' 
task.due_at      # => Mon, 03 Feb 2013 22:00:00 GMT +00:00 

它也可以讓你玩時區,使用慢性等。

相關問題