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

NoMethodError: undefined method `where' for HistoryTracker:Class #169

Open
prasadsurase opened this issue Sep 13, 2016 · 20 comments
Open

NoMethodError: undefined method `where' for HistoryTracker:Class #169

prasadsurase opened this issue Sep 13, 2016 · 20 comments
Labels

Comments

@prasadsurase
Copy link

I am using mongoid-history(0.5.0) with an rails(5.0.0) and mongoid(github master branch). The changes are

#app/models/history_tracker.rb
class HistoryTracker
  include Mongoid::History::Trackable
end

#config/initializers/history_tracker.rb
Mongoid::History.tracker_class_name = :history_tracker

#app/models/user.rb
class User
  include Mongoid::Document
  include Mongoid::Timestamps
  include Mongoid::History::Trackable
  include Mongoid::Attributes::Dynamic

  ...
  field :name, type: String
  field :points, type: Integer, default: 0
  ...

  track_history on: [:name, :points], track_create: false, track_update: true, track_destroy: true
end

When I run 'user.history_tracks' in rails console, I get

2.3.0 :012 > user = User.last
 => #<User _id: 10de0dd7710542, created_at: 2016-09-13 15:10:07 UTC, updated_at: 2016-09-13 15:10:07 UTC, email: "[email protected]", encrypted_password: "$2a$10$ByExx918bnV6", remember_created_at: nil, sign_in_count: 1, current_sign_in_at: 2016-09-13 15:10:07 UTC, last_sign_in_at: 2016-09-13 15:10:07 UTC, current_sign_in_ip: "::1", last_sign_in_ip: "::1", github_handle: "prasad", active: true, name: "Prasad Surase", provider: "github", uid: "56", avatar_url: "https://avatars.githubusercontent.com/u/56?v=3", points: 0, version: nil, modifier_id: nil> 
2.3.0 :013 > user.version
 => nil 
2.3.0 :014 > user.modifier_id
 => nil 
2.3.0 :015 > user.history_trac
user.history_trackable_options  user.history_tracks             
2.3.0 :015 > user.history_tracks
NoMethodError: undefined method `where' for HistoryTracker:Class
    from /Users/prasad/.rvm/gems/ruby-2.3.0/gems/mongoid-history-0.5.0/lib/mongoid/history/trackable.rb:75:in `history_tracks'
    from (irb):15
    from /Users/prasad/.rvm/gems/ruby-2.3.0/gems/railties-4.2.5/lib/rails/commands/console.rb:110:in `start'
    from /Users/prasad/.rvm/gems/ruby-2.3.0/gems/railties-4.2.5/lib/rails/commands/console.rb:9:in `start'
    from /Users/prasad/.rvm/gems/ruby-2.3.0/gems/railties-4.2.5/lib/rails/commands/commands_tasks.rb:68:in `console'
    from /Users/prasad/.rvm/gems/ruby-2.3.0/gems/railties-4.2.5/lib/rails/commands/commands_tasks.rb:39:in `run_command!'
    from /Users/prasad/.rvm/gems/ruby-2.3.0/gems/railties-4.2.5/lib/rails/commands.rb:17:in `<top (required)>'
    from ./bin/rails:4:in `require'
    from ./bin/rails:4:in `<main>'

Am I missing something or is this a valid bug?

@dblock
Copy link
Collaborator

dblock commented Sep 13, 2016

I released 0.6.0 an hour ago, can you please try that?

@dblock dblock added the bug? label Sep 13, 2016
@prasadsurase
Copy link
Author

prasadsurase commented Sep 14, 2016

@dblock I created sample app using ruby 2.3.0, rails 5.0.0, mongoid(github master branch) and mongoid(0.6.0).

  1. Can't create a new User because of validation errors.
2.3.0 :014 >   user = User.create(email: '[email protected]', password: 'prasad123', password_confirmation: 'prasad123')
 => #<User _id: BSON::ObjectId('57d8e68b5f10de200053b8f6'), created_at: nil, email: "[email protected]", modifier_id: nil, name: nil, points: 0, updated_at: nil, version: nil> 
2.3.0 :015 > user.valid?
 => false 
2.3.0 :016 > user.errors
 => #<ActiveModel::Errors:0x007f9af9def670 @base=#<User _id: BSON::ObjectId('57d8e68b5f10de200053b8f6'), created_at: nil, email: "[email protected]", modifier_id: nil, name: nil, points: 0, updated_at: nil, version: nil>, @messages={:modifier=>["can't be blank"]}, @details={:modifier=>[{:error=>:blank}]}>

Also, I tried using the latest version(0.6.0) for an existing open-source project and it results in the same error( NoMethodError: undefined method `where' for HistoryTracker:Class). This
is the commit where I have tried to integrate mongoid-history. Please feel free to clone the repo to check locally.

@sivagollapalli
Copy link
Contributor

@dblock This issue has been raised because of belongs_to_required_by_default has been set to true once we add mongoid-history gem in Gemfile actually it should not. I have gone through code but I didn't find anywhere where we are overriding mongoid options.

@dblock
Copy link
Collaborator

dblock commented Sep 14, 2016

I would try to turn it into a failing spec here next.

@prasadsurase
Copy link
Author

@dblock @sivagollapalli that might be the case but the app link that I have provided in the latest comment runs on rails 4.2.

@prasadsurase
Copy link
Author

for further explanation,

2.3.0 :003 > HistoryTracker.ancestors
 => [HistoryTracker, Mongoid::History::Trackable, Object, PP::ObjectMixin, EasyDiff::SafeDup, ActiveSupport::Dependencies::Loadable, Mongoid::Extensions::Object, BSON::Object, Origin::Extensions::Object, JSON::Ext::Generator::GeneratorMethods::Object, Kernel, BasicObject] 

