Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
396 views
in Technique[技术] by (71.8m points)

validation - How do ruby on rails multi parameter attributes *really* work (datetime_select)

I believe that datetime_select is black magic. What I'm really trying to figure out is the whole 1i,2i,3i,4i... multiple parameters stuff. Specifically how is it handled in the back end (activerecord, something else?). What's with the 'i' after the order-number? Is it a type-specifier? If so what are other types that are available? I've read the source of date_helper.rb and it's quite opaque.

Here's my motivation:

I've got a :datetime column in my model and I want to input in the view via two text_fields: one for date and one for time. They need to be validated, merged together, then stored into the datetime column. Ultimately I'll be using a javascript calendar to input dates into the date field.

So has anybody done this? I tried using virtual attributes (incredibly undocumented besides the rudimentary railscast) and the issue was that when a new activerecord object is created and has nil attributes, the virtual attribute fails (undefined method strftime for nil class, which makes sense).

Anybody have any suggestions or best practices? Thanks!

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

I had the same question. Here's what I found...

http://apidock.com/rails/ActiveRecord/Base/assign_multiparameter_attributes

assign_multiparameter_attributes(pairs) private

Instantiates objects for all attribute classes that needs more than one constructor parameter. This is done by calling new on the column type or aggregation type (through composed_of) object with these parameters. So having the pairs written_on(1) = "2004", written_on(2) = "6", written_on(3) = "24", will instantiate written_on (a date type) with Date.new("2004", "6", "24"). You can also specify a typecast character in the parentheses to have the parameters typecasted before they’re used in the constructor. Use i for Fixnum, f for Float, s for String, and a for Array. If all the values for a given attribute are empty, the attribute will be set to nil.

So the numbers are for the parameters of the data type that the column is. The "i" is to convert it to an integer. Other types are supported like "f" for float, etc.

You can see here in execute_callstack_for_multiparameter_attributes that it detects the target type and instantiates it passing the values.

So, to try directly answering the posed question, I don't think you can use it to override how a DateTime is created because it uses the constructor which doesn't support the format you want to pass in. My work-around was to split the DateTime column out to one Date and one Time column. Then the UI could work the way I wanted.

I wonder if it might be possible to create attribute accessors on the class that represent the date and time separately but keep a single DateTime column. Then the form could reference those separate accessors. That might be workable. Another option might be to use composed_of to customize the type further.

Hope that helps someone else. :)


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...