Ruby is already using the class name of my model - ruby-on-rails

I'm making a forum application with various levels of authorization, one of which is a Monitor. I am doing this by extending my User class, and I plan on fine tuning this with "-ship" classes (e.g. administratorship, authorship, moderatorship, etc.). Apparently the Monitor class is part of ruby mixin. How do I keep my resource name without the collisions?

Some possibilities:
avoid the require 'monitor.rb' call which is pulling in the standard Monitor instance
do some runtime magic to rename the existing Monitor class.
monkey with your load path so that require 'monitor.rb' pulls in an empty implementation of Monitor.
But in all cases you could end up with the situation where a 3rd party library is using Monitor expecting it to be the standard Monitor class. So, I'd advise against any of the above.
I'd say your only two reasonable options are:
A) you could put your class in a namespace:
Module MyApp
class Monitor
#...
end
end
if your app uses some kind of auto-require magic (e.g it's a rails app) then you would put your implementation in /my_app/monitor.rb. When you wanted to refer to that class you would do something like my_monitor = MyApp::Monitor.new(), or whatever.
B) you could use a different class name :)

Declare your Monitor class in other module.
module MyModule
class Monitor
end
end

FYI, I just found a neat trick (errr, hack) to get around this which may work.
I work on a large legacy application which, unfortunately, has a "Fixture" model which is quite important and which is used everywhere. When running tests, it's impossible to create a Fixture instance because of the Fixture class used by ActiveRecord when running tests. So I did the following:
FixtureModel = Fixture.dup
This freezes my class in place so that I can refer to it later (but just in my tests!) without being extended by the ActiveRecord Fixture class (which is not namespaced)

Related

Where to properly outsource model code in rails 4?

In a model of mine I'm using the bing translator gem for automatic translation of a model attribute via a after_create callback:
class Place < ActiveRecord::Base
after_create :auto_translate
....
# AUTO_TRANSLATE STUFF
def initialize_bing_translator(bing_id, bing_secret)
t = BingTranslator.new(bing_id, bing_secret)
<do other stuff>
end
def auto_translate
<do stuff>
end
<further auto_translate methods>
The whole bunch of functions seems to bloat the model code a little so I want to put it into some extra module. Where exactly shall I place the .rb-file? Is this a use-case for a concern (a concept I did not fully understood)? Is it better to define a seperate module in the model file itself or to place it in /lib/user_modules/? Is there sth like a rule-of-thumb? The information available on the web are confusing me a little and I'd be glad if someone could shed some light on that issue for me!
I started putting stuff like that in subfolders of models and namespacing things accordingly. In your specific case I'd put it in something like models/place/translator.rb (or similar) and call the class Place::Translator.
If you just want a sort of logical separation but will not use the same functionality elsewhere you can use concerning instead of a separate concern.
There are many options and most of them are primarily opinion-based. It depends on if you plan to reuse that class, how complex your application already is and if the new class has any external dependency.
I would think about: create your own gem, add to app/models, add a new app/translators directory, perhaps in lib...

Restructure bulky class

I have an ActiveRecord model Reservation.
It got to the point that the class is to large and does too much.
I would like to split it into a few different ones and place those under the Reservation module.
Unfortunately this will break the app.
At this moment I see following options:
namespace it to something like ReservationConcerns or similar
add the functionality to the Reservation class itself, but physically move it to the subdir (Reservation would be in app/models/reservation.rb, Reservation::Pipeline would be in app/models/reservation/pipeline.rb etc).
So the question is how to structure the different concerns of a feature already having it as one single, bulky class without breaking the app.
If you want to split up a Ruby class into different components without changing its public interface, one solution is to use modules:
# app/models/reservation.rb
class Reservation < ActiveRecord::Base
# associations, validations, etc.
include Pipeline
end
# app/models/reservation/pipeline.rb
module Reservation::Pipeline
def some_pipeline_method
# ...
end
def other_pipeline_method
# ...
end
end
ActiveRecord also provides observers, which "is a great way to reduce the clutter that normally comes when the model class is burdened with functionality that doesn't pertain to the core responsibility of the class". Observers often make heavy use of the ActiveModel::Dirty methods.
These suggestions are complimentary: modules can help you group your interface into more local chunks, while observers can make backend details more self-contained. From here, it's difficult to be more specific without knowing exactly what pieces you have that you're trying to break out.

Ruby module as both namespace and mixin

