Currently building a Rails 3 app and I've notice there are a lot of words and phrases that I use in many different views multiple times. Rather than hard-coding them in the views each time, I thought it might be a good idea to have the content stored in a CONSTANTS hash. Would it make sense to make a constants.rb file in config/initializers and then have a hash in it called CONSTANTS, then whenever I need to content for a view, I'd just call the CONSTANTS hash with a respective key? Is this a good way of going about it, or should I do something else?
Sounds like Rails locale files might be what you want. You would define your strings in config/locales/en.yml (for English) file. You define your strings in a yaml file, then use them via t (:my_string) in your views. It makes it easier to maintain, or to extend to another language.
Take a look at Rails i18n Guide, it explains things in detail.
Related
This is a question merely about code style.
I am working on a multilingual app in Ruby on Rails 4. My personal feeling tells me ideally to not do calls to I18n.t() in models, I just think model methods should be consistent, and not depending on varying environmental situations like the current user's locale, especially since I18n is usually related to views. I've got a few questions about this though:
Do you think this is a good rule in general?
How should I manage error messages in custom validation methods? Should I make exceptions for that scenario?
How should I manage customised keys that we use in form fields, such as the displayed text of a collection_select, that are partially translated? Is there a way to use view helpers for these occasions, that is (almost) as convenient as building model methods for these?
Yes. Translations belong to the view layer and only to the "display" part of it (that is, not to the API, which is still view)
Error messsages should be standard enough so you get to translate them correctly by iterating them in the view and getting the piecewise translations. Unfortunately that's not always possible because of different grammatical order of the sentences in languages. Still it's not useful to move those translations to the model. ActiveRecord's Errors class has hooks for translations just like ActiveModel, so the view can rely on them without injecting any i18n in the model itself.
Select helpers can often take a lambda as a label generator, you can use and abuse view paths and relative i18n keys and whatever you need without having to inject anything in the model. In case of doubt, use a presenter and inject I18n in it.
In my Rails app I need to maintain too many default texts. For example, I have a Hotel model. When someone creates a hotel, some default email templates, default sms templates get created automatically for that hotel. Currently I am maintaining them inside a Constants modules and access them like:
Constants::DEFAULT_RESERVATION_EMAIL_TEMPLATE
Constants::DEFAULT_RESERVATION_SMS_TEMPLATE
etc.
I wonder if there any other convenient and efficient ways to maintain those default texts as it seems Constants module is going huge in each days. I am thinking like I can manage them in a yaml file so that it does not affect on memory and I can read from the yaml file when necessary.
I would use the normal i18n yml files for that. You can manage multiple languages through yml files. And you can easily change the content.
But you also can use a database for your backend.
Following links could give you an idea:
http://asciicasts.com/episodes/256-i18n-backends
Rails: store translations in database
http://franck.verrot.fr/blog/2010/02/27/rails-3-let-activerecord-manage-your-translations/
https://github.com/svenfuchs/globalize3 (if you also have default texts for model attributes, you can define them in a yml file and save them in the database after create, or something similar..)
I have set up a simple Rails app based on Post, Comment example from the default documentation. -> http://edgeguides.rubyonrails.org/getting_started.html
What would be the appropriate way of localizing existing content from these Posts ?
If I assume that Post has a :title and "content, and I would like this content to be entered not only in English, but also in German and Dutch, then how would I achieve this if I want the end result to look similar to this :
http://0.0.0.0:3000/en/posts.json to get all posts in English and respectively,
http://0.0.0.0:3000/de/posts.json for German?
I havent found a gem yet, that would support such multilangual content.
I have seen doe, many existing ways to do so, mostly in applications like Wordpress or Drupal, which are not rails based.
I guess the preferred way would be either storing EN and DE posts in seperate tables (but then how to add new languages?), or to place all translations within the same database table, but seperate translations in a different way, but how to get them easily out in json in the right language?
I am really confused and puzzled why such a "common" problem, is not solved in Rails by default, or maybe I am simply looking in the wrong place.
Globalize3 will do what you want to do. It stores all translations for a particular model in a separate table, with a locale column identifying what the language of a particular translation is. This makes it possible to add new languages without having to migrate the database, so the approach is very scalable.
There are other gems for translating content as well, e.g. Traco is one that I know of, but this one stores the translations in the same table as the model, so when you add new languages you have to migrate each model table. I personally prefer the Globalize3 approach, although it makes the gem itself more complicated internally.
I'm just starting out in Rails and there's a lot I still need to learn so I'm likely to be on Stackoverflow more often than normal asking beginner Rails / Ruby questions.
I'm just trying to figure out how Helpers work in Rails. From what I've seen so far, Helpers are intended to be used with Views and not so much with your Controllers.
However I would like to make a simple function that will validate the user input given in params (check if certain params are defined and optionally check if their value is valid).
Can anyone explain to me what would be the best way of implementing this? (Keeping in mind that I will want to use this in many different controllers so it should be globally available.)
I also noticed that by default Rails does not generate a lib folder in the main application folder. Are developers to place their libs outside the app folder in the main folder, or does Rails use libraries differently?
With regards to your validation issue, it depends on what you are validating.
If the data makes up objects from your problem domain, also known as models, then you should use the built in validators from ActiveModel. This is probably what you should do, but its hard to say without knowing the exact problem. See the Rails Guides on Validations. You can tell if this is the case by asking yourself if the data that needs validation will be stored after you get it. If so, its most definitely a model. An example of this kind of data would be the title and text fields of a blog post being sent to Rails from a browser form.
If the data is something tertiary to your models, or specific to presentation, then you should be fine using helpers. You noticed that helpers are used mostly in the views, and although this is true, theres nothing stopping you from using them in the controllers, you just have to declare that you will use them using the ActiveController#helper method. Inside the ApplicationController class, a lot of devs will put helper :all to just include all the helpers in all the controllers. Once the code has been required once, it doesn't really incur that big a performance hit.
Do note that almost all incoming data can be modeled using a model. A big school of thought in the Rails world subscribes to the Fat Model idea. People say that putting as much code as possible in the model and as little in the controller as possible separates concerns properly and leads to more maintainable code. This suggests that even if you don't think the incoming data is modelable (in the sense that you can create a model to represent it), you should try to make it a model and encapsulate the logic around validating it. However, you may find that making a helper function is faster, and either will work.
Your notion of validating user input is a good one. I get the feeling that as you are new to Rails you are used to doing these things yourself, but that doesn't quite apply here. In the Rails world, a lot of the common stuff like validations is handled by the framework. You don't have to check for presence in the params array, instead you call validates_presence_of on the model and let Rails spit the error out to the user. It makes things easier in the long run if you let the framework do what it is designed to.
With regards to your question about the lib folder, it doesn't really matter. You can put miscellaneous support files and libraries in the lib folder in the root directory and they will be available for use in your application (the files in the app folder). You can also choose to abstract your code into a plugin or a gem and include it that way, which a lot of people opt to do. My suggestion for this would be to read up on the notion of gems and plugins before diving in.
Want you want is probably a custom validator (in Rails3):
http://railscasts.com/episodes/211-validations-in-rails-3
You can either add libs in a lib folder you create, or add them to config/initializers in a file you add. Files in the initializers directory are automatically loaded by Rails.
I have a small ruby application that I made on my local machine. It uses a text file insted of a database. It's a simple app that takes in a word, processes it against the text file, and then outputs the results using puts.
I would like to fit it into a RoR framework, hosted on my personal machine. I have run through some lessons and tutorials in a few books and online materials I have, but they all involve databases.
I read thru the notes in config/environment.rb and found at line 19 instructions to uncomment the line that removes ActiveRecord.
I am currently looking for the appropriate directories to put the text file itself, and the code from the ruby app that reads this text file. Thank you.
You probably want to do something like the following:
Have a controller that takes the word as a parameter.
Turn you app into a function that takes the word as a parameter and returns the results (instead of doing puts)
Call the function from your controller and render the results (e.g. something like:
render :text => my_func(word)
This sounds like a better fit for something more lightweight like Sinatra.
If you were bound and determined to use Rails, you could make a controller with an action that just runs the code from your program, but it seems like overkill. You wouldn't be using 99.9% of the framework's capabilities, so why is it even there?
If your just trying to give it a little interface you could look at Shoes which is an easy to use multi-platform gui framework.
Or like someone mentioned take a look at Sinatra.
You can simply use rails without worrying about ActiveRecord. I'd sugest making your little application into a class and requiring the file in a controller you want to use (or in environment.rb). Put the file in lib and if the data is temporary, "tmp" is fine or just put it in "lib" with the script you wrote even "db" is a fine location for it. To make a view just run your code and put the return in a class variable and make a view for it.
A model need not inherit from ActiveRecord::Base. Or anything else. As long as it follows the naming convention for models, Rails will pick it up without problem.
Having said that, if you're really looking at a one-model, one-controller, one-action, no-database app, then Sinatra would probably be a really good lightweight place to start...