问题
I am creating a non-model object that will be used with a Rails form builder by using ActiveModel
. This is a Rails 3 project. Here's an example of what I have so far:
class SalesReport
include ActiveModel::Validations
include ActiveModel::Conversion
extend ActiveModel::Naming
attr_accessor :promotion_code, :start_date, :end_date
def initialize(attributes = {})
attributes.each do |name, value|
send("#{name}=", value)
end
end
def persisted?
false
end
end
I happen to be using HAML and simple_form, but that's not important. Ultimately, I'm just using standard Rails date select fields:
= simple_form_for [:admin, @report], as: :report, url: admin_reports_path do |f|
= f.input :promotion_code, label: 'Promo Code'
= f.input :start_date, as: :date
= f.input :end_date, as: :date
= f.button :submit
Rails splits up the date fields into individual fields, so when the form is submitted, there are actually 3 date fields that are submitted:
{
"report" => {
"start_date(1i)" => "2014",
"start_date(2i)" => "4",
"start_date(3i)" => "1"
}
}
In my SalesReport
object, I'm assigning the params to my attr
methods, but I'm getting an error that I don't have a start_date(1i)=
method, which I obviously haven't defined. Ultimately, I'd like to end up with a Date
object that I can use instead of 3 separate fields.
How should I handle these date fields in my non-model object?
回答1:
In your initialization you could manually assign the values from attributes to the class methods and down below override you start_date
and end_date
setter methods.
class SalesReport
include ActiveModel::Validations
include ActiveModel::Conversion
extend ActiveModel::Naming
attr_accessor :promotion_code, :start_date, :end_date
def initialize(attributes = {})
@promotion_code = attributes['promotion_code']
year = attributes['start_date(1i)']
month = attributes['start_date(2i)']
day = attributes['start_date(3i)']
self.start_date = [year, month, day]
end
def start_date=(value)
if value.is_a?(Array)
@start_date = Date.new(value[0].to_i, value[1].to_i, value[2].to_i)
else
@start_date = value
end
end
def persisted?
false
end
end
This should allow you to give the setter a Date
instance or an Array
with the separate date elements and the setter will assign the correct date to @start_date
.
Just do the same for @end_date
.
Hope this can help you.
来源:https://stackoverflow.com/questions/22798691/how-to-handle-date-fields-in-a-non-model-rails-form