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

Prepare to release 6.5 #968

Merged
merged 4 commits into from
Oct 29, 2019
Merged

Prepare to release 6.5 #968

merged 4 commits into from
Oct 29, 2019

Conversation

seuros
Copy link
Collaborator

@seuros seuros commented Sep 8, 2019

Support for ActiveRecord 6.

@seuros seuros mentioned this pull request Sep 8, 2019
@masonhensley
Copy link

masonhensley commented Sep 15, 2019

@seuros - is this intended to replace #951 for rails 6 support? If so, thanks! Do you need any help? 🤓

Related Issue: #961

.travis.yml Outdated Show resolved Hide resolved
@mkilling
Copy link
Contributor

mkilling commented Sep 17, 2019

We still have one failing test case with ActiveRecord 6.0. Once this is resolved, is everything ready for a release?

 1) Dirty behavior of taggable objects with un-contexted tags when tag_list changed should show changes of freshly initialized dirty object
     Failure/Error: expect(taggable.changes).to eq({'tag_list' => [['awesome', 'epic'], ['one']]})
     
       expected: {"tag_list"=>[["awesome", "epic"], ["one"]]}
            got: {"tag_list"=>[nil, ["one"]]}
     
       (compared using ==)
     
       Diff:
       @@ -1,2 +1,2 @@
       -"tag_list" => [["awesome", "epic"], ["one"]],
       +"tag_list" => [nil, ["one"]],
       
     # /Users/mkilling/.rvm/gems/ruby-2.5.3@acts-as-taggable-on/gems/rspec-support-3.8.2/lib/rspec/support.rb:97:in `block in <module:Support>'
     # /Users/mkilling/.rvm/gems/ruby-2.5.3@acts-as-taggable-on/gems/rspec-support-3.8.2/lib/rspec/support.rb:106:in `notify_failure'
     # /Users/mkilling/.rvm/gems/ruby-2.5.3@acts-as-taggable-on/gems/rspec-expectations-3.8.4/lib/rspec/expectations/fail_with.rb:35:in `fail_with'
     # /Users/mkilling/.rvm/gems/ruby-2.5.3@acts-as-taggable-on/gems/rspec-expectations-3.8.4/lib/rspec/expectations/handler.rb:38:in `handle_failure'
     # /Users/mkilling/.rvm/gems/ruby-2.5.3@acts-as-taggable-on/gems/rspec-expectations-3.8.4/lib/rspec/expectations/handler.rb:50:in `block in handle_matcher'
     # /Users/mkilling/.rvm/gems/ruby-2.5.3@acts-as-taggable-on/gems/rspec-expectations-3.8.4/lib/rspec/expectations/handler.rb:27:in `with_matcher'
     # /Users/mkilling/.rvm/gems/ruby-2.5.3@acts-as-taggable-on/gems/rspec-expectations-3.8.4/lib/rspec/expectations/handler.rb:48:in `handle_matcher'
     # /Users/mkilling/.rvm/gems/ruby-2.5.3@acts-as-taggable-on/gems/rspec-expectations-3.8.4/lib/rspec/expectations/expectation_target.rb:65:in `to'
     # ./spec/acts_as_taggable_on/dirty_spec.rb:23:in `block (4 levels) in <top (required)>'
     # /Users/mkilling/.rvm/gems/ruby-2.5.3@acts-as-taggable-on/gems/rspec-core-3.8.2/lib/rspec/core/example.rb:257:in `instance_exec'
     # /Users/mkilling/.rvm/gems/ruby-2.5.3@acts-as-taggable-on/gems/rspec-core-3.8.2/lib/rspec/core/example.rb:257:in `block in run'
     # /Users/mkilling/.rvm/gems/ruby-2.5.3@acts-as-taggable-on/gems/rspec-core-3.8.2/lib/rspec/core/example.rb:503:in `block in with_around_and_singleton_context_hooks'
     # /Users/mkilling/.rvm/gems/ruby-2.5.3@acts-as-taggable-on/gems/rspec-core-3.8.2/lib/rspec/core/example.rb:460:in `block in with_around_example_hooks'
     # /Users/mkilling/.rvm/gems/ruby-2.5.3@acts-as-taggable-on/gems/rspec-core-3.8.2/lib/rspec/core/hooks.rb:464:in `block in run'
     # /Users/mkilling/.rvm/gems/ruby-2.5.3@acts-as-taggable-on/gems/rspec-core-3.8.2/lib/rspec/core/hooks.rb:602:in `run_around_example_hooks_for'
     # /Users/mkilling/.rvm/gems/ruby-2.5.3@acts-as-taggable-on/gems/rspec-core-3.8.2/lib/rspec/core/hooks.rb:464:in `run'
     # /Users/mkilling/.rvm/gems/ruby-2.5.3@acts-as-taggable-on/gems/rspec-core-3.8.2/lib/rspec/core/example.rb:460:in `with_around_example_hooks'
     # /Users/mkilling/.rvm/gems/ruby-2.5.3@acts-as-taggable-on/gems/rspec-core-3.8.2/lib/rspec/core/example.rb:503:in `with_around_and_singleton_context_hooks'
     # /Users/mkilling/.rvm/gems/ruby-2.5.3@acts-as-taggable-on/gems/rspec-core-3.8.2/lib/rspec/core/example.rb:254:in `run'
     # /Users/mkilling/.rvm/gems/ruby-2.5.3@acts-as-taggable-on/gems/rspec-core-3.8.2/lib/rspec/core/example_group.rb:633:in `block in run_examples'
     # /Users/mkilling/.rvm/gems/ruby-2.5.3@acts-as-taggable-on/gems/rspec-core-3.8.2/lib/rspec/core/example_group.rb:629:in `map'
     # /Users/mkilling/.rvm/gems/ruby-2.5.3@acts-as-taggable-on/gems/rspec-core-3.8.2/lib/rspec/core/example_group.rb:629:in `run_examples'
     # /Users/mkilling/.rvm/gems/ruby-2.5.3@acts-as-taggable-on/gems/rspec-core-3.8.2/lib/rspec/core/example_group.rb:595:in `run'
     # /Users/mkilling/.rvm/gems/ruby-2.5.3@acts-as-taggable-on/gems/rspec-core-3.8.2/lib/rspec/core/example_group.rb:596:in `block in run'
     # /Users/mkilling/.rvm/gems/ruby-2.5.3@acts-as-taggable-on/gems/rspec-core-3.8.2/lib/rspec/core/example_group.rb:596:in `map'
     # /Users/mkilling/.rvm/gems/ruby-2.5.3@acts-as-taggable-on/gems/rspec-core-3.8.2/lib/rspec/core/example_group.rb:596:in `run'
     # /Users/mkilling/.rvm/gems/ruby-2.5.3@acts-as-taggable-on/gems/rspec-core-3.8.2/lib/rspec/core/example_group.rb:596:in `block in run'
     # /Users/mkilling/.rvm/gems/ruby-2.5.3@acts-as-taggable-on/gems/rspec-core-3.8.2/lib/rspec/core/example_group.rb:596:in `map'
     # /Users/mkilling/.rvm/gems/ruby-2.5.3@acts-as-taggable-on/gems/rspec-core-3.8.2/lib/rspec/core/example_group.rb:596:in `run'
     # /Users/mkilling/.rvm/gems/ruby-2.5.3@acts-as-taggable-on/gems/rspec-core-3.8.2/lib/rspec/core/runner.rb:116:in `block (3 levels) in run_specs'
     # /Users/mkilling/.rvm/gems/ruby-2.5.3@acts-as-taggable-on/gems/rspec-core-3.8.2/lib/rspec/core/runner.rb:116:in `map'
     # /Users/mkilling/.rvm/gems/ruby-2.5.3@acts-as-taggable-on/gems/rspec-core-3.8.2/lib/rspec/core/runner.rb:116:in `block (2 levels) in run_specs'
     # /Users/mkilling/.rvm/gems/ruby-2.5.3@acts-as-taggable-on/gems/rspec-core-3.8.2/lib/rspec/core/configuration.rb:2008:in `with_suite_hooks'
     # /Users/mkilling/.rvm/gems/ruby-2.5.3@acts-as-taggable-on/gems/rspec-core-3.8.2/lib/rspec/core/runner.rb:111:in `block in run_specs'
     # /Users/mkilling/.rvm/gems/ruby-2.5.3@acts-as-taggable-on/gems/rspec-core-3.8.2/lib/rspec/core/reporter.rb:74:in `report'
     # /Users/mkilling/.rvm/gems/ruby-2.5.3@acts-as-taggable-on/gems/rspec-core-3.8.2/lib/rspec/core/runner.rb:110:in `run_specs'
     # /Users/mkilling/.rvm/gems/ruby-2.5.3@acts-as-taggable-on/gems/rspec-core-3.8.2/lib/rspec/core/runner.rb:87:in `run'
     # /Users/mkilling/.rvm/gems/ruby-2.5.3@acts-as-taggable-on/gems/rspec-core-3.8.2/lib/rspec/core/runner.rb:71:in `run'
     # /Users/mkilling/.rvm/gems/ruby-2.5.3@acts-as-taggable-on/gems/rspec-core-3.8.2/lib/rspec/core/runner.rb:45:in `invoke'
     # /Users/mkilling/.rvm/gems/ruby-2.5.3@acts-as-taggable-on/gems/rspec-core-3.8.2/exe/rspec:4:in `<main>'

