How does rails handle model names with unusual pluralization - ruby-on-rails

I want to create a model called Match. Will the table for Match be matches or matchs i.e pluralizing with 'es' instead of the normal 's'? If I have another table, Player, belonging to Match, should the reference be match_id? If rails understands how to plularize Match, what other unusual pluralizations does it accept e.g. a model called Misery which would have a normal pluralized form of miseries?

Based on meagar's comment, most english pluralizations are done correctly in rails. If in doubt, you can just open a rails console and type 'model_name".pluralize e.g.
'match'.pluralize
which returns 'matches'. If this doesn't work, then you can roll your own according to this SO answer.

Related

Preventing Mongoid 4.0.0 model field coercion of id => _id

I'm using Mongoid 4.0.0 with Rails 4. My models map tables in another application, and I have no control over the field names.
One of the models has a field named id, which is getting coerced into Mongo's _id field. For example, when I insert a document with an id value of "something" I get
{_id:"something", id:null}
instead of
{_id:ObjectId("<hexstring>"),id:"something"}
Is there any way to avoid this coercion, make Mongoid not conflate the two fields, and leave my id field alone?
As I said, renaming the id field is not an option.
Thanks!
[edited]
This is definitely not a MongoDB issue. It must be in Moped or (my guess) Mongoid.
I've tried changing the params key from :id to :_rid but this is still happening. I'm going to check out aliases, but from my first pass I don't think they're going to help -- they appear to go the wrong way.
This appears to be hardcoded into Moingoid and a pervasive assumption throughout. It's annoying enough, though, that I might come up with a patch to allow users to override the key field on a per-model basis.
Oh well.

Steps to simply Change the Name of my Model

So I think I jacked up my naming conventions (or rather realized I want to do it a different way). I initially created a "Persons" model (which created person.rb). I also created a persons_controller, but apparently rails looks for "People" so I changed the controller name to people_controller.rb (in the files...not in the command line).
I'm new to rails so I really just need to scrap all this and change my names because this setup (having to using Person, Persons, People) throughout the model/controller/views is just a bit confusing for a beginner. All I want to do is change the "Persons" or "People" to the word "Players". So if I were starting from scratch I'd do "rails generate model Player" in the command line, and "rails generate controller Players". But I have no idea how to go about changing my existing controller and model names to this...and I couldn't fully understand some of the older questions related to this topic.
Any help would be greatly appreciated here. Step by Step instruction like your talking to a 12 year old is also highly encouraged given my novice status.
thanks guys,
The basic conventions that will explain everything
About class name and file name
Class name must correspond to file path. In English, if you have a Thing model, it must be in models/thing.rb file ; if you have a ThingsController it must be in controllers/things_controller.rb
Class name with camel case (i.e SomeThing) must be declared in a file with underscore (i.e some_thing.rb). The file name is written in small letters and underscore is used to "separate" the words. Other example: ThisIsEasyToUnderstand will give this_is_easy_to_understand
About model name, table name and controller name
A model name is singular, a table name is plural and a controller is plural. For example a Thing model will have a things table, and will work with a ThingsController controller
Rails try at most to use correct English syntax, so a Person model will work with a people table and a PeopleController controller
You may have trouble when the model name is, in English, the same in its singular and plural form. Ex: aircraft, eyeglasses, scissors etc.. I won't details the solution to keep my answer clear, but know it can append and you can find solutions on those a bit everywhere on internet.
As an overview:
When you create a model, create a name in its singular form
When you create a controller create a name in its plural form
if you need to rename models or controller you already created you must rename in your code but also rename the file name
If you need to rename a model you will also need to rename its table, and you need a migration for that (search google for "rails migration rename table" )
Hope it help for your first steps in Rails
You can quickly scrap a model (and its associated files) by calling
rails destroy model [modelname]
Same with controllers, scaffolds, etc.
rails destroy scaffold [modelname]
rails destroy controller [controllername]
Of course, there's no undoing this after you've deleted them, so I'd create the new controllers/models/scaffolds first, migrate any relevant code, and then destroy the useless files.

Get all has many from an activerecord hash

