#-- # Copyright (c) 2010-2012 Michael Berkovich, tr8n.net # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the # "Software"), to deal in the Software without restriction, including # without limitation the rights to use, copy, modify, merge, publish, # distribute, sublicense, and/or sell copies of the Software, and to # permit persons to whom the Software is furnished to do so, subject to # the following conditions: # # The above copyright notice and this permission notice shall be # included in all copies or substantial portions of the Software. # # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND # NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE # LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. #++ # #-- Tr8n::LanguageCaseRule Schema Information # # Table name: tr8n_language_case_rules # # id INTEGER not null, primary key # language_case_id integer not null # language_id integer # translator_id integer # definition text not null # position integer # created_at datetime # updated_at datetime # # Indexes # # tr8n_lcr_translator_id (translator_id) # tr8n_lcr_lang_id (language_id) # tr8n_lcr_case_id (language_case_id) # #++ class Tr8n::LanguageCaseRule < ActiveRecord::Base set_table_name :tr8n_language_case_rules attr_accessible :language_case_id, :language_id, :translator_id, :definition, :position attr_accessible :language, :language_case, :translator belongs_to :language_case, :class_name => "Tr8n::LanguageCase" belongs_to :language, :class_name => "Tr8n::Language" belongs_to :translator, :class_name => "Tr8n::Translator" serialize :definition def definition @indifferent_def ||= HashWithIndifferentAccess.new(super) end def self.cache_key(id) "language_case_rule_#{id}" end def cache_key self.class.cache_key(id) end # TODO: what is this for? def self.by_id(id) Tr8n::Cache.fetch(cache_key(id)) do find_by_id(id) end end def self.gender_options [["not applicable", "none"], ["unknown", "unknown"], ["male", "male"], ["female", "female"]] end def self.condition_options(with_if = false) opts = [["starts with", "starts_with"], ["does not start with", "does_not_start_with"], ["ends in", "ends_in"], ["does not end in", "does_not_end_in"], ["is", "is"], ["is not", "is_not"]] return opts unless with_if opts.each do |opt| opt[0] = "if #{opt[0]}" end opts end def self.operation_options [["replace with", "replace"], ["prepand", "prepand"], ["append", "append"]] end def self.operator_options [["and", "and"], ["or", "or"]] end def evaluate(object, value) value = value.to_s if ["male", "female", "unknown", "neutral"].include?(definition["gender"]) object_gender = Tr8n::GenderRule.gender_token_value(object) return false if definition["gender"] == "male" and object_gender != Tr8n::GenderRule.gender_object_value_for("male") return false if definition["gender"] == "female" and object_gender != Tr8n::GenderRule.gender_object_value_for("female") return false if definition["gender"] == "unknown" and object_gender != Tr8n::GenderRule.gender_object_value_for("unknown") end result1 = evaluate_part(value, 1) if definition["multipart"] == "true" result2 = evaluate_part(value, 2) return false if definition["operator"] == "and" and !(result1 and result2) return false if definition["operator"] == "or" and !(result1 or result2) end result1 end def evaluate_part(token_value, index) values = sanitize_values(definition["value#{index}"]) case definition["part#{index}"] when "starts_with" values.each do |value| return true if token_value.to_s =~ /^#{value.to_s}/ end return false when "does_not_start_with" values.each do |value| return false if token_value.to_s =~ /^#{value.to_s}/ end return true when "ends_in" values.each do |value| return true if token_value.to_s =~ /#{value.to_s}$/ end return false when "does_not_end_in" values.each do |value| return false if token_value.to_s =~ /#{value.to_s}$/ end return true when "is" return values.include?(token_value) when "is_not" return !values.include?(token_value) end false end def apply(value) value = value.to_s values = sanitize_values(definition["value1"]) regex = values.join('|') case definition["operation"] when "replace" if definition["part1"] == "starts_with" return value.gsub(/\b(#{regex})/, definition["operation_value"]) elsif definition["part1"] == "is" return definition["operation_value"] elsif definition["part1"] == "ends_in" return value.gsub(/(#{regex})\b/, definition["operation_value"]) end when "prepand" return "#{definition["operation_value"]}#{value}" when "append" return "#{value}#{definition["operation_value"]}" end value end def sanitize_values(values) return [] unless values values.split(",").collect{|val| val.strip} end def humanize_values(values) sanitize_values(values).join(", ") end def description return "undefined rule" if definition.blank? desc = "If" if definition["gender"] != "none" desc << " subject" if ["male", "female"].include?(definition["gender"]) desc << " is a #{definition["gender"]}" else desc << " has an unknown gender" end end desc << " and" unless desc == "If" desc << " token value" desc << describe_part(1) if ["true", true].include?(definition["multipart"]) desc << " " << definition["operator"] desc << describe_part(2) end desc << ", then" case definition["operation"] when "replace" then desc << " replace it with" when "prepand" then desc << " prepand the value with" when "append" then desc << " append the value with" end desc << " '" << humanize_values(definition["operation_value"]) << "' " desc.html_safe end def describe_part(index) desc = "" case definition["part#{index}"] when "starts_with" then desc << " starts with" when "does_not_start_with" then desc << " does not start with" when "ends_in" then desc << " ends in" when "does_not_end_in" then desc << " does not end in" when "is" then desc << " is" when "is_not" then desc << " is not" end desc << " '" << humanize_values(definition["value#{index}"]) << "'" end end