Skip to content
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

Extracted attributes assingment from ActiveRecord to ActiveModel #10776

Merged
merged 1 commit into from Jan 23, 2015

Conversation

@bogdan
Copy link
Contributor

bogdan commented May 28, 2013

Now you are able to do:

class Feedback
  include ActiveModel::AttributeAssignment
  attr_accessor :email, :subject, :body
end

f = Feedback.new
f.assign_attributes(
  :email => "bogdan@example.com", 
  :subject => "Hello", 
  :body => "The app dont work for me"
)

This is just a proof of concept PR.

There is still some todos:

  • Write tests for ActiveModel::AttributeAssignment
  • Deprecate AR::UnknownAttributeError in flavor of AM one
  • Add change log entry
  • rebase change log entry 2-3 times

I am gonna add them if this will be approved to merge in.

@dmathieu
dmathieu reviewed May 28, 2013
View changes
activerecord/lib/active_record/errors.rb Outdated
end

end
UnknownAttributeError = ActiveModel::AttributeAssignment::UnknownAttributeError

This comment has been minimized.

Copy link
@dmathieu

dmathieu May 28, 2013

Contributor

I don't think this is still necessary.

This comment has been minimized.

Copy link
@bogdan

bogdan May 28, 2013

Author Contributor

Existing rails apps could still use this constant to catch this exception and process it manually.

This comment has been minimized.

Copy link
@dmathieu

dmathieu May 28, 2013

Contributor

Raising it has to trigger a deprecation then.

This comment has been minimized.

Copy link
@bogdan

bogdan Feb 13, 2014

Author Contributor

Do you know how to do that?

@dmathieu
Copy link
Contributor

dmathieu commented May 28, 2013

Is there a reason why you didn't extract the tests too ?

@bogdan
Copy link
Contributor Author

bogdan commented Sep 25, 2013

@dmathieu once I saw someone from core team saying that overlapping between AR and AM tests is good idea. No concrete reason.

@robin850
robin850 reviewed Sep 28, 2013
View changes
activemodel/lib/active_model/attribute_assignment.rb Outdated

private

def _assign_attribute(k, v)

This comment has been minimized.

Copy link
@robin850

robin850 Sep 28, 2013

Member

Could you please indent the private methods as the contribution guideline states ? Also, I think that this will at least need a changelog entry. Not sure if you should add one in AR changelog as well.

This comment has been minimized.

Copy link
@robin850

robin850 Sep 28, 2013

Member

Nice pull request though, thank you!

@rafaelfranca
Copy link
Member

rafaelfranca commented Jan 21, 2015

What is the motivation for this extraction?

@bogdan
Copy link
Contributor Author

bogdan commented Jan 21, 2015

Using outside of activerecord just like validation and others:

Attributes assignment concept is something I personally use a lot for many types of objects.

@rafaelfranca
Copy link
Member

rafaelfranca commented Jan 21, 2015

👍 for the idea from my side. @sgrif WDYT?

@sgrif
Copy link
Contributor

sgrif commented Jan 23, 2015

👍 for the idea from me, as well. Would like to review the code again once it's been rebased onto master and had tests added/moved/etc

@bogdan bogdan force-pushed the bogdan:assign-attributes branch Jan 23, 2015
@bogdan
Copy link
Contributor Author

bogdan commented Jan 23, 2015

Updated the PR:

  • Rebased with master
  • Added tests for ActiveModel
  • Decided to keep a separated documentation for #attributes= in activerecord because it includes many DB interaction points
  • Left ActiveRecord::AttributeAssignment tests untouched that now creates some overlap in tests. Thought it is a good idea
  • Made changelog
@arthurnn
Copy link
Member

arthurnn commented Jan 23, 2015

I would use this on Mongoid if this is merge on ActiveModel.!

@rafaelfranca
rafaelfranca reviewed Jan 23, 2015
View changes
activemodel/lib/active_model/attribute_assignment.rb Outdated
_assign_attributes(sanitize_for_mass_assignment(attributes))
end

def _assign_attributes(attributes)

This comment has been minimized.

Copy link
@rafaelfranca

rafaelfranca Jan 23, 2015

Member

Should not this method be private?

@rafaelfranca
rafaelfranca reviewed Jan 23, 2015
View changes
activemodel/lib/active_model/attribute_assignment.rb Outdated
@attribute = attribute.to_s
super("unknown attribute '#{attribute}' for #{@record.class}.")
end

This comment has been minimized.

Copy link
@rafaelfranca
@rafaelfranca
rafaelfranca reviewed Jan 23, 2015
View changes
activemodel/lib/active_model/attribute_assignment.rb Outdated