I have a model Campain which has many Media.
I do this:
Campain.all.medias
But get this error:
undefined method `medias' for #<Array:0x00000004bbaf40>
How can I get all medias from Campain.all?
The better approach is to use this code:
Campaign.includes(:media).map(&:media)
(Used English grammar, I hope you get the main idea). This will get all in two requests.
---EDIT---
If media - is has_many assosiation, indeed the return will be in form: [[...],[..]] so in that case use flaten to make it just simple array.
In the case when there needed all Mediums that are for all Camplaign use arrays group method to collect unique or just simple uniq. This approach to use Rails classes is preferable, as it is more general and configurable, for example it will apply any default scopes, that may be on Campaign.
Just to complete Dylans Post - I upgraded to Rails 3.1.1 today. My app has ~60 Models and one of these was called Media and it worked well eaven when it was bad english. So I upgraded and I think they patched the pluralizemethod. I wasnt able to call the medias actions and rails said the table 'media' doesnt exist which was the moment I realised my table was called media because I used rails 3.0.3 to create the model. I renamed the model, controller and views names, updated the routes from resources :medias to ressources :media as a quick fix and it worked again!
If you are looking for all Media that has an associated Campaign, you should query via the Media object, not the Campaign object. This will give you one array of Media objects, and only takes one query (assuming your Media object has a campaign_id [that is, Media :belongs_to :campaign]).
Media.where("campaign_id is not null").all
As far as Rails is concerned, the singular of Media is "medium" and the plural is "media", so just try media. However, all will still return an array, which you can't call media on anyway. So you probably want:
#campaigns = Campaign.all
#media = Medium.where(:campaign_id => #campaigns.collect(&:id))
or this (similar to another answer, but you need to flatten the results):
Campaign.includes(:media).map(&:media).flatten

Should rails action names contain underscores like: get_user or getUser or getuser?

How should I name a action if it contains 2 words:
word_other
wordOther
wordother
?
I assume you're talking about controller actions? In that case, they need to be underscored: get_user.
The convention is for variable and method names to be underscored: #new_instance.get_user. This ensures that controller methods map cleanly to actions. It also improves readability and helps distinguish method_names from ClassNames
In Ruby, method names have the convention that they should be separated by underscores, so Rails action names are no different.
It should be with underscore: word_other.
Rails action name is actually just a method name and Ruby's convention for method name is in lower case with words separated by underscore.
I was trying to find an official statement about this, but unfortunately I couldn't find it. But you can have a look at the methods available in Ruby Core to see how Ruby methods are named. There's also a write up on the naming convention for both Ruby and Rails.
With Rails, naming convention is even more important because one of the philosophy of Rails is convention over configuration. For example, if your controller class name is BookShopsController, you need to use book_shops to refer to it in your routes.
resources :book_shops
# or
match 'book_shops/:id' => 'book_shops#show'
If you don't follow along with the convention, you may find that things are more difficult to work with or it may not work as expected.
You should name it word_other.
In short:
methods and variables: all_lower_case_seperated_by_underscores
class- and module-names: CamelCased
constants: UPPERCASE
This article is very good summary of the ruby and rails naming conventions.
In general, ruby identifiers should use snake_case rather than camelCase. However, Rails action names should be selected from a much smaller list: show, index, new, create, edit, update, destroy. That is to say that following RESTful conventions will lead you to a simpler system that more accurately reflects the semantics of the web and allows you to more cleanly model your domain's resources and should be preferred to other action naming 'systems'.

Obfuscating ids in Rails app

I'm trying to obfuscate all the ids that leave the server, i.e., ids appearing in URLs and in the HTML output.
I've written a simple Base62 lib that has the methods encode and decode. Defining—or better—overwriting the id method of an ActiveRecord to return the encoded version of the id and adjusting the controller to load the resource with the decoded params[:id] gives me the desired result. The ids now are base62 encoded in the urls and the response displays the correct resource.
Now I started to notice that subresources defined through has_many relationships aren't loading. e.g. I have a record called User that has_many Posts. Now User.find(1).posts is empty although there are posts with user_id = 1. My explanation is that ActiveRecord must be comparing the user_id of Post with the method id of User—which I've overwritten—instead of comparing with self[:id]. So basically this renders my approach useless.
What I would like to have is something like defining obfuscates_id in the model and that the rest would be taken care of, i.e., doing all the encoding/decoding at the appropriate locations and preventing ids to be returned by the server.
Is there any gem available or does somebody have a hint how to accomplish this? I bet I'm not the first trying this.
What you are describing sounds like a specialized application of a URL slug. Take a look at plugins like acts_as_sluggable or friendly_id. Also look at overriding the to_param method on your User model.
Maybe start here: Best Permalinking for Rails

Resources