Comments (7)
Sorry for the delay in getting back to you on this.
The generator now works for the most part, but it fails for models that don't inherit from ApplicationModel
(my base model that inherits from ActiveRecord::Base
). I realize I previously told you that all my models inherit from ApplicationModel, but that's actually not true—my apologies.
I've got a few "pseudo-models" that don't inherit from any class, that just act as models for certain purposes in my application. One such pseudo-model looks like this:
class UserRegistration
include ActiveModel::Validations
include ActiveModel::Conversion
extend ActiveModel::Naming
...
For what it's worth, this is not a fringe case: it's something I've seen other devs do and there are many blog posts and StackOverflow questions about it.
The other failure I'm seeing is my omniauth-identity model, which looks like this:
class Identity < OmniAuth::Identity::Models::ActiveRecord
...
These models all produce errors like this:
Errno::ENOENT: No such file or directory @ rb_sysopen - ~/app/models/.rb
~/.rvm/gems/ruby-2.1.0@gemset/bundler/gems/active_mocker-e5c2285ad9c4/lib/active_mocker/file_reader.rb:6:in `initialize'
~/.rvm/gems/ruby-2.1.0@gemset/bundler/gems/active_mocker-e5c2285ad9c4/lib/active_mocker/file_reader.rb:6:in `open'
~/.rvm/gems/ruby-2.1.0@gemset/bundler/gems/active_mocker-e5c2285ad9c4/lib/active_mocker/file_reader.rb:6:in `read'
~/.rvm/gems/ruby-2.1.0@gemset/bundler/gems/active_mocker-e5c2285ad9c4/lib/active_mocker/model_reader.rb:69:in `read_file'
~/.rvm/gems/ruby-2.1.0@gemset/bundler/gems/active_mocker-e5c2285ad9c4/lib/active_mocker/model_reader.rb:31:in `load_parent_class'
~/.rvm/gems/ruby-2.1.0@gemset/bundler/gems/active_mocker-e5c2285ad9c4/lib/active_mocker/model_reader.rb:23:in `sandbox_model'
~/.rvm/gems/ruby-2.1.0@gemset/bundler/gems/active_mocker-e5c2285ad9c4/lib/active_mocker/model_reader.rb:15:in `klass'
~/.rvm/gems/ruby-2.1.0@gemset/bundler/gems/active_mocker-e5c2285ad9c4/lib/active_mocker/model_reader.rb:10:in `parse'
~/.rvm/gems/ruby-2.1.0@gemset/bundler/gems/active_mocker-e5c2285ad9c4/lib/active_mocker/model_schema/assemble.rb:161:in `get_model'
~/.rvm/gems/ruby-2.1.0@gemset/bundler/gems/active_mocker-e5c2285ad9c4/lib/active_mocker/model_schema/assemble.rb:36:in `block in run'
~/.rvm/gems/ruby-2.1.0@gemset/bundler/gems/active_mocker-e5c2285ad9c4/lib/active_mocker/model_schema/assemble.rb:35:in `map'
~/.rvm/gems/ruby-2.1.0@gemset/bundler/gems/active_mocker-e5c2285ad9c4/lib/active_mocker/model_schema/assemble.rb:35:in `run'
~/.rvm/gems/ruby-2.1.0@gemset/bundler/gems/active_mocker-e5c2285ad9c4/lib/active_mocker/generate.rb:17:in `generate_model_schema'
~/.rvm/gems/ruby-2.1.0@gemset/bundler/gems/active_mocker-e5c2285ad9c4/lib/active_mocker/generate.rb:40:in `create_template'
~/.rvm/gems/ruby-2.1.0@gemset/bundler/gems/active_mocker-e5c2285ad9c4/lib/active_mocker/generate.rb:11:in `initialize'
~/.rvm/gems/ruby-2.1.0@gemset/bundler/gems/active_mocker-e5c2285ad9c4/lib/active_mocker/task.rake:5:in `new'
~/.rvm/gems/ruby-2.1.0@gemset/bundler/gems/active_mocker-e5c2285ad9c4/lib/active_mocker/task.rake:5:in `block (2 levels) in <top (required)>'
~/.rvm/gems/ruby-2.1.0@gemset/bin/ruby_executable_hooks:15:in `eval'
Using the code on master, when I don't add an initializer to configure ActiveMocker, I am able to run the mock generation for the most part, except for these failures. However, when I add a configure block as you suggest, the generator immediately fails:
ActiveMocker.configure do |config|
config.model_base_classes = %w[ ActiveRecord::Base ApplicationModel ]
end
rake aborted!
ActiveMocker::Config #schema_file must be specified!
~/.rvm/gems/ruby-2.1.0@gemset/bundler/gems/active_mocker-e5c2285ad9c4/lib/active_mocker/config.rb:30:in `block in check_required_settings'
~/.rvm/gems/ruby-2.1.0@gemset/bundler/gems/active_mocker-e5c2285ad9c4/lib/active_mocker/config.rb:29:in `each'
~/.rvm/gems/ruby-2.1.0@gemset/bundler/gems/active_mocker-e5c2285ad9c4/lib/active_mocker/config.rb:29:in `check_required_settings'
~/.rvm/gems/ruby-2.1.0@gemset/bundler/gems/active_mocker-e5c2285ad9c4/lib/active_mocker/config.rb:16:in `set'
~/.rvm/gems/ruby-2.1.0@gemset/bundler/gems/active_mocker-e5c2285ad9c4/lib/active_mocker/public_methods.rb:27:in `configure'
~/app/config/initializers/active_mocker.rb:1:in `<top (required)>'
~/.rvm/gems/ruby-2.1.0@gemset/gems/activesupport-4.1.1/lib/active_support/dependencies.rb:241:in `load'
~/.rvm/gems/ruby-2.1.0@gemset/gems/activesupport-4.1.1/lib/active_support/dependencies.rb:241:in `block in load'
~/.rvm/gems/ruby-2.1.0@gemset/gems/activesupport-4.1.1/lib/active_support/dependencies.rb:232:in `load_dependency'
~/.rvm/gems/ruby-2.1.0@gemset/gems/activesupport-4.1.1/lib/active_support/dependencies.rb:241:in `load'
~/.rvm/gems/ruby-2.1.0@gemset/gems/railties-4.1.1/lib/rails/engine.rb:648:in `block in load_config_initializer'
~/.rvm/gems/ruby-2.1.0@gemset/gems/activesupport-4.1.1/lib/active_support/notifications.rb:161:in `instrument'
~/.rvm/gems/ruby-2.1.0@gemset/gems/railties-4.1.1/lib/rails/engine.rb:647:in `load_config_initializer'
~/.rvm/gems/ruby-2.1.0@gemset/gems/railties-4.1.1/lib/rails/engine.rb:612:in `block (2 levels) in <class:Engine>'
~/.rvm/gems/ruby-2.1.0@gemset/gems/railties-4.1.1/lib/rails/engine.rb:611:in `each'
~/.rvm/gems/ruby-2.1.0@gemset/gems/railties-4.1.1/lib/rails/engine.rb:611:in `block in <class:Engine>'
~/.rvm/gems/ruby-2.1.0@gemset/gems/railties-4.1.1/lib/rails/initializable.rb:30:in `instance_exec'
~/.rvm/gems/ruby-2.1.0@gemset/gems/railties-4.1.1/lib/rails/initializable.rb:30:in `run'
~/.rvm/gems/ruby-2.1.0@gemset/gems/railties-4.1.1/lib/rails/initializable.rb:55:in `block in run_initializers'
~/.rvm/gems/ruby-2.1.0@gemset/gems/railties-4.1.1/lib/rails/initializable.rb:44:in `each'
~/.rvm/gems/ruby-2.1.0@gemset/gems/railties-4.1.1/lib/rails/initializable.rb:44:in `tsort_each_child'
~/.rvm/gems/ruby-2.1.0@gemset/gems/railties-4.1.1/lib/rails/initializable.rb:54:in `run_initializers'
~/.rvm/gems/ruby-2.1.0@gemset/gems/railties-4.1.1/lib/rails/application.rb:288:in `initialize!'
~/app/config/environment.rb:5:in `<top (required)>'
~/.rvm/gems/ruby-2.1.0@gemset/gems/activesupport-4.1.1/lib/active_support/dependencies.rb:247:in `require'
~/.rvm/gems/ruby-2.1.0@gemset/gems/activesupport-4.1.1/lib/active_support/dependencies.rb:247:in `block in require'
~/.rvm/gems/ruby-2.1.0@gemset/gems/activesupport-4.1.1/lib/active_support/dependencies.rb:232:in `load_dependency'
~/.rvm/gems/ruby-2.1.0@gemset/gems/activesupport-4.1.1/lib/active_support/dependencies.rb:247:in `require'
~/.rvm/gems/ruby-2.1.0@gemset/gems/railties-4.1.1/lib/rails/application.rb:264:in `require_environment!'
~/.rvm/gems/ruby-2.1.0@gemset/gems/railties-4.1.1/lib/rails/application.rb:367:in `block in run_tasks_blocks'
~/.rvm/gems/ruby-2.1.0@gemset/bin/ruby_executable_hooks:15:in `eval'
~/.rvm/gems/ruby-2.1.0@gemset/bin/ruby_executable_hooks:15:in `<main>'
Also, looking at the mocks that were successfully generated, I think this behavior is not ideal. Take these two models:
class ApplicationModel < ActiveRecord::Base
def to_s
name
end
end
class UserModel < ActiveRecord::Base; end
ActiveMocker will create a mock for each of these classes, but the UserModel
mock does not know anything about ApplicationModel#to_s
, so the mock is incomplete. This is a contrived example, of course, but the whole point of an ApplicationModel
is to share core functionality throughout all the models—functionality which is missing from all of the mocks.
Here's a scheme I think might alleviate all of these inheritance problems and provide higher-fidelity mocks. Consider these models:
# base model
class ApplicationModel < ActiveRecord::Base; end
# single-table inheritance models
class User < ApplicationModel; end
class Admin < User; end
class Moderator < User; end
# pseudo-models
class UserRegistration; end
class AdminRegistration < UserRegistration; end
The generator will consider the models in this order, because of their filenames: Admin
, AdminRegistration
, ApplicationModel
, Moderator
, User
, UserRegistration
.
- First, process
Admin
and see that it inherits fromUser
, so we should first make the mock ofUser
. In order to make the mock ofUser
, we must first make the mock ofApplicationModel
. So the first mock generated will actually beApplicationModelMock < ActiveMocker::Mock::Base
. ThenUserMock
will be generated, but its parent should be set toApplicationModelMock
so that it behaves just like the normal model would, inheriting fromApplicationModel
. Finally, generate theAdmin
mock and set its parent toUserMock
. - Next, process
AdminRegistration
. To do so, first processUserRegistration
. Since that class doesn't inherit from anything, we can stop processing it and stop processingAdminRegistration
. I don't think anybody would expect a mock to be generated for a pseudo-model. - Next, process
ApplicationModel
. It's already been processed and mocked, so move on. - Next, process
Moderator
. It inherits fromUser
, which has already been processed/mocked, so just generate the mock and set its parent toUserMock
. - Next, process
User
. It's already been processed mocked, so move on. - Next, process
UserRegistration
. It's already been processed and ignored, so stop.
At the end you would have the following mocks:
class AdminMock < UserMock; end
class ApplicationModelMock < ActiveMocker::Mock::Base; end
class ModeratorMock < UserMock; end
class UserMock < ApplicationModelMock; end
This would preserve the object hierarchy and create better mocks that have all the mocked methods of their parents. I'm not sure how difficult this would be to implement with the current code base, but I think it would be an awesome improvement!
from active_mocker.
Thank you for your detail and examples it's very helpful.
To address the pseudo-models
I can't see the use case for creating mocks out of those classes. It looks like those type of model could be used in units tests. Maybe there is something I am not considering, at a minimum it should pass over the models and ignore them.
I agree with your last example in preserving the object hierarchy. I think this is a much better design and would like to go forward with it. This will take some reworking of things, but I don't see any technical barriers l like I had with the last change (having to use ruby parse and unparse to modify the source code before eval). Where I am employed I would like to refactor some of our models to use STI, so I will have some real use cases to work from.
from active_mocker.
Also when setting model_base_classes
the default setting have not been loaded yet, so it breaks. You can try adding require 'active_mocker/railtie'
to the top of config/initializers/active_mocker.rb
but it will it need some refining.
from active_mocker.
I'm also running into the /app/models/.rb issue, though I'm not completely sure what model it's hitting it on. I could see not wanting to generate them for non-ActiveRecord classes, but it should probably gracefully skip them.
from active_mocker.
Test out the latest commit 0ba96c7. All feature should be working let me know if not.
Use gem 'active_mocker', github: 'zeisler/active_mocker'
from active_mocker.
Released 1.7.beta1
gem 'active_mocker', '~>1.7.beta1'
from active_mocker.
Fixed with release of 1.7
from active_mocker.
Related Issues (20)
- Correctly Support many through
- Minitest support? HOT 1
- missing forwardable dependency HOT 2
- Getting "ActiveMocker.safe_methods is unable to find methods: __missing_class_macros__" error for ruby 2.5.5 HOT 4
- Support polymorphic associations HOT 3
- Ignore modules
- Superclass mismatch
- Some mechanism for ignoring DSL code in classes HOT 1
- Be more optimistic with rake dependency (rake 11) HOT 3
- Can't generate mocks for rails Concerns HOT 14
- Error message "To see more/less detail set error_verbosity = 0, 1, 2, 3" very unclear. How do you set error_verbosity with rake? HOT 4
- Database type 'jsonb' is not a registered type. To register use ActiveRecordSchemaScrapper::Attributes.register_type(name: :jsonb, klass: <RubyClass>) HOT 5
- Support first_or_create on collection HOT 1
- undefined method `colorize' for "superclass must be a Class (Module given)":String HOT 5
- Copy across attr_accessors and cattr_accessors HOT 8
- Constant values assigned to non sudo primitives objects
- Missing schema information on a non abstract model does not fail.
- Less warnings when generating for mixed model and non model files. HOT 1
- Using a default value for decimal data types results in a failing mock class generated in 2.2.3 and a mock class syntax error in version 2.0.0 HOT 5
- Calling update on a record should call save as well. HOT 1
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from active_mocker.