module Typus
module Orm
module ClassMethods
# Model fields as an ActiveSupport::OrderedHash.
def model_fields
ActiveSupport::OrderedHash.new.tap do |hash|
columns.map { |u| hash[u.name.to_sym] = u.type.to_sym }
end
end
# Model relationships as an ActiveSupport::OrderedHash.
def model_relationships
ActiveSupport::OrderedHash.new.tap do |hash|
reflect_on_all_associations.map { |i| hash[i.name] = i.macro }
end
end
# Model description for admin panel.
def typus_description
read_model_config['description']
end
# Form and list fields
def typus_fields_for(filter)
ActiveSupport::OrderedHash.new.tap do |fields_with_type|
data = read_model_config['fields']
fields = data[filter.to_s] || data['default'] || ""
virtual_fields = instance_methods - model_fields.keys.map { |i| i.to_s }
fields.extract_settings.map { |f| f.to_sym }.each do |field|
if reflect_on_association(field)
fields_with_type[field.to_s] = reflect_on_association(field).macro
next
end
if typus_field_options_for(:selectors).include?(field)
fields_with_type[field.to_s] = :selector
next
end
dragonfly = respond_to?(:dragonfly_apps_for_attributes) && dragonfly_apps_for_attributes.try(:has_key?, field)
paperclip = respond_to?(:attachment_definitions) && attachment_definitions.try(:has_key?, field)
if dragonfly || paperclip
fields_with_type[field.to_s] = :file
next
end
if virtual_fields.include?(field.to_s)
fields_with_type[field.to_s] = :virtual
end
fields_with_type[field.to_s] = case field.to_s
when 'parent', 'parent_id' then :tree
when /password/ then :password
when 'position' then :position
when /\./ then :transversal
else
if fields_with_type[field.to_s]
fields_with_type[field.to_s]
else
model_fields[field]
end
end
end
end
end
def typus_filters
ActiveSupport::OrderedHash.new.tap do |fields_with_type|
if data = read_model_config['filters']
data.extract_settings.map { |i| i.to_sym }.each do |field|
attribute_type = model_fields[field.to_sym]
if reflect_on_association(field.to_sym)
attribute_type = reflect_on_association(field.to_sym).macro
end
fields_with_type[field.to_s] = attribute_type
end
end
end
end
# Extended actions for this model on Typus.
def typus_actions_on(filter)
actions = read_model_config['actions']
actions && actions[filter.to_s] ? actions[filter.to_s].extract_settings : []
end
# Used for +search+, +relationships+
def typus_defaults_for(filter)
read_model_config[filter.to_s].try(:extract_settings) || []
end
def typus_search_fields
Hash.new.tap do |search|
typus_defaults_for(:search).each do |field|
if field.starts_with?("=")
field.slice!(0)
search[field] = "="
elsif field.starts_with?("^")
field.slice!(0)
search[field] = "^"
else
search[field] = "@"
end
end
end
end
def typus_application
read_model_config['application'] || 'Unknown'
end
def typus_field_options_for(filter)
options = read_model_config['fields']['options']
options && options[filter.to_s] ? options[filter.to_s].extract_settings.map { |i| i.to_sym } : []
end
#--
# With Typus::Resources we some application defaults.
#
# Typus::Resources.setup do |config|
# config.per_page = 15
# end
#
# If for any reason we need a better default for an specific resource we
# we override it on `application.yaml`.
#
# Post:
# ...
# options:
# per_page: 15
#++
def typus_options_for(filter)
options = read_model_config['options']
unless options.nil? || options[filter.to_s].nil?
options[filter.to_s]
else
Typus::Resources.send(filter)
end
end
def typus_export_formats
read_model_config['export'].try(:extract_settings) || []
end
def typus_order_by
typus_defaults_for(:order_by).map do |field|
field.include?('-') ? "#{table_name}.#{field.delete('-')} DESC" : "#{table_name}.#{field} ASC"
end.join(', ')
end
#--
# Define our own boolean mappings.
#
# Post:
# fields:
# default: title, status
# options:
# booleans:
# status: "Published", "Not published"
#
#++
def typus_boolean(attribute = :default)
options = read_model_config['fields']['options']
boolean = if options && options['booleans'] && boolean = options['booleans'][attribute.to_s]
boolean.is_a?(String) ? boolean.extract_settings : boolean
else
["True", "False"]
end
{ boolean.first => "true", boolean.last => "false" }
end
#--
# Custom date formats.
#++
def typus_date_format(attribute = :default)
options = read_model_config['fields']['options']
if options && options['date_formats'] && options['date_formats'][attribute.to_s]
options['date_formats'][attribute.to_s].to_sym
else
:default
end
end
#--
# This is user to use custome templates for attribute:
#
# Post:
# fields:
# form: title, body, status
# options:
# templates:
# body: rich_text
#
# Templates are stored on app/views/admin/templates.
#++
def typus_template(attribute)
options = read_model_config['fields']['options']
if options && options['templates'] && options['templates'][attribute.to_s]
options['templates'][attribute.to_s]
end
end
def adapter
@adapter ||= ActiveRecord::Base.configurations[Rails.env]['adapter']
end
def typus_user_id?
columns.map { |u| u.name }.include?(Typus.user_fk)
end
def read_model_config
Typus::Configuration.config[name] or raise "No typus configuration specified for #{name}"
end
end
module InstanceMethods
def owned_by?(user)
send(Typus.user_fk) == user.id
end
end
end
end
if defined?(ActiveRecord)
require 'typus/orm/active_record/search'
ActiveRecord::Base.extend Typus::Orm::ClassMethods
ActiveRecord::Base.extend Typus::Orm::ClassMethods::Search
ActiveRecord::Base.send :include, Typus::Orm::InstanceMethods
end