I am looking to understand what is going on with the following
I have a message model
class Message
include ActiveModel::Validations
include ActiveModel::Conversion
extend ActiveModel::Naming
I would like to use validates_uniqueness_of :email through the gem client_side_validations, however the gem seems to rely on using
< ActiveRecord::Base
so my model should look like so
class Message < ActiveRecord::Base
include ActiveModel::Validations
include ActiveModel::Conversion
extend ActiveModel::Naming
however if I include the inheritance I get an error message along the lines of
undefined method []
Something is not right and i was wondering if anyone could explain why this is happening
Thanks
Not sure if it is related to the error, but you should not be including/extending all those ActiveModel modules if you are inheriting from ActiveRecord::Base, since they will be included through inheritance. I would first try taking those out and see if that works.
Related
I have this tiny bit of code, used in a few model classes in an application:
validates_format_of :month, :with => /\d{4}\/(0[1-9]|1[0-2])/i, :message => "must be in the format YYYY/MM"
What's the rails way to DRY this up? i.e., where should the code go and how should it be called?
take a look at Active Model Validator
You can use observer in rails
to DRY up your code.
[This is a follow-up question to "How I can modularize Rails model?"]
Is there anyway to organize classes in app/models directory of Rails?
Do I have to use single top-level namespace for all of the classes?
Initial motivation is, I want place business logic classes which do not inherited from ActiveRecord::Base into app/models directory. Searching this site reveals many answers which recommend to place business logics classes in the app/models directory. I posted a different question, and got recommendation that it is possible to place such classes into lib directory.
Now I'm curious. I'd like to place these classes into different namespace and directory in apps/models directory which recommended by others. Is it possible?
Actually, I experiment that, but it seems to me that is what rails is not expected. If I create such a class (like SomeModName::ClassInMod in some_mod_name/class_in_mod.rb ) it does not get loaded. Also, I defined constants inside the module. Since they're not loaded, I can't use them. Actually, with rspec it work without problem, but with rails server, the class does not loaded. I'm sure it is related to autoloading issue.
In addition to the classes mentioned above, classes inherited from ActiveRecord::Base can be placed into some namespaces inside a module. I'm curious whether this work well or not too.
So the question in other words: can I make rails happy by configuring these files to be loaded, or is not the way rails designed?
Yes, you can define an ActiveRecord class in a module. The easy way is to use the generator:
./script/rails generate model logic/phase_logic
./script/rails generate model logic/evaluation_logic
Observe, that Rails will create additionally a file with the definition of the module. In this case:
# app/models/logic.rb
module Logic
...
end
# app/models/logic/phase_logics.rb
class Logic::PhaseLogic < ActiveRecord::Base
...
end
# app/models/logic/evaluation_logics.rb
class Logic::EvaluationLogic < ActiveRecord::Base
...
end
Your problems with constants defined in the module were caused by the fact, that you defined the constants in the definition module "wrapped" around only one model, from the two you have created. A very important part in understanding ruby (and Rails) - especially for people who have strong background in compiled languages - is to remember that there is no compilation phase, so the definition of some class is read and executed only when that specific class is used. Sometimes a week after the application server has been started and served thousands of requests.
Thus, as I said in the previous question's answer, the problem with autoloading was that sometimes the definition of the constants was read after the definition which was trying to use them. The order was random - if the first used object happened to be EvaluationLogic, then the error emerged. It the first object happened to be PhaseLogic, everything was fine.
Now, when you have a file for the module itself, and define constants in that file (app/models/logic.rb), autoloading will be able to find and execute the definitions before any class starts to use them. I hope everything will be OK.
So, I am having some trouble running tests in Rails. When I ran 'Rake test' and I have something like this
http_basic_authenticate_with :name =>Hello.first.myhello, :password =>Hello.first.myhello
Inside my controller, I get an error
'method_missing': undefined method `myhello' for nil:NilClass (NoMethodError)
Clearly the fixtures aren't being loaded, is there anyway I can make them load and have this not fail? Using Rails 3.1.
** edit: possibly related SO question/answer? Basically, put this in your test unit class:
fixtures :hellos
If that doesn't do it, could you paste the relevant parts of your fixture and test class?
**original:
I'm not sure about your experience level or your setup, so just to confirm that you are testing what you think you are testing, could you add this line before the line in your question?
Hello.create(:name => some_value, :password => some_value)
In case there is any confusion,
undefined method `myhello' for nil:NilClass
indicates that you are not actually getting any records, not that you don't have the Hello model.
UPDATE
I wrongly checked the edgerails guide instead of the currently correct Rails 3 guide (which has no mention of after_initialize). Not sure why the edgerails guide is "incorrect" though - I thought edgerails guide was supposed to be the latest up-to-date guide?
I'm leaving this question as-is just in case someone comes looking for the same "problem".
Macro-style call to after_initialize is the way to go.
Should after_initialize be used as method or macro-style call ?
This works, but gives a deprecation warning:
def after_initialize
logger.info "Called after_initialize"
end
DEPRECATION WARNING: Base#after_initialize has been deprecated,
please use Base.after_initialize :method instead.
This works, and there is no warning:
after_initialize :do_this_after_initialize
def do_this_after_initialize
logger.info "Called after_initialize"
end
But the Active Record Validations and Callbacks Guide in 10.4 after_initialize and after_find says:
...If you try to register
after_initialize or after_find using
macro-style class methods, they will
just be ignored. This behaviour is
due to performance reasons, since
after_initialize and after_find will
both be called for each record found
in the database, significantly slowing
down the queries...
So that means that the macro-style usage is inefficient versus the method-style way?
(I guess the guide is wrong, 'cos code is king :D)
Another Update
A commit here from January 28, 2011, suggests that the correct way is still to use the macro-style call, not a def after_initialize.
The call backs should be used as macro style in your model: http://api.rubyonrails.org/classes/ActiveRecord/Callbacks.html
With the introduction of ActiveModel in Rails 3 whats the new method of calling ActiveRecord::RecordNotFound. ActiveModel::RecordNotFound ?
This is the definition (1) of ActiveModel:
ActiveModel is a class to be implemented by each ORM to allow Rails to generate customized controller code.
ActiveRecord implements ActiveModel. ActiveRecord raises its ActiveRecord::RecordNotFound exception when it can't find record by given id or a set of ids (2) in the database.
This mean there can't be such exception like ActiveModel::RecordNotFound.
ActiveModel is a set of modules and conventions to be implemented, the main goal being providing a common interface to mappers, no more, no less. So nope, ActiveRecord::RecordNotFound stays ActiveRecord::RecordNotFound. RecordNotFound does not make sense for every mapper : with Mongoid for instance, you'll have DocumentNotFound (well, Mongoid::Errors::DocumentNotFound).