views:

28

answers:

1

I have an object called human and that object has a field called job. I want users to be able to add their own jobs (which will obviously be added in their own language) but I want to have any job that is a default in the database to be translated when someone does a Human.job, can rails translate the default if it is in the view but not if it is in the model as I have some sql logic that tests how many humans have the job of coder.

#Human
class Human < ActiveRecord::Base
  validates_presence_of :job, :name
  def job
    if is_view?
     key = job.gsub(/ /,'_')
      translation = I18n.translate("jobs.#{key.downcase}")
      if translation.include?('translation missing:')
        job
      else
        translation
      end
    else
      job
    end
  end
end

#en.yml
en:
  jobs:
    coder: 'coder'

#en-Accountants.yml
en-Accountants:
  jobs:
    coder: 'slave'

#fr.yml
fr:
  jobs:
    coder: 'le coder'

eg:

A human 'Bob' with a job of 'Coder' should be 'slave' to accountants and 'le coder' to those using the app in french but I should be able to still do a find for every coder.

A: 

If you want to present the name of the job in different ways then the best place to do that would be in a helper. That keeps the presentation logic out of your model. Your helper code would be equivalent to your is_view? code.

Admittedly that means you have to call it each time you display the job name, probably what you are trying to avoid. You could create a delegator class which you use for humans in your views. You'd still need to remember to create delegated versions of humans though when you are passing them to your views.

Something like this for example:

class HumanView < SimpleDelegator
  def job
    unchanged_job = super # The actual saved job string
    key = unchanged.gsub(/ /,'_')
    translation = I18n.translate("jobs.#{key.downcase}")
    if translation.include?('translation missing:')
      unchanged_job
    else
      translation
    end
  end
end

Then in your controller you can do:

def index
  humans = Human.find(:all) # For example
  @humans = humans.map { |h| HumanView.new(h) }
end

def show
  h = Human.find(params[:id])
  @human = HumanView.new(h)
end

SimpleDelegator is a standard ruby class that just delegates any method calls to the 'wrapped' object if the delegator class doesn't define the method.

Shadwell
Thanks Shadwell! This is a big help!
dah