app/models/ling.rb
class Ling < ActiveRecord::Base
include Groupable
include CSVAttributes
CSV_ATTRIBUTES = %w[ id name depth parent_id group_id creator_id ]
def self.csv_attributes
CSV_ATTRIBUTES
end
acts_as_gmappable :process_geocoding => false, :lat => :get_latitude, :lng => :get_longitude
validates_presence_of :name, :depth
validates_numericality_of :depth
validates_uniqueness_of :name, :scope => :group_id
validates_existence_of :parent, :allow_nil => true
validate :parent_depth_check
validate :group_association_match
validate :available_depth_for_group
# TODO dependent nullify parent_id on child if parent destroyed
belongs_to :parent, :class_name => "Ling", :foreign_key => "parent_id", :inverse_of => :children
has_many :children, :class_name => "Ling", :foreign_key => "parent_id", :inverse_of => :parent
has_many :examples, :dependent => :destroy
has_many :lings_properties, :dependent => :destroy
has_many :properties, :through => :lings_properties
has_many :stored_values, :as => :storable, :dependent => :destroy
include Concerns::Wheres
include Concerns::Selects
include Concerns::Orders
attr_protected :depth
scope :parent_ids, select("#{self.table_name}.parent_id")
scope :with_parent_id, lambda { |id_or_ids| where("#{self.table_name}.parent_id" => id_or_ids) }
def get_latitude
get_latlong.split(/,/).first
end
def get_longitude
get_latlong.split(/,/).last
end
attr_reader :info
def get_infos
props_in_ling
self
end
def grouped_name
group.ling_name_for_depth(self.depth || 0)
end
def add_property(value, property)
params = {:property_id => property.id, :value => value}
unless lings_properties.exists?(params)
lings_properties.create(params) do |lp|
lp.group = group
end
end
end
def add_property_sureness(value, sureness, property)
params = {:property_id => property.id, :value => value, :sureness => sureness}
unless lings_properties.exists?(params)
lings_properties.create(params) do |lp|
lp.group = group
end
end
end
def parent_depth_check
errors.add(:parent, "must be a #{group.ling0_name.humanize} object") if (depth == 1 && parent && parent.depth != 0)
end
def group_association_match
errors.add(:parent, "#{group.ling0_name.humanize} must belong to the same group as this #{self.grouped_name}") if parent && parent.group != group
end
def available_depth_for_group
errors.add(:depth, "is deeper than allowed in #{group.name}") if group && depth && group.depth_maximum < depth
end
def storable_keys
group.present? ? group.ling_storable_keys : []
end
def store_value!(key_symbol_or_string, value_string)
key = key_symbol_or_string.to_s
if curr = stored_values.with_key(key).first
curr.value = value_string
curr.save
else
StoredValue.create(:key => key, :value => value_string, :storable => self)
end
end
def stored_value(key_symbol_or_string)
key = key_symbol_or_string.to_s
if storable_keys.include? key
(record = stored_values.select{|sv| sv.key == key}.first).present? ? record.value : ""
else
nil
end
end
private
def get_latlong
property = Property.in_group(group).where(:name => 'latlong').first
if property.present?
lings_has_latlong = LingsProperty.in_group(group).where(:property_id => property.id, :ling_id => self.id).first
return lings_has_latlong.value unless lings_has_latlong.nil?
end
return ""
end
def props_in_group
@props_total ||= Property.in_group(group).at_depth(depth).count(:id)
end
def props_in_ling
@info ||= LingsProperty.in_group(group).where(:ling_id => self.id).count(:id) * 100 / props_in_group
@info = 100 if @info > 100
end
end