Custom Validation Classes in Ruby on Rails - ruby-on-rails

I am trying to make a custom validation class in ruby on rails, however I cannot figure out how to make it modular.
I followed this example:
Validator Class Example
For the second example on that page titled: "Validate object single states with an isolated custom validator" how can I put the PreventFutureDateValidator class into a separate file? I cannot figure out where these files would be placed in Ruby on Rails.

These kindo of files are normally stored in /lib.

It's common to put validator classes in /app/validators/

Related

Default namespace of models in Rails

After upgrading my Rails app, I have run into a problem where the name of one of my models are conflicting with another class in Rails, namely Configuration.
Is there a way for me to (from a controller) explicit use my model class Configuration instead of ActiveSupport::Configurable::Configuration? What is the default namespace for my models?
You can use ::Configuration to call your class. It means that you're referring to the constant Configuration from the toplevel namespace. But I think it's annoying. You can rename your class to avoid this.

Override the default Rails model template

I want to override the default model file that's generated with rails generate model. I've created a template based on this file, but I can't figure out where to put it. Other answers seem to suggest /lib/templates/rails/model/model.rb or /lib/templates/rails/model/model_generator.rb, but neither of those do anything - I put the template in that location but when I run rails generate model ModelName it gets ignored.
Am I going about this the right way? Where should I put the template?
Solved: I wanted lib/templates/active_record/model/model.rb.
You probably need to put it in "lib/rails/generators/active_record/model/templates/model.rb". Here's the rails' default one: https://github.com/rails/rails/blob/master/activerecord/lib/rails/generators/active_record/model/templates/model.rb

Ruby - :: in class name

I'm working with some legacy RoR code, which has four related classes, each defined in its own file. All of these classes are parser classes, and live in app/models/parsers. Each file name ends with _parser.rb.
Here's an example class def line from file adf_parser.rb:
class Parsers::AdfParser
I'm lost as to what the Parsers:: part of that is doing.
There's no explicit module called Parsers defined anywhere that I can find.
I don't see any documentation about implicitly creating modules just by adding module specifications to class names.
The only external dependency is "require 'csv'".
There are include statements within the class def, but I don't think they have anything that would explain the class name.
I created a new RoR test project and put stubs of these files in a parallel directory, and they won't run from the command line due to a
name error.
I don't see any examples online of classes named in this way.
I'm sure this isn't rocket surgery, but I've lost most of my morning trying to figure this out, and I'd love it if someone could just tell me what's going on with it.
Update: It sounds like this is just a bit of Rails magic, based on the subdirectory name. I think the reason that I got an error in my test app is that I just ran the files through the ruby interpreter, rather than invoking them with Rails in some way.
class Parsers::AdfParser is in practice equivalent to:
module Parsers
class AdfParser
For this to work properly, and the file to be autoloaded its location should be parsers/adf_parser.rb, whether under app/models or lib. Basically the file path needs to mimic the class hierarchy.
It's in the parsers sub-directory of modules; Rails namespaces for you by convention.

How do you extend collection(?) to include second, third, etc. functions in Rails?

Pretty self explanatory.
I use array_name.first to get the first element. How do you extend it to get second, third, random, etc?
Thanks.
In Ruby you can just reopen any existing class and add your own functions.
In rails, you already have those methods defined in activesupport
See the source at github: https://github.com/rails/rails/blob/master/activesupport/lib/active_support/core_ext/array/access.rb
I discovered it is already there, in Ruby 1.9.2 at least.
If it weren't there, I would create a file in config/initializers called array_helper.rb (or whatever) and add the following code:
class Array
def second
self[1]
end
end
Why? Because all classes in Ruby are open and you can extend anything you want.
Here's some tricks to know:
When working in the console, if you want to test the file, be sure to use rails console and not irb. Also, do reload! after creating or updating the above file. Finally, all objects must be recreated to use the new code after reload!.

How do I add a method to a ruby gem without editing the gem source?

I am using the acts_as_taggable_on gem and would like to add a method to one of the gem source files (tag.rb), but I do not want to change the gem source in any way.
I have tried creating my own tag.rb file to in the /app/models directory or in the /lib directory, and then adding the desired method to that file expecting that ruby will merge the two tag.rb files
But when I do I get a NoMethodError: undefined method ...
What am I missing?
I think you're right that reopening the Tag class is the way to go. I wouldn't introduce another level of inheritance unless it really made sense for your code.
I'm not sure, off the top of my head, why reopening the Tag class didn't work. A few thoughts:
1 - When you wrote your own Tag class, did it descend from ActiveRecord::Base? The Tag class in acts as taggable on does, and I could see how neglecting that might mess things up.
2 - If I needed a place to put code that reopened a plugin class for a single method, I'd probably put it in an initializer file (such as config/initializers/tag_patch.rb). Just to keep things clean.
3 - If all else fails and you still can't get the Tag class reopened properly (for whatever reason) there are other metaprogramming techniques you might try to add the method. For example:
Tag.send(:define_method, “method_name”) do
#code for your method
end
Wait, you shouldn't be adding method to the file, but to the class instead. Are you familiar with the concept of reopening the class? You can't add a method just by naming your file same as the one which original class is defined in. Fortunately. :)

Resources