expect for Mongoid::History::Trackable and Mongoid::Extensions::Object no other Mongoid classes/modules are present in the chain which seems weird.

@Ninigi
Copy link

Ninigi commented Nov 16, 2016

Not entirely sure if this is related, but I'll just throw it out there.

I've had an issue with Rails 5.0.1, Mongoid 6.0.2 and Mongoid-History 0.6.0. The app acts as a standalone API and shares its database with a Rails 4 app.
The Rails 5 app is read-only and I did not have a problem with it up until today when I opened a rails console and tried to update a record, which always returned false.
Even without calling save or validate every record had errors and was invalid right from when loaded. When I inspected the errors I got

record.errors.messages
#=> :modifier=>["can't be blank"]

So, after a little research (with a short stop in this thread) I ended up reading the mongoid config specs and realised they are setting Mongoid.belongs_to_required_by_default = true by default, which is in compliance with the rails 5 active record default setting (changed from default = false to default = true), but screwed up everything when not saving a modifier.

Simply adding an initializer solved the problem:

# config/initializers/mongoid_belongs_to_required_by_default.rb

Mongoid.belongs_to_required_by_default = false

@dblock
Copy link
Collaborator

dblock commented Nov 16, 2016

It sounds like a separate (and real) problem @Ninigi.

@Ninigi
Copy link

Ninigi commented Nov 18, 2016

@dblock so, should I open an issue? The problem is an unexpected behaviour because of the Mongoid default setting, a simple comment about it in the README would already fix it (since you only need to add the initializer)

@dblock
Copy link
Collaborator

dblock commented Nov 18, 2016

I think you should and maybe try to write a spec for it? At the very least it's a bug, and your solution is a workaround, but we should actually fix the underlying issue.

@Ninigi
Copy link

Ninigi commented Nov 18, 2016

Ok, will do. I think the solution is going to be easy enough, so probably will have a PR attached. Thanks for your time :)

@DarthHater
Copy link

@Ninigi you just saved my butt on a project, thanks for that.

@Ninigi
Copy link

Ninigi commented Mar 31, 2017

@DarthHater thanks for the PR, I wanted to do it and never found the time... And then I forgot >.<

@dblock
Copy link
Collaborator

dblock commented Mar 31, 2017

What do we do with this issue here? Looks like Mongoid.belongs_to_required_by_default was required? Not sure I understand what's going on.

@Ninigi
Copy link

Ninigi commented Mar 31, 2017

@dblock The issue basically is that ActiveRecord changed its policy towards relations with Rails 5. Before, when you defined a belongs_to relation, the foreign key was not required (could be null or not), now it is required by default unless stated otherwise.

Mongoid adopted that behavior, which breaks mongoid-history if you try to save a history without setting the modifier_id (belongs_to relation), because modifier_id will now be validated for presence by default - hence the :modifier => "cant be blank" error message.

It is not related to the original issue I think, but rather to the issue that prasadsurase ran into when creating a sample app:

2.3.0 :014 >   user = User.create(email: '[email protected]', password: 'prasad123', password_confirmation: 'prasad123')
 => #<User _id: BSON::ObjectId('57d8e68b5f10de200053b8f6'), created_at: nil, email: "[email protected]", modifier_id: nil, name: nil, points: 0, updated_at: nil, version: nil> 
2.3.0 :015 > user.valid?
 => false 
2.3.0 :016 > user.errors
 => #<ActiveModel::Errors:0x007f9af9def670 @base=#<User _id: BSON::ObjectId('57d8e68b5f10de200053b8f6'), created_at: nil, email: "[email protected]", modifier_id: nil, name: nil, points: 0, updated_at: nil, version: nil>, @messages={:modifier=>["can't be blank"]}, @details={:modifier=>[{:error=>:blank}]}>

@dblock
Copy link
Collaborator

dblock commented Apr 2, 2017

Okay, so I think what we need is either or both documentation that explains this in README and much better error messaging. Care to contribute @Ninigi?

@jkras
Copy link

jkras commented Apr 27, 2017

Would love to help, though kind of new to open source.

I'm facing the same issue - switching belongs_to_required_by_default off allows me to crud my models but obviously doesn't track the user that did it as there is nothing forcing MH to write the modifier.

When I don't turn it off, I simply get an :modifier=>["can't be blank"] error.

Can't establish if I should set the modifier manually (doesn't seem like the correct approach), or how to debug this and have mongoid history set the modifier to the current_user

Additionally, I'm running rails 5.0.2, mongoid 6.1.0, mongoid-history 0.6.1, devise 4.2.1 (also running cancancan)...

Thanks!

@jkras
Copy link

jkras commented Apr 27, 2017

I have a solution to my question. Posting it for feedback, or in case anyone else has the problem ...

In #139 @dblock mentions that you need to set the modifier explicitly. Seeing as though there is one model at the moment that I want to track changes in, I've added a merge to the strong params method which now looks like this:

def object_params
      params.require(:object).permit(:field1, :field2).merge(modifier: current_user)
end

This works, so I'll keep it like this for now, unless anyone has a better implementation idea

@ErvalhouS
Copy link

Issue for me was that creating through console the modifier_id needs to be passed manually or as some id from seed or as default value like, example:

  field :modifier_id, type: String, default: -> { self._id }

@alexismansilla
Copy link

thanks for that @Ninigi

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

No branches or pull requests

8 participants