-
Notifications
You must be signed in to change notification settings - Fork 21.9k
Move multi-parameter attributes from ActiveRecord to ActiveModel #8189
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
I'm not sure I like the idea of having this I haven't looked carefully at the code though, but I'm 👍 for the spirit, we just need to figure out how to make all this work. |
This seems a good idea but the aggregate attributes compatibility concerns me. I would not move it to Action Controller thought. I think is better and easy to maintain compatibility with aggregate attributes to move it to Active Model and inherit to this new model in Active Record adding the I don't see too much gain in moving this to Action Controller beyond the "model layer shouldn't need to be aware of the format that's used to pass the data from the client to the server". About the side effect that make "very easy to register custom types" this is already possible using That said, I would gladly accept a feature making possible to use multi-parameters with Active Model classes but I'd not made it to Action Controller. @josevalim @spastorino @jeremy @wycats your thoughts here would be great. |
I'm 👎 on the idea of moving it to Action Controller. If you take it to it's logical conclusion you'd only accept the correct types for boolean, integer, decimal, etc. columns, which is obviously crazy. If we just do it for multi-parameter attributes then we have split the responsibility for typecasting params. The plan suggest by @rafaelfranca is a better idea. |
Thanks for the feedback. I hadn't considered the impact on aggregate attributes, which would need some work, but I thought they were being removed in Rails 4 anyway? (#6743) I take @pixeltrix's point about splitting responsibility for type conversion, but as things stand now responsibility for multi-parameter support is already split: Perhaps it would be cleaner for |
Ignoring the Currently you would use it like this: class Person
include ActiveModel::Model
attr_accessor :name, :date_of_birth
def class_for_attribute(attr)
return Date if attr == 'date_of_birth'
end
end
george = Person.new(
'name' => 'George',
'date_of_birth(1i)' => '1984',
'date_of_birth(2i)' => '2',
'date_of_birth(3i)' => '20'
)
george.date_of_birth #=> Mon, 20 Feb 1984 If this seems sane I'll clean it up, add tests and provide a nicer way of specifying date, time and datetime attributes without needing to override the |
I like this idea a lot. I have had problems too with having multi-parameters assignments depending so heavily on active record. |
@georgebrock sorry for the delay. The overral implementation seems good. Some considerations:
|
ping. What is the status on this one? |
+1 for this feature. |
@senny Sorry for the delay, life got in the way. I should have some time to pick this up again next week. @rafaelfranca Thanks for the feedback. Agreed on both points. |
I've pushed an updated version:
There are still a couple of things to do before this lands:
More next Friday if I don't get to it before then. |
|
||
# Raised when unknown attributes are supplied via mass assignment. | ||
class UnknownAttributeError < NoMethodError | ||
end |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
How do you feel about moving the error classes to the bottom of the file so that coming into the file the documentation on AttributeAssignment is the first thing we see?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good call. Thanks Caleb.
@carlosantoniodasilva, @rafaelfranca: I think this is ready to go, let me know what you think. |
I'm sorry but we are too close to 4.0 to merge this one. But we will revisit after the release. |
Absolutely, I wasn't expecting it to make 4.0 at this late stage. Let me know if there's more I can do to get this merged when the release is out of the way. |
Cant you include it into rails 3.2.x? Would be really nice..? :) |
@lichtamberg: no, this can't make it to 3.2.x. The 3.2 branch is only for bugfixes now. |
@dmathieu sure. I'll review this soon. I need to discuss some API related things with the Rails core |
@rafaelfranca any updates on this? |
I've rebased this onto the current master. Anything else I can do towards getting it merged? /cc @rafaelfranca |
This is a major change and I don't want to take the decision too soon. Right now this is on hold until we start the development of Rails 4.1 @georgebrock thank for rebasing. I'll ping you when we are going to merge. |
Making strong parameters work with ActiveModel::Model would be very nice. Thanks for this contribution I am looking forward to it. |
ActiveModel::Model provides an initializer that assigns the give params to attributes. We need to override it in ActiveModel::AttributeAssignment in order to support multi-parameter attributes in the constructor.
If mass assignment is used for an unknown single parameter attribute, an UnknownAttribute error is raised. This makes the behaviour consistent for multi-parameter attributes.
When the attribute does exist, but we don't know what class to use for a multi-parameter assignment, we now raise a helpful exception. This should help people TDD their way to a correct implementation of multi-parameter attributes, or make it more clear what's going on when there's a real error.
This way the first thing you see when looking at the file is the documentation for the AttributeAssignment model.
I've just rebased again to keep this close to master and easy to merge. Tests still passing. |
So this is still not available in Rails 4.x? Anyone have a workaround? |
CC @rafaelfranca @tenderlove ;) would be nice to get this in if everything is in order |
I need this today, as I'm upgrading a critical Rails app to 4.0.2. Is there a way to pull this in from git and use it, or am I out of luck? |
Fork rails, add github.com/georgebrock/rails as a remote, merge this branch into rails/4.0.2 (the tag), and then use your fork of Rails: gem 'rails', github: 'yourusername/rails' I'm not recommending this, but that is what you would do. On Mon, Jan 20, 2014 at 5:09 PM, Nicholas Young notifications@github.com
|
Thanks Caleb. With Mongoid dropping multi-param attributes at the same time, this whole thing is a huge mess. I'll try to sort it out.
|
@nicholaswyoung I needed this in my project, so I just created a concern using the code here, along with an Rspec support file to test the functionality on my model. Note that I only built tests around the date functionality since I'm personally not in need of the time related code. Here's a gist that shows how I put the code here to use: https://gist.github.com/mhuggins/6c3d343fd800cf88f28e |
Is there are any possibility to speedup this pull-request to be merged? |
bump +1 |
We are still open to the idea but the implementation should leverage the attributes API introduced in Rails 5.2 in Active Model. Thank you again for this PR. |
How is this coming along? |
Multi-parameter attributes (used to build a complex type like a
Date
from several simple values that can be easily POSTed) are currently implemented inActiveRecord::AttributeAssignment
. This is pretty frustrating if you're trying to use anActiveModel::Model
withDate
orDateTime
fields.I've fixed this by moving multi-parameter conversion to the
ActionController::Parameters
class, so it happens before the value hits the model. IMO the model layer shouldn't need to be aware of the format that's used to pass the data from the client to the server.To support this the type that the values should be re-assembled into is included in the form (e.g.
<input type="hidden" name="my_model[created_at(type)]" value="Date">
) instead of being determined from the model schema.The main aim was to get multi-parameter attributes working with
ActiveModel
, but a nice side effect of this implementation is that it becomes very easy to register custom types. For example, you could easily submit an amount of money as a currency and an amount and have it converted to your own customMoney
class:This isn't a finished implementation yet. It needs documentation, and the
ActiveRecord
implementation needs to be deprecated or removed. I've added multi-parameter support toActionController
and updated thedate_select
,datetime_select
andtime_select
helpers to use the new implementation. I figured this was far enough to get some feedback.Edit: Renamed from Move multi-parameter attributes from ActiveRecord to ActionController to Move multi-parameter attributes from ActiveRecord to ActiveModel to reflect the current state of the change.