# Raised when unknown attributes are supplied via mass assignment.
class UnknownAttributeError < NoMethodError

This comment has been minimized.

Copy link
@rafaelfranca
@rafaelfranca
rafaelfranca reviewed Jan 23, 2015
View changes
activemodel/test/cases/attribute_assignment_test.rb Outdated
require 'active_support/hash_with_indifferent_access'

class AttributeAssignmentTest < ActiveModel::TestCase

This comment has been minimized.

Copy link
@rafaelfranca
@rafaelfranca
rafaelfranca reviewed Jan 23, 2015
View changes
activemodel/test/cases/attribute_assignment_test.rb Outdated

class AttributeAssignmentTest < ActiveModel::TestCase


This comment has been minimized.

Copy link
@rafaelfranca
@rafaelfranca
rafaelfranca reviewed Jan 23, 2015
View changes
activemodel/test/cases/attribute_assignment_test.rb Outdated


class Model

This comment has been minimized.

Copy link
@rafaelfranca
@rafaelfranca
rafaelfranca reviewed Jan 23, 2015
View changes
activemodel/test/cases/attribute_assignment_test.rb Outdated
end

class ProtectedParams < ActiveSupport::HashWithIndifferentAccess

This comment has been minimized.

Copy link
@rafaelfranca
@rafaelfranca
rafaelfranca reviewed Jan 23, 2015
View changes
activemodel/test/cases/attribute_assignment_test.rb Outdated
test "assign private attribute" do
model = Model.new
assert_raises ActiveModel::AttributeAssignment::UnknownAttributeError do
model.assign_attributes(metadata: {a: 1})

This comment has been minimized.

Copy link
@rafaelfranca

rafaelfranca Jan 23, 2015

Member

space after { and before }

@rafaelfranca
rafaelfranca reviewed Jan 23, 2015
View changes
activemodel/lib/active_model/attribute_assignment.rb Outdated

module ActiveModel
module AttributeAssignment

This comment has been minimized.

Copy link
@rafaelfranca
@rafaelfranca
rafaelfranca reviewed Jan 23, 2015
View changes
activerecord/lib/active_record/attribute_assignment.rb Outdated
@@ -208,5 +189,6 @@ def extract_max_param(upper_cap = 100)
[values.keys.max, upper_cap].min
end
end

This comment has been minimized.

Copy link
@rafaelfranca
@rafaelfranca
rafaelfranca reviewed Jan 23, 2015
View changes
activemodel/lib/active_model/attribute_assignment.rb Outdated
end
return if new_attributes.blank?

attributes = new_attributes.stringify_keys

This comment has been minimized.

Copy link
@rafaelfranca

rafaelfranca Jan 23, 2015

Member

no need these extra whitespaces

@rafaelfranca rafaelfranca added this to the 5.0.0 milestone Jan 23, 2015
@bogdan bogdan force-pushed the bogdan:assign-attributes branch Jan 23, 2015
@bogdan
Copy link
Contributor Author

bogdan commented Jan 23, 2015

@rafaelfranca removed all whitespace

@vipulnsward
vipulnsward reviewed Jan 23, 2015
View changes
activemodel/CHANGELOG.md Outdated
@@ -1,3 +1,23 @@
* Extracted `ActiveRecord::AttributeAssignment` to `ActiveModel::AttributesAssignment`

This comment has been minimized.

Copy link
@vipulnsward

vipulnsward Jan 23, 2015

Member

AttributesAssignment => AttributeAssignment

@vipulnsward
vipulnsward reviewed Jan 23, 2015
View changes
activemodel/CHANGELOG.md Outdated
cat = Cat.new
cat.assign_attributes(name: "Gorby", status: "yawning")
cat.name # => 'Gorby'
cate.status => 'yawning'

This comment has been minimized.

Copy link
@vipulnsward
@vipulnsward
vipulnsward reviewed Jan 23, 2015
View changes
activemodel/lib/active_model/attribute_assignment.rb Outdated
# cat = Cat.new
# cat.assign_attributes(name: "Gorby", status: "yawning")
# cat.name # => 'Gorby'
# cate.status => 'yawning'

This comment has been minimized.

Copy link
@vipulnsward

vipulnsward Jan 23, 2015

Member

same here

# cat.name # => 'Gorby'
# cat.status => 'sleeping'
def assign_attributes(new_attributes)
if !new_attributes.respond_to?(:stringify_keys)

This comment has been minimized.

Copy link
@vipulnsward

vipulnsward Jan 23, 2015

