简体   繁体   English

仅在视图中覆盖活动记录模型属性

[英]Overriding active record model attributes only in the view

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.job时可以翻译数据库中默认的任何作业,从而可以进行翻译默认值是在视图中,而不是在模型中,因为我有一些sql逻辑来测试有多少人从事编码工作。

#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. 从事“编码员”工作的人类“鲍勃”应该是会计的“奴隶”,而使用法语使用该应用程序的人应该是“编码员”,但是我仍然应该能够为每个编码员做一个发现。

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? 您的帮助程序代码将等效于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. SimpleDelegator是一个标准的ruby类,如果delegator类未定义方法,则该方法仅将任何方法调用都委派给“ wrapped”对象。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM