Tweet to tweets is no big deal.
And I assume Country would become countries without any fuss. I'd even credit them with Cactus becoming cacti (correct me if I'm wrong).
But what if I have class Barnabus? Do I call its table barnabuss, barnabi, or barnabusses?
What about zxzzy? How are non-english words handled?
Are there any non-messy options for overriding the decapitalization and pluralization?
I'm new to Rails and the modified table names have me a bit off-put.
Links to relevant documentation are appreciated. This is the only documentation I have seen relevant to this, and its not helpful for understanding odd exceptions for table names.
Forgive me if this is already covered, the results I got were not exactly what I'm trying to figure out.
String#pluralize uses a heuristic with the rather simple general rules for the English language as a base and adding some known common exceptions.
Using ActiveSupport::Inflector you can customize its behavior.
In Rails projects you can find the inflections config at config/initializers/inflections.rb.
If you'd like to create a Barnabus model with a corresponding barnabi table then all you have to do is uncomment some inflections.rb content and explicitly tell Rails how to treat this word.
ActiveSupport::Inflector.inflections do |inflect|
inflect.irregular 'barnabus', 'barnabi'
end
P.S. Thanks to Holger Just for the edit.
You can trust it for most of the cases but if you have some doubtful model name with awkward plural names, you can always specify the table name in Model. e.g.
class SomeName < ActiveRecord::Base
self.table_name = 'any_name'
end
If pluralization in views/error messages are your concern, in the situation that Rails fails magnificently with pluralizing a tricky table name you can add some localization to your app and tell it what you want it to use under various contexts. See http://guides.rubyonrails.org/i18n.html#translations-for-active-record-models
Here's an example of pluralization rules in action:
activerecord:
models:
barnabus:
zero: Barnabi
one: Barnabus
few: Barnabi
other: Barnabi
Related
We've got an app that deals with crops like tomatoes, beans, and squash.
One bean, many beans
One tomato, many tomatoes
One squash, many squash
Some of the crops have very weird plural forms, eg. you never pick "one garlic" you pick "one head of garlic". Some are almost never referred to in the singular, eg. "oats" -- you don't plant "one oat".
We use these words in sentences like, "Bob planted 3 tomatoes" or "Mary harvested 3 kg of oats".
So we want to use the Rails inflector to configure some special cases. However, we want to store the details of this in our database alongside other information about crops. Our users will be able to update the record to list the correct singular or plural forms.
We've read up on how to use the inflector but everything suggests configuring it in config/ somewhere, which means we'd have to restart the app for changes to take effect. How can we pick up new inflection information from the database as it changes?
We're using Rails 3.2 but would welcome Rails 4 answers if that's needed, as we're likely to be upgrading sometime soonish anyway.
You can use the 'inflections' singleton to define rules dynamically as you load crops from your database. Assuming you store singular form in an attribute singular and plural in attribute plural...
class Crop < ActiveRecord::Base
after_find do |crop|
ActiveSupport::Inflector.inflections.plural(crop.singular, crop.plural) if crop.singular
end
...
end
And of course you just then use the pluralize method as usual...
ActiveSupport::Inflector.inflections.plural("beatle", "mopheads")
p "beatle".pluralize
=> "mopheads"
Forgive my ignorance if I am missing something really trivial, I am very new to RoR.
Coming from Django background I remember models being like
class Post(models.Model):
title = models.CharField(max_length=100)
description = models.TextField()
both column name and field type are clearly specified.
Where as, when I write this rails command
> rails g model Post title:string description:text
all I get is
class Post < ActiveRecord::Base
attr_accessible :description, :title
end
Is there a way to write column names and field types while extending ActiveRecord::Base instead of having them only in the migration file?
Thanks, any help is appreciated
attr_accessible is deprecated and strong params replaces it functionality in the controller.
If you want to get a list of the schema information in your model file you can annotate it at the top of the file. This was best practices at some point, however I do not think it is used as much. I personally do not like this and just use the schema.
Post on best practices and annotating:
http://rails-bestpractices.com/posts/68-annotate-your-models
Gem to auto annotate:
https://github.com/ctran/annotate_models
The most wonderful thing about ActiveRecord is that you don't need to do any mapping, as all the fields are being automatically mapped using current schema. Of course default mapping can be overridden if needed, however this is a very rare case.
This approach is called "convention over configuration" and is present all over Rails - it assumes most common parameters for what you are trying to achieve so it saves a lot of unnecessary coding and mapping. It might feel weird at start, especially that you'll need to learn how to override those defaults, but I promise you are gonna love it when you get used to it. :)
I looked around and it seems that to set pluralization rules for model names you put the following in your locale file
# es.yml
es:
activerecord:
models:
business:
one: Lugar
other: Lugares
However, when the model name is translated in plural, I still get Lugars instead of Lugares
Not sure what's wrong
It should work with Business.model_name.human(:count => 2)
Your problem is that you are mixing up two forms of pluralization of strings in Rails. The first is meant for internal purposes: for naming classes, variables, methods, table names, etc. This is pluralize, and to make it properly handle exceptions etc. you can define inflections in config/initializers/inflections.rb.
But this type of pluralization is not appropriate for translations. For that, you should use Business.model_name.human(:count => 2) (as #doesterr suggested), which will reference the locale file for the locale you are in, which is what you want.
For details see this answer.
In rails application I have two models: Food and Drink.
Both food and drink have a name, which has to be stored in two languages.
How do I better realize translations for theese tables?
First solution I realized was to replace name column with name_en and name_ru.
Another solution is to encode with YAML hash like { :en => 'eng', :ru => 'rus' } and store yaml as a name.
What would you recommend, assuming content is not static?
Maybe there's good article?
The first option (name_en, name_ru) is the easiest to implement.
You could include a name method that returns the right value depending on the selected locale. You could even create a module, if you are going to use this on lots of models/fields:
class Food < ActiveRecord::Base
...
def name
self.send("name_#{I18n.locale}")
end
end
If in the future you must include an additional language, you will have to add a migration, of course. But that shoudn't be too troublesome.
The second one (encoding using YAML) seems a bit more cumbersome - you will not have to make an additional migration with it, but you loose other functionality. For example, search is made much more difficult - you can't use SQL any more for looking through descriptions, as they are coded on YAML instead of being plain text.
So I recommend having two fields.
I'm still new to ROR, so pardon the simplicity of the question...
So http://www.example.com/controller/:id displays a record in my table, with :id being a number (1,2,3 etc.).
Is there a way I can have :id in the URL be the value of a field in the displayed record? Such that I can have http://www.example.com/controller/record_field? I want to have a human-friendly reference to specific records in my table. I'm sure this must be possible. Do I change something in routes.rb?
Thanks for the help!
The cleanest way is to add a new find method in your model (or simply use the find_by_fieldname Rails gives you in your control). Then you'll have your controller use that method instead of the regular find(params[:id]) to pull your model record.
Check out Ryan B's screencast on this here. It's pretty easy, and he's a good teacher, so you shouldn't have any problems.
I use the excellent rails plugin named friendly_id.
http://github.com/norman/friendly_id/tree/master
That should sort you out nicely. It is well documented too.
Take care around fields that might have modern Greek characters—might need to figure a work around for those.
Jon Smock's solution will work, too. I tend to prefer the following.
class Hamburger << ActiveRecord::Base
#this normally defaults to id
def to_param
name
end
end
class SomeModelController << ApplicationController
def show
#hamburger = Hamburger.find(params[:id]) #still default code
end
end
#goes in some view
This is the <%= link_to "tastiest hamburger ever", url_for(#hamburger) %>.
This is, loosely speaking, an SEO technique (beautiful URLs are also user-friendly and I suggest them to absolutely everyone even if you don't care about SEO, for example on pages behind a login). I have a more extended discussion of Rails SEO, which includes other tips like this, here.
Important tip: You should consider, at design-time, what you are going to do if the param should change. For example, in my hamburger scenario, it is entirely possible that I might rename "Sinfully Delicious Cheeseburger" to "Triple Bypass". If that changes URLs, there are some possible implications, such as breakage of customer links to my website. Accordingly, for production use I usually give these models an immutable permalink attribute which I initialize to be human-meaningful exactly once. If the object later changes, oh well, the URL stays the same. (There are other solutions -- that is just the easiest one.)