In the Rails application I’m currently developing I have many “request” models. We are using a lot of web services and we have a lot of different requests to those services, each of them with their own logic (mostly validations). So they are all grouped in a module as a namespace:
module Request
end
So now every request is something like:
class Request::SendSomeData
end
So far, so good… The thing is that we are going to have a lot of such requests which will share some common logic. It is easy to include the module
class Request::SendSomeData
include Request
end
… (so it will act both as a namespace and a mixin), but I was wondering if there is a way to make it without the include (as it is going to be some kind of code repetition).
Is there a way for Ruby to put some instance methods to all the classes in a module’s namespace without explicitly including the module?
In other words can I have something like:
module Request
def someMethod
end
end
and
class Request::SendSomeData
end
and be able to use
Request::SendSomeData.new.someMethod
at the same time?
What you are asking can't be done without some evil hackery.
You either have too many classes, or are focusing on an issue that is too unimportant. It's only one line of code per class.
An alternative is to create a base model class, as I have previously described in another question, but this requires the derived classes to each call set_table_name, so it won't save you any typing.

Are modules in ruby only meant to be used when multiple objects require its functionality?

I've read that the main service provided by a module is to contain and group similar functions that are needed by several objects. But is it a good practice to create a module for something like a parser even if you are certain that only one object will ever require its services?
Modules serve two purposes. The first as you have noted is to allow functionality to be added to a diverse set of classes (diverse meaning outside the inheritance tree). The second an by far more common use is to organize the names space. When you see code like ActiveRecord::Base or BSON::ObjectID the authors of these gems have placed their functionality in a module, ActiveRecord and BSON respectively, that prevents their class names from conflicting with the applications they are included in or other libraries.
With the parser you mentioned, it sounds to me like you want to construct a singleton class rather then a module.
It can help for organization to create a module even if you are using it in one place. For example you might have a lot of methods that are all related, but not really related to the code you are including the module in. This is similar to the the organization that a class provides, except that a module isn't focused on an object.
main service provided by a module is
to contain and group similar functions
that are needed by several objects
I would re-word it to "group similar functions that might be needed by at least one object". It's very frequent that you don't know how many classes will end up including or extending a module (for example if you are writing a library)
Independently of that, I see two more "main purposes":
They are a way to provide scopes (you can package several classes and other modules inside one module).
They have a callback called included. This might seem trivial, but that callback is key in a lot of interesting meta-programming techniques.
I would go for a class (if you got not too much code). Place it under /lib
class Parse
def self.xml(xml_string)
...
end
end
Parse.xml("<xml></xml>")
You can call it from anywhere.
http://en.wikipedia.org/wiki/Separation_of_concerns
Modules are indeed a group of similar functions. If you got a lot of parsing code you could do:
class Xml
acts_as_parser
end
class Json
acts_as_parser
end
...
acts_as_parser will load the group of functions from the module.
But is it a good practice to create a module for something like a parser even if you are certain that only one object will ever require its services?
Yes.
In Ruby, modules help a whole lot with separation of concerns and are very good for doing "aspect-oriented" programming (i.e., fun with mixins).
# Basic Hierarchy
class X
def say ; 'X' end
end
class Y < X
def say ; super + 'Y' end
end
y = Y.new
y.say #=> 'XY'
# Throwing in an aspects/mixins
module A
def say ; super + 'A' end
end
class Y
include A
end
y.say #=> 'XAY'
# Throwing in another aspects/mixins
module B
def say ; super + 'B' end
end
class Y
include B
end
y.say #=> 'XABY'
When faced with an excessively large class, sometimes I split it up into a couple of modules based on its functionality, and have a virtually empty class just include those modules.

Ruby/Rails: Reopening vs Overwriting a Class

I want to add a method to a Rails model, to be used in testing. If I do this
class Model
def something_new
do_something
end
end
in the Rails console or in a file loaded at run time, Model is overwritten rather than modified. If I put something like v = Model.classbefore the lines above, the new method is successfully added to the existing class. Apparently the reference is needed to signal that an existing class is being re-opened.
On the other hand, one can add a method to, say, Fixnum without having to refer to it first. What is going on here, and what is the usual way to ensure that an existing class is re-opened and modified rather than being overwritten?
Thanks.
It sounds like you're not requiring the class before using it. When you write Model.class and there is no Model class, Rails automagically brings in Model for you. If you just write class Model, it just sees that as a class definition. Just doing require 'model' should work.
Use class_eval, that way you will be reopening the class the right way.
Here's a very good article on reopening classes.
Just as an addition to Chuck's answer here is the quote from Rails docs:
6.1.1 Constants after the class and module Keywords
Ruby performs a lookup for the constant that follows a class or module keyword because it needs to know if the class or module is going to be created or reopened.
If the constant is not defined at that point it is not considered to be a missing constant, autoloading is not triggered.

Resources