I'm writing a rails application, and I need to name one of my model Test, and inside that model I need a class attribute - when I tried the first one, I couldn't run any UT since Test ceased to be a module - so I ranamed to Tst. I haven't even tried naming a column class - I went with clss. What names would you use? Are there any conventions known amongs RoR developers for such situations?
I haven't seen anything for Test but class is typically changed to klass.
Ruby and Rails have several different objects part of a standard library. You cannot use an already-defined class name as name for your models.
For instance, you cannot call a model Thread or Object because Ruby already defines a Thread and Object class.
Likewise, Ruby has a library called Test::Unit so you can't use the Test namespace as model name.
There isn't a real full list of reserve objects because it really depends on your current environment. However, in order to successfully use Rails, you should at least have a basic Ruby knowledge so that you know the names of the most common standard library classes.
I've run up against this a few times (writing educational software--where you regularly want to model 'tests' :-). Depends exactly what you're modeling I suppose, but I usually opt for 'quiz' to avoid conflicts. I'd love to hear a better solution, since I find 'quizzes' an awkward plural.
Like dj2 said, class is usually done as 'klass'.
Please check the following page for Rails reserved words: http://reservedwords.herokuapp.com/ None of these words should be used as class or attribute name.
Related
I am trying to build a rack based web framework on my own, and I got confused when I refer to the design of Ruby on Rails.
Why should a model in Rails be named like User instead of UserModel, just like controllers or helpers do (for example, UsersController, PostsHelper)?
If the naming convention of model is good, why don't controllers or helpers follow the same rule? The Controller and Helper postfix is bit tedious.
Is it good to namespace everything? For example: Controller::User, Model::User.
Are there any good references/books that talk about the file structure of software?
I think that it's for convenience sake. You would never usually reference the controller and helper classes in your code, whereas you reference the model classes all the time. If they were called UserModel you would have lots of code like
user = UserModel.first
post = PostModel.first
there's two problems with this: it breaks the convention of "call the instance variable name after the class", which is a simple bit of self-documentation, and also it's cumbersome, with a lot of repeated information.
Also, the User class does actually represent a real life user, whereas the UserController class doesn't represent anything in the real world, it's just part of the machinery, if you know what i mean.
EDIT - some more answers:
3) Namespacing should be reserved for separate sections of your site, like an admin section for example: you can have an AdminController which inherits from ApplicationController, and adds a few more bits (such as a before_filter for checking that there's a current user and that they're an admin), and then your other admin section controllers inherit from AdminController. Namespacing in the routes allows easy management of this.
4) As for books, read this: http://www.amazon.co.uk/Agile-Development-Rails-Pragmatic-Programmers/dp/1937785564/ref=sr_1_1?s=books&ie=UTF8&qid=1450792683&sr=1-1&keywords=hansson+rails
It has some "Make a blog in 15 minutes" type stuff which i would actually recommend NOT diving into until you understand the underlying architecture, which is well explained elsewhere in the book. Too many people dive into Rails without understanding what they are doing (their hapless questions fill this forum).
All about convention, had to decide something. I don't speak for the rails core but this is my thoughts.
Model - In most cases, this is a representation of a single instance of a something. Although you could have cases where that is not the case, it helps me to conceptualize the singularity of it. I.e. I am dealing with a User not a Users
Controller/Helpers/Tablenames - In the database a User model maps to users table. The controller and helpers follow the same convention of the database.
Namespacing is good, but you should only namespace something when it makes sense on a clear boundary.
A great ruby framework to look at that is not rails is Lotus - http://lotusrb.org/ It uses namespaces heavily.
I'm using Rails 3.1 on a project, and bundler has added quite a few gems that I do not really know the contents of that well.
For some reason in development mode (probably because it keeps unloading classes), I intermittently run into an ActiveRecord::AssociationTypeMismatch. That look like this:
Character(#31360520) expected, got Character(#23815500)
I believe that one of the gems has defined a class "Character" and it's conflicting with my ActiveRecord "Character" model. I'm having trouble searching down the source of this problem as it comes up with a bunch of generic results, and I'm not sure what those numbers are called by the Ruby community (class id?).
So a few questions that I'd love help with:
what is that number in the parens after the class name?
How can I look up where that class is from (in which gem) based on the id reported in the exception?
What is the best practice here for commonly named ActiveRecord models? Should I be namespacing my models, or is the blame more with the author of the gem?
i'm sort of a noob, so don't consider all i say as an established truth - but i think i might help.
question 1
Not sure, but i suspect those numbers are object_ids of the expected Class. In ruby, classes are objects too (singleton objects, though), so they have an object_id as would any other object (you can call object_id on any object to get its unique id). If you want to get an Hash of every classes loaded in your environment along with their id, you can try something like this in the console :
all_classes = ObjectSpace.each_object.select {|o| o.class == Class}
with_ids = Hash[ all_classes.map {|c| [c,c.object_id] } ]
question 2
In the console, all classes are displayed showing their full namespace path, so you should be able with the above script to distinguish your two Character classes if they belong to a different namespace.
If the namespace is identical though, the problem may become hairy because one of your class definition will override the other, depending on the load order. I would not be surprised if using ri in your shell would help you to find the culprit gem in this case.
question 3
I would say : avoid vague, too common names for your models ; but in this case, i'd say the gem is to blame, because someone providing a gem should be really careful not to pollute the namespace, especially if it pollutes the ActiveRecord::Base namespace.
I have a Rails app with a few model classes (e.g. Category, Subcategory, User, etc.). In order to implement a not-too-trivial filter functionality, I built a hierarchy of filter classes: FilterCategory, FilterSubcategory, etc., that derive from FilterBase. Each of them uses the appropriate "sister" model class (e.g. Category.find :all).
I quickly realized that I can't simply call the "sister" model class without using "require" first. However, I now suspect that using "require" is the main reason for two other problems I posted here and here, which probably mess up the class caching when config.cache_classes=false.
Is there another way for me to call these other models without requiring them?
I tried using the BaseWithoutTable plugin, but when I call the "sister model", I end up getting "Not a valid constant descriptor: nil", which occurs since Rails looks for "FilterCategory::Category" rather than "Category".
Any thoughts of the best way to do that?
I'm using Rails 2.3.8, Ruby 1.8.7.
Thanks,
Amit
I wonder if you want ::Category - getting Category from the top-level namespace rather than scoping it to FilterCategory?
If your models are in the app/models directory, you shouldn't need to explicitly require them - Rails already takes care of that.
I'm really enjoying Rails (even though I'm generally RESTless), and I enjoy Ruby being very OO. Still, the tendency to make huge ActiveRecord subclasses and huge controllers is quite natural (even if you do use a controller per resource). If you were to create deeper object worlds, where would you put the classes (and modules, I suppose)? I'm asking about views (in the Helpers themselves?), controllers and models.
Lib is okay, and I've found some solutions to get it to reload in a dev environment, but I'd like to know if there's a better way to do this stuff. I'm really just concerned about classes growing too large. Also, what about Engines and how do they fit in?
Because Rails provides structure in terms of MVC, it's natural to end up using only the model, view, and controller containers that are provided for you. The typical idiom for beginners (and even some intermediate programmers) is to cram all logic in the app into the model (database class), controller, or view.
At some point, someone points out the "fat-model, skinny-controller" paradigm, and intermediate developers hastily excise everything from their controllers and throw it into the model, which starts to become a new trash can for application logic.
Skinny controllers are, in fact, a good idea, but the corollary--putting everything in the model, isn't really the best plan.
In Ruby, you have a couple of good options for making things more modular. A fairly popular answer is to just use modules (usually stashed in lib) that hold groups of methods, and then include the modules into the appropriate classes. This helps in cases where you have categories of functionality that you wish to reuse in multiple classes, but where the functionality is still notionally attached to the classes.
Remember, when you include a module into a class, the methods become instance methods of the class, so you still end up with a class containing a ton of methods, they're just organized nicely into multiple files.
This solution can work well in some cases--in other cases, you're going to want to think about using classes in your code that are not models, views or controllers.
A good way to think about it is the "single responsibility principle," which says that a class should be responsible for a single (or small number) of things. Your models are responsible for persisting data from your application to the database. Your controllers are responsible for receiving a request and returning a viable response.
If you have concepts that don't fit neatly into those boxes (persistence, request/response management), you probably want to think about how you would model the idea in question. You can store non-model classes in app/classes, or anywhere else, and add that directory to your load path by doing:
config.load_paths << File.join(Rails.root, "app", "classes")
If you're using passenger or JRuby, you probably also want to add your path to the eager load paths:
config.eager_load_paths << File.join(Rails.root, "app", "classes")
The bottom-line is that once you get to a point in Rails where you find yourself asking this question, it's time to beef up your Ruby chops and start modeling classes that aren't just the MVC classes that Rails gives you by default.
Update: This answer applies to Rails 2.x and higher.
Update: The use of Concerns have been confirmed as the new default in Rails 4.
It really depends on the nature of the module itself.
I usually place controller/model extensions in a /concerns folder within app.
# concerns/authentication.rb
module Authentication
...
end
# controllers/application_controller.rb
class ApplicationController
include Authentication
end
# concerns/configurable.rb
module Configurable
...
end
class Model
include Indexable
end
# controllers/foo_controller.rb
class FooController < ApplicationController
include Indexable
end
# controllers/bar_controller.rb
class BarController < ApplicationController
include Indexable
end
/lib is my preferred choice for general purpose libraries. I always have a project namespace in lib where I put all application-specific libraries.
/lib/myapp.rb
module MyApp
VERSION = ...
end
/lib/myapp/CacheKey.rb
/lib/myapp/somecustomlib.rb
Ruby/Rails core extensions usually take place in config initializers so that libraries are only loaded once on Rails boostrap.
/config/initializer/config.rb
/config/initializer/core_ext/string.rb
/config/initializer/core_ext/array.rb
For reusable code fragments, I often create (micro)plugins so that I can reuse them in other projects.
Helper files usually holds helper methods and sometimes classes when the object is intended to be used by helpers (for instance Form Builders).
This is a really general overview. Please provide more details about specific examples if you want to get more customized suggestions. :)
... the tendency to make huge
ActiveRecord subclasses and huge
controllers is quite natural ...
"huge" is a worrisome word... ;-)
How are your controllers becoming huge? That's something you should look at: ideally, controllers should be thin. Picking a rule-of-thumb out of thin air, I'd suggest that if you regularly have more than, say, 5 or 6 lines of code per controller method (action), then your controllers are probably too fat. Is there duplication that could move into a helper function or a filter? Is there business logic that could be pushed down into the models?
How do your models get to be huge? Should you be looking at ways to reduce the number of responsibilities in each class? Are there any common behaviours you can extract into mixins? Or areas of functionality you can delegate to helper classes?
EDIT: Trying to expand a bit, hopefully not distorting anything too badly...
Helpers: live in app/helpers and are mostly used to make views simpler. They're either controller-specific (also available to all views for that controller) or generally available (module ApplicationHelper in application_helper.rb).
Filters: Say you have the same line of code in several actions (quite often, retrieval of an object using params[:id] or similar). That duplication can be abstracted first to a separate method and then out of the actions entirely by declaring a filter in the class definition, such as before_filter :get_object. See Section 6 in the ActionController Rails Guide Let declarative programming be your friend.
Refactoring models is a bit more of a religious thing. Disciples of Uncle Bob will suggest, for example, that you follow the Five Commandments of SOLID. Joel & Jeff may recommend a more, er, "pragmatic" approach, although they did appear to be a little more reconciled subsequently. Finding one or more methods within a class that operate on a clearly-defined subset of its attributes is one way to try identifying classes that might be refactored out of your ActiveRecord-derived model.
Rails models don't have to be subclasses of ActiveRecord::Base, by the way. Or to put it another way, a model doesn't have to be an analogue of a table, or even related to anything stored at all. Even better, as long as you name your file in app/models according to Rails' conventions (call #underscore on the class name to find out what Rails will look for), Rails will find it without any requires being necessary.
Here's an excellent blog post about refactoring the fat models that seem to arise from the "thin controller" philosphy:
http://blog.codeclimate.com/blog/2012/10/17/7-ways-to-decompose-fat-activerecord-models/
Basic message is "Don’t Extract Mixins from Fat Models", use service classes instead, the author provides 7 patterns to do so
I have a rails app moving along fairly well, but the fact that I'm doing this myself means that some poor sod is eventually going to see this and say, "What the hell were you thinking? Why did you put this here?!?!"
Where is that poor, sorry soul going to expect to see a series of classes that aren't used by anything but a single model class? Obviously, I could chuck it in the_model.rb along with class TheModel, but this may expand beyond the planned two classes...
I thought about lib, but it doesn't need to clutter everyone's view of the world....
Thank you.
My predecessor thanks you.
Leave them in the_model.rb until you need them in more than one place. If you refactor needlessly, you're not doing the simplest thing that could possibly work. You aren't gonna need it.
At that point, the general pattern is to create a directory for "concerns". See this weblog post by Jamis Buck or this one by Peter Marklund for more information.
In general: follow the Rails naming conventions when translating class names into filesystem locations. (that is: keep the class FooHelper::Bar in foo_helper/bar.rb)
You can make exceptions for small helper classes that are only used once and keep them in the same file as your model, but those should be exceptions. (but the converse is also true, don't create one-line thousands of single line files)
Use modules and class namespaces to your advantage. If you have a helper class that is only used by (and dependent on) your model, put them into the namespace of the model class:
class TheModel::HelperClass
end
the location in the file system would be app/models/the_model/helper_class.rb
And something that is not dependent on your model can probably still be namespaced
module Bar
class Foo
end
end
living in bar/foo.rb, of course
You should probably not be afraid to put things that are not models into lib -- that's what this directory is for
I'd say concerns, while useful, are not really the right way to go because that is a way to split a single class into multiple files and you don't seem to be doing that.