if ActsAsTaggableOn::Utils.legacy_activerecord?
set_attribute_was("#{tag_type}_list", #{tag_type}_list)
else
attribute_change("#{tag_type}_list")
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If my current understanding is correct, this line is supposed to set the 'previous' value of the *_list attribute. It seems that attribute_change is not the right method to do this. I’ve quickly looked into the code for AttributeMutationTracker but I’m not quite sure yet what’s the best way to replicate the behavior of set_attribute_was in AR 6.0.

Ideas welcome.

Copy link

@cristian-rivera cristian-rivera Sep 19, 2019

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Perhaps we could use {attribute}_will_change! as seen here in Rails 6 as well: https://api.rubyonrails.org/classes/ActiveModel/Dirty.html

If an attribute is modified in-place then make use of [attribute_name]_will_change! to mark that the attribute is changing. Otherwise Active Model can't track changes to in-place attributes. Note that Active Record can detect in-place modifications automatically. You do not need to call [attribute_name]_will_change! on Active Record models.

person.name_will_change!
person.name_change # => ["Bill", "Bill"]
person.name << 'y'
person.name_change # => ["Bill", "Billy"]

image

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The problem is a bit different though. It’s that in this test case original value for tag_list is nil and not ["awesome", "epic"] as expected. ActiveRecord picks up that the attribute has been changed, but it does not print the correct previous value.

taggable = TaggableModel.find(@taggable.id)
taggable.tag_list
# => ["awesome", "epic"]
taggable.tag_list_will_change!
taggable.tag_list_change
# => [nil, nil]
taggable.tag_list = 'one'
taggable.tag_list_change
# => [nil, ["one"]]

@mkilling
Copy link
Contributor

mkilling commented Sep 19, 2019

It seems that #955 is somewhat related to this

@edd1312
Copy link

edd1312 commented Oct 4, 2019

I changed the core.rb file to:

if self.class.preserve_tag_order? || (parsed_new_list.sort != #{tag_type}_list.sort)
                if ActsAsTaggableOn::Utils.legacy_activerecord?
                  attribute_will_change! "#{tag_type}_list"
                  save
                else
                  attribute_change("#{tag_type}_list")
                end
                write_attribute("#{tag_type}_list", parsed_new_list)
              end

and it works !!!

@mkilling
Copy link
Contributor

mkilling commented Oct 4, 2019

@edd1312 Thanks for trying that out. If I understand your code correctly, it will still not work on ActiveRecord 6.0. Also, I’m not convinced that saving the record should be a side effect of assigning to the tag_type_list.

@edd1312
Copy link

edd1312 commented Oct 4, 2019

@mkilling i tried it with the branch #951 .
making the changes in this branch it would be:


if self.class.preserve_tag_order? || (parsed_new_list.sort != #{tag_type}_list.sort)
                write_attribute("#{tag_type}_list", #{tag_type}_list )
                attribute_will_change! "#{tag_type}_list"
                save
                write_attribute("#{tag_type}_list", parsed_new_list)
              end

making this changes it returns this result

.........................................................................*......
on/spec/acts_as_taggable_on/dirty_spec.rb
   18:       end
   19: 
   20:       it 'should show changes of freshly initialized dirty object' do
   21:         taggable = TaggableModel.find(@taggable.id)
   22:         byebug
=> 23:         taggable.tag_list = 'one'
   24:         expect(taggable.changes).to eq({'tag_list' => [['awesome', 'epic'], ['one']]})
   25:       end
   26: 
   27:       if Rails.version >= "5.1"
(byebug) continue
..................................................................................................log writing failed. "\xE3" from ASCII-8BIT to UTF-8
........................................................log writing failed. "\xE6" from ASCII-8BIT to UTF-8
.log writing failed. "\xD7" from ASCII-8BIT to UTF-8
.log writing failed. "\xE4" from ASCII-8BIT to UTF-8
.log writing failed. "\xD8" from ASCII-8BIT to UTF-8
.log writing failed. "\xE2" from ASCII-8BIT to UTF-8
....log writing failed. "\xD0" from ASCII-8BIT to UTF-8
....log writing failed. "\xD0" from ASCII-8BIT to UTF-8
.........................................

Pending: (Failures listed here are expected and do not affect your suite's status)

  1) Acts As Taggable On CachingWithArray #TODO
     # Not yet implemented
     # ./spec/acts_as_taggable_on/caching_spec.rb:127


Finished in 7.37 seconds (files took 0.97566 seconds to load)
287 examples, 0 failures, 1 pending

perhaps this is not the best solutions but it works for me

@mkilling
Copy link
Contributor

mkilling commented Oct 5, 2019

This works for me:

if self.class.preserve_tag_order? || (parsed_new_list.sort != #{tag_type}_list.sort)
  if ActsAsTaggableOn::Utils.legacy_activerecord?
    set_attribute_was("#{tag_type}_list", #{tag_type}_list)
  else
    unless #{tag_type}_list_changed?
      @attributes["#{tag_type}_list"] = ActiveModel::Attribute.from_user("#{tag_type}_list", #{tag_type}_list, ActsAsTaggableOn::Taggable::TagListType.new)
    end
  end
  write_attribute("#{tag_type}_list", parsed_new_list)
end

Can anybody who’s more familiar with ActiveModel tell me if there are any problems with this solution?

(Edit: fixed my proposed code for multiple updates of #{tag_type}_list)

@mkilling
Copy link
Contributor

mkilling commented Oct 5, 2019

@seuros Given my proposed change above is acceptable, what are the next steps towards releasing version 6.5? I’m tracking my changes in https://github.com/mkilling/acts-as-taggable-on/tree/support-rails-6. I can raise a pull request.

@jackbot
Copy link

jackbot commented Oct 8, 2019

This LGTM, it'd be great to get Rails 6 support!

@edd1312
Copy link

edd1312 commented Oct 20, 2019

for those that want to add the mkilling rails 6 support solution. the line in Gemfile should be:
gem 'acts-as-taggable-on',github:"mkilling/acts-as-taggable-on",branch:"support-rails-6"

@mkilling
Copy link
Contributor

@mbleigh @seuros It would be great if we could merge this and make it a release. How can we move this forward? Thanks!

@seuros
Copy link
Collaborator Author

seuros commented Oct 21, 2019 via email

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

Successfully merging this pull request may close these issues.

6 participants