Member

We can check hash type instead of respond here.

This comment has been minimized.

Copy link
@bogdan

bogdan Jan 23, 2015

Author Contributor

Dunno, extracted it as it is from ActiveRecord. If it should be changed - lets do investigation why it is done like this and change it in another patch.

This comment has been minimized.

Copy link
@sgrif

sgrif Jan 23, 2015

Contributor

Yeah, I agree with @bogdan here. In general, I'd rather see respond_to? over is_a?.

This comment has been minimized.

Copy link
@PikachuEXE

PikachuEXE May 19, 2016

Contributor

Why is this using if ! instead of unless?

This comment has been minimized.

Copy link
@theoros

theoros Oct 28, 2016

I personally think it's easier to read if ! than unless...

@vipulnsward
vipulnsward reviewed Jan 23, 2015
View changes
activemodel/lib/active_model/attribute_assignment.rb Outdated

def initialize(record, attribute)
@record = record
@attribute = attribute.to_s

This comment has been minimized.

Copy link
@vipulnsward

vipulnsward Jan 23, 2015

Member

I think the to_s is extra here.

…utesAssignment`

Allows to use it for any object as an includable module.
@bogdan bogdan force-pushed the bogdan:assign-attributes branch to 2606fb3 Jan 23, 2015
@sgrif sgrif merged commit 2606fb3 into rails:master Jan 23, 2015
1 check was pending
1 check was pending
continuous-integration/travis-ci The Travis CI build is in progress
Details
sgrif added a commit that referenced this pull request Jan 23, 2015
Minor style changes across the board. Changed an alias to an explicit
method declaration, since the alias will not be documented otherwise.
sgrif added a commit that referenced this pull request Jan 23, 2015
Extracted attributes assingment from ActiveRecord to ActiveModel
@egilburg
Copy link
Contributor

egilburg commented Jan 23, 2015

❤️

@egilburg
Copy link
Contributor

egilburg commented Jan 23, 2015

I wonder if, once all non-db-specific logic (including recent one such as the user-facing casting half) is extracted to AM, it would make sense to have a more full-featured out-of-the-box implementation of active model for those that want it to behave not just as a form object but as much as a full AR as possible, except not persisted. That means all the same validations/errors, attribute assignment, casting, etc.

Perhaps call it ActiveModel::Base which would be a richer implementation than ActiveModel::Model, possibly extending it.

end
UnknownAttributeError = ActiveSupport::Deprecation::DeprecatedConstantProxy.new( # :nodoc:
'ActiveRecord::UnknownAttributeError',
'ActiveModel::AttributeAssignment::UnknownAttributeError'

This comment has been minimized.

Copy link
@egilburg

egilburg Jan 24, 2015

Contributor

Given that end users may be rescuing from this error in their apps, it seems like a rather long and implementation-specific namespace. Perhaps keep it under ActiveModel::UnknownAttributeError?

This comment has been minimized.

Copy link
@robin850

robin850 Jan 31, 2015

Member

Yep, I agree there ; this is too implementation-specific! 👍

This comment has been minimized.

Copy link
@sgrif

sgrif Jan 31, 2015

Contributor

Agreed, let's leave this undeprecated, and just alias it. It's an unnecessary change for users, and forces them to care too much about implementation.

This comment has been minimized.

Copy link
@sgrif

sgrif Jan 31, 2015

Contributor

@robin850 Would you care to open a PR?

This comment has been minimized.

Copy link
@bogdan

bogdan Jan 31, 2015

Author Contributor

Leaving this undeprecated can cause confusion because while constant alias will work the caught exception instances will still have new name. It looks like people are just yelling about too long name space and want it to be sorter like in @egilburg's comment

@robin850 robin850 mentioned this pull request Feb 25, 2015
robin850 added a commit to robin850/rails that referenced this pull request Feb 26, 2015
The name `ActiveModel::AttributeAssignment::UnknownAttributeError` is
too implementation specific so let's move the constant directly under
the ActiveModel namespace.

Also since this constant used to be under the ActiveRecord namespace, to
make the upgrade path easier, let's avoid raising the former constant
when we deal with this error on the Active Record side.
@rafaelfranca rafaelfranca modified the milestones: 5.0.0 [temp], 5.0.0 Dec 30, 2015
@m0ur3n

This comment has been minimized.

Copy link

m0ur3n commented on activemodel/CHANGELOG.md in 2606fb3 Jul 20, 2016

should it be

cat.status # => 'sleeping'

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Linked issues

Successfully merging this pull request may close these issues.

None yet

You can’t perform that action at this time.