typus 3.1.5 → 3.1.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/{CHANGELOG → CHANGELOG.md} +73 -22
- data/Gemfile +6 -6
- data/README.md +1 -1
- data/app/controllers/admin/resources_controller.rb +1 -1
- data/app/helpers/admin/resources/data_types/integer_helper.rb +10 -0
- data/app/helpers/admin/resources/data_types/position_helper.rb +1 -1
- data/app/helpers/admin/resources/filters_helper.rb +2 -1
- data/app/helpers/admin/resources/form_helper.rb +7 -3
- data/app/helpers/admin/resources/relationships_helper.rb +2 -1
- data/app/views/admin/templates/_has_many.html.erb +5 -1
- data/app/views/admin/templates/_position.html.erb +1 -1
- data/config/routes.rb +3 -6
- data/lib/typus.rb +5 -2
- data/lib/typus/controller/format.rb +1 -1
- data/lib/typus/orm/active_record/class_methods.rb +5 -14
- data/lib/typus/orm/active_record/search.rb +2 -66
- data/lib/typus/orm/base/class_methods.rb +180 -0
- data/lib/typus/orm/base/search.rb +91 -0
- data/lib/typus/orm/mongoid.rb +12 -1
- data/lib/typus/orm/mongoid/class_methods.rb +55 -1
- data/lib/typus/orm/mongoid/instance_methods.rb +18 -0
- data/lib/typus/orm/mongoid/search.rb +46 -0
- data/lib/typus/version.rb +1 -1
- data/typus.gemspec +2 -2
- data/vendor/assets/fancybox/{jquery.fancybox-1.3.4.css → jquery.fancybox-1.3.4.css.erb} +33 -33
- metadata +22 -18
- data/lib/typus/orm/base.rb +0 -167
| @@ -0,0 +1,180 @@ | |
| 1 | 
            +
            module Typus
         | 
| 2 | 
            +
              module Orm
         | 
| 3 | 
            +
                module Base
         | 
| 4 | 
            +
                  module ClassMethods
         | 
| 5 | 
            +
             | 
| 6 | 
            +
                    # Model fields as an <tt>ActiveSupport::OrderedHash</tt>.
         | 
| 7 | 
            +
                    def model_fields; end
         | 
| 8 | 
            +
             | 
| 9 | 
            +
                    # Model relationships as an <tt>ActiveSupport::OrderedHash</tt>.
         | 
| 10 | 
            +
                    def model_relationships; end
         | 
| 11 | 
            +
             | 
| 12 | 
            +
                    # Model description for admin panel.
         | 
| 13 | 
            +
                    def typus_description
         | 
| 14 | 
            +
                      read_model_config['description']
         | 
| 15 | 
            +
                    end
         | 
| 16 | 
            +
             | 
| 17 | 
            +
                    # Form and list fields
         | 
| 18 | 
            +
                    def typus_fields_for(filter); end
         | 
| 19 | 
            +
             | 
| 20 | 
            +
                    def typus_filters; end
         | 
| 21 | 
            +
             | 
| 22 | 
            +
                    # Extended actions for this model on Typus.
         | 
| 23 | 
            +
                    def typus_actions_on(filter)
         | 
| 24 | 
            +
                      actions = read_model_config['actions']
         | 
| 25 | 
            +
                      actions && actions[filter.to_s] ? actions[filter.to_s].extract_settings : []
         | 
| 26 | 
            +
                    end
         | 
| 27 | 
            +
             | 
| 28 | 
            +
                    # Used for +search+, +relationships+
         | 
| 29 | 
            +
                    def typus_defaults_for(filter)
         | 
| 30 | 
            +
                      read_model_config[filter.to_s].try(:extract_settings) || []
         | 
| 31 | 
            +
                    end
         | 
| 32 | 
            +
             | 
| 33 | 
            +
                    def typus_search_fields
         | 
| 34 | 
            +
                      Hash.new.tap do |search|
         | 
| 35 | 
            +
                        typus_defaults_for(:search).each do |field|
         | 
| 36 | 
            +
                          if field.starts_with?("=")
         | 
| 37 | 
            +
                            field.slice!(0)
         | 
| 38 | 
            +
                            search[field] = "="
         | 
| 39 | 
            +
                          elsif field.starts_with?("^")
         | 
| 40 | 
            +
                            field.slice!(0)
         | 
| 41 | 
            +
                            search[field] = "^"
         | 
| 42 | 
            +
                          else
         | 
| 43 | 
            +
                            search[field] = "@"
         | 
| 44 | 
            +
                          end
         | 
| 45 | 
            +
                        end
         | 
| 46 | 
            +
                      end
         | 
| 47 | 
            +
                    end
         | 
| 48 | 
            +
             | 
| 49 | 
            +
                    def typus_application
         | 
| 50 | 
            +
                      name = read_model_config['application'] || 'Unknown'
         | 
| 51 | 
            +
                      name.extract_settings.first
         | 
| 52 | 
            +
                    end
         | 
| 53 | 
            +
             | 
| 54 | 
            +
                    def typus_field_options_for(filter)
         | 
| 55 | 
            +
                      options = read_model_config['fields']['options']
         | 
| 56 | 
            +
                      options && options[filter.to_s] ? options[filter.to_s].extract_settings.map(&:to_sym) : []
         | 
| 57 | 
            +
                    end
         | 
| 58 | 
            +
             | 
| 59 | 
            +
                    #--
         | 
| 60 | 
            +
                    # With +Typus::Resources.setup+ we can define application defaults.
         | 
| 61 | 
            +
                    #
         | 
| 62 | 
            +
                    #     Typus::Resources.setup do |config|
         | 
| 63 | 
            +
                    #       config.per_page = 25
         | 
| 64 | 
            +
                    #     end
         | 
| 65 | 
            +
                    #
         | 
| 66 | 
            +
                    # If for any reason we need a better default for an specific resource we
         | 
| 67 | 
            +
                    # can override it on +application.yaml+.
         | 
| 68 | 
            +
                    #
         | 
| 69 | 
            +
                    #     Post:
         | 
| 70 | 
            +
                    #       ...
         | 
| 71 | 
            +
                    #       options:
         | 
| 72 | 
            +
                    #         per_page: 25
         | 
| 73 | 
            +
                    #++
         | 
| 74 | 
            +
                    def typus_options_for(filter)
         | 
| 75 | 
            +
                      options = read_model_config['options']
         | 
| 76 | 
            +
             | 
| 77 | 
            +
                      unless options.nil? || options[filter.to_s].nil?
         | 
| 78 | 
            +
                        options[filter.to_s]
         | 
| 79 | 
            +
                      else
         | 
| 80 | 
            +
                        Typus::Resources.send(filter)
         | 
| 81 | 
            +
                      end
         | 
| 82 | 
            +
                    end
         | 
| 83 | 
            +
             | 
| 84 | 
            +
                    def typus_order_by
         | 
| 85 | 
            +
                      typus_defaults_for(:order_by).map do |field|
         | 
| 86 | 
            +
                        field.include?('-') ? "#{field.delete('-')} DESC" : "#{field} ASC"
         | 
| 87 | 
            +
                      end.join(', ')
         | 
| 88 | 
            +
                    end
         | 
| 89 | 
            +
             | 
| 90 | 
            +
                    #--
         | 
| 91 | 
            +
                    # Define our own boolean mappings.
         | 
| 92 | 
            +
                    #
         | 
| 93 | 
            +
                    #     Post:
         | 
| 94 | 
            +
                    #       fields:
         | 
| 95 | 
            +
                    #         default: title, status
         | 
| 96 | 
            +
                    #         options:
         | 
| 97 | 
            +
                    #           booleans:
         | 
| 98 | 
            +
                    #             status: "Published", "Not published"
         | 
| 99 | 
            +
                    #
         | 
| 100 | 
            +
                    #++
         | 
| 101 | 
            +
                    def typus_boolean(attribute = :default)
         | 
| 102 | 
            +
                      options = read_model_config['fields']['options']
         | 
| 103 | 
            +
             | 
| 104 | 
            +
                      boolean = if options && options['booleans'] && boolean = options['booleans'][attribute.to_s]
         | 
| 105 | 
            +
                        boolean.is_a?(String) ? boolean.extract_settings : boolean
         | 
| 106 | 
            +
                      else
         | 
| 107 | 
            +
                        ["True", "False"]
         | 
| 108 | 
            +
                      end
         | 
| 109 | 
            +
             | 
| 110 | 
            +
                      [[boolean.first, "true"], [boolean.last, "false"]]
         | 
| 111 | 
            +
                    end
         | 
| 112 | 
            +
             | 
| 113 | 
            +
                    #--
         | 
| 114 | 
            +
                    # Custom date formats.
         | 
| 115 | 
            +
                    #++
         | 
| 116 | 
            +
                    def typus_date_format(attribute = :default)
         | 
| 117 | 
            +
                      options = read_model_config['fields']['options']
         | 
| 118 | 
            +
                      if options && options['date_formats'] && options['date_formats'][attribute.to_s]
         | 
| 119 | 
            +
                        options['date_formats'][attribute.to_s].to_sym
         | 
| 120 | 
            +
                      else
         | 
| 121 | 
            +
                        :default
         | 
| 122 | 
            +
                      end
         | 
| 123 | 
            +
                    end
         | 
| 124 | 
            +
             | 
| 125 | 
            +
                    #--
         | 
| 126 | 
            +
                    # This is user to use custome templates for attribute:
         | 
| 127 | 
            +
                    #
         | 
| 128 | 
            +
                    #     Post:
         | 
| 129 | 
            +
                    #       fields:
         | 
| 130 | 
            +
                    #         form: title, body, status
         | 
| 131 | 
            +
                    #         options:
         | 
| 132 | 
            +
                    #           templates:
         | 
| 133 | 
            +
                    #             body: rich_text
         | 
| 134 | 
            +
                    #
         | 
| 135 | 
            +
                    # Templates are stored on <tt>app/views/admin/templates</tt>.
         | 
| 136 | 
            +
                    #++
         | 
| 137 | 
            +
                    def typus_template(attribute)
         | 
| 138 | 
            +
                      options = read_model_config['fields']['options']
         | 
| 139 | 
            +
                      if options && options['templates'] && options['templates'][attribute.to_s]
         | 
| 140 | 
            +
                        options['templates'][attribute.to_s]
         | 
| 141 | 
            +
                      end
         | 
| 142 | 
            +
                    end
         | 
| 143 | 
            +
             | 
| 144 | 
            +
                    def adapter
         | 
| 145 | 
            +
                      @adapter ||= ::ActiveRecord::Base.configurations[Rails.env]['adapter']
         | 
| 146 | 
            +
                    end
         | 
| 147 | 
            +
             | 
| 148 | 
            +
                    def typus_user_id?; end
         | 
| 149 | 
            +
             | 
| 150 | 
            +
                    def read_model_config
         | 
| 151 | 
            +
                      Typus::Configuration.config[name] or raise "No typus configuration specified for #{name}"
         | 
| 152 | 
            +
                    end
         | 
| 153 | 
            +
             | 
| 154 | 
            +
                    #--
         | 
| 155 | 
            +
                    #     >> Post.to_resource
         | 
| 156 | 
            +
                    #     => "posts"
         | 
| 157 | 
            +
                    #     >> Admin::User.to_resource
         | 
| 158 | 
            +
                    #     => "admin/users"
         | 
| 159 | 
            +
                    #++
         | 
| 160 | 
            +
                    def to_resource
         | 
| 161 | 
            +
                      name.underscore.pluralize
         | 
| 162 | 
            +
                    end
         | 
| 163 | 
            +
             | 
| 164 | 
            +
                    def custom_attribute?(field)
         | 
| 165 | 
            +
                      case field.to_s
         | 
| 166 | 
            +
                      when 'parent', 'parent_id' then :tree
         | 
| 167 | 
            +
                      when /password/            then :password
         | 
| 168 | 
            +
                      when 'position'            then :position
         | 
| 169 | 
            +
                      when /\./                  then :transversal
         | 
| 170 | 
            +
                      end
         | 
| 171 | 
            +
                    end
         | 
| 172 | 
            +
             | 
| 173 | 
            +
                    def virtual_fields
         | 
| 174 | 
            +
                      instance_methods.map(&:to_s) - model_fields.keys.map(&:to_s)
         | 
| 175 | 
            +
                    end
         | 
| 176 | 
            +
             | 
| 177 | 
            +
                  end
         | 
| 178 | 
            +
                end
         | 
| 179 | 
            +
              end
         | 
| 180 | 
            +
            end
         | 
| @@ -0,0 +1,91 @@ | |
| 1 | 
            +
            module Typus
         | 
| 2 | 
            +
              module Orm
         | 
| 3 | 
            +
                module Base
         | 
| 4 | 
            +
                  module Search
         | 
| 5 | 
            +
             | 
| 6 | 
            +
                    def build_search_conditions(key, value)
         | 
| 7 | 
            +
                      raise "Not implemented!"
         | 
| 8 | 
            +
                    end
         | 
| 9 | 
            +
             | 
| 10 | 
            +
                    def build_boolean_conditions(key, value)
         | 
| 11 | 
            +
                      { key => (value == 'true') ? true : false }
         | 
| 12 | 
            +
                    end
         | 
| 13 | 
            +
             | 
| 14 | 
            +
                    def build_datetime_conditions(key, value)
         | 
| 15 | 
            +
                      tomorrow = Time.zone.now.beginning_of_day.tomorrow
         | 
| 16 | 
            +
             | 
| 17 | 
            +
                      interval = case value
         | 
| 18 | 
            +
                                 when 'today'         then 0.days.ago.beginning_of_day..tomorrow
         | 
| 19 | 
            +
                                 when 'last_few_days' then 3.days.ago.beginning_of_day..tomorrow
         | 
| 20 | 
            +
                                 when 'last_7_days'   then 6.days.ago.beginning_of_day..tomorrow
         | 
| 21 | 
            +
                                 when 'last_30_days'  then 30.days.ago.beginning_of_day..tomorrow
         | 
| 22 | 
            +
                                 end
         | 
| 23 | 
            +
             | 
| 24 | 
            +
                      build_filter_interval(interval, key)
         | 
| 25 | 
            +
                    end
         | 
| 26 | 
            +
             | 
| 27 | 
            +
                    alias_method :build_time_conditions, :build_datetime_conditions
         | 
| 28 | 
            +
             | 
| 29 | 
            +
                    def build_date_conditions(key, value)
         | 
| 30 | 
            +
                      tomorrow = 0.days.ago.tomorrow.to_date
         | 
| 31 | 
            +
             | 
| 32 | 
            +
                      interval = case value
         | 
| 33 | 
            +
                                 when 'today'         then 0.days.ago.to_date..tomorrow
         | 
| 34 | 
            +
                                 when 'last_few_days' then 3.days.ago.to_date..tomorrow
         | 
| 35 | 
            +
                                 when 'last_7_days'   then 6.days.ago.to_date..tomorrow
         | 
| 36 | 
            +
                                 when 'last_30_days'  then 30.days.ago.to_date..tomorrow
         | 
| 37 | 
            +
                                 end
         | 
| 38 | 
            +
             | 
| 39 | 
            +
                      build_filter_interval(interval, key)
         | 
| 40 | 
            +
                    end
         | 
| 41 | 
            +
             | 
| 42 | 
            +
                    def build_filter_interval(interval, key)
         | 
| 43 | 
            +
                      raise "Not implemented!"
         | 
| 44 | 
            +
                    end
         | 
| 45 | 
            +
             | 
| 46 | 
            +
                    def build_string_conditions(key, value)
         | 
| 47 | 
            +
                      { key => value }
         | 
| 48 | 
            +
                    end
         | 
| 49 | 
            +
             | 
| 50 | 
            +
                    alias_method :build_integer_conditions, :build_string_conditions
         | 
| 51 | 
            +
                    alias_method :build_belongs_to_conditions, :build_string_conditions
         | 
| 52 | 
            +
             | 
| 53 | 
            +
                    # TODO: Detect the primary_key for this object.
         | 
| 54 | 
            +
                    def build_has_many_conditions(key, value)
         | 
| 55 | 
            +
                      ["#{key}.id = ?", value]
         | 
| 56 | 
            +
                    end
         | 
| 57 | 
            +
             | 
| 58 | 
            +
                    ##
         | 
| 59 | 
            +
                    # To build conditions we reject all those params which are not model
         | 
| 60 | 
            +
                    # fields.
         | 
| 61 | 
            +
                    #
         | 
| 62 | 
            +
                    # Note: We still want to be able to search so the search param is not
         | 
| 63 | 
            +
                    #       rejected.
         | 
| 64 | 
            +
                    #
         | 
| 65 | 
            +
                    def build_conditions(params)
         | 
| 66 | 
            +
                      Array.new.tap do |conditions|
         | 
| 67 | 
            +
                        query_params = params.dup
         | 
| 68 | 
            +
             | 
| 69 | 
            +
                        query_params.reject! do |k, v|
         | 
| 70 | 
            +
                          !model_fields.keys.include?(k.to_sym) &&
         | 
| 71 | 
            +
                          !model_relationships.keys.include?(k.to_sym) &&
         | 
| 72 | 
            +
                          !(k.to_sym == :search)
         | 
| 73 | 
            +
                        end
         | 
| 74 | 
            +
             | 
| 75 | 
            +
                        query_params.compact.each do |key, value|
         | 
| 76 | 
            +
                          filter_type = model_fields[key.to_sym] || model_relationships[key.to_sym] || key
         | 
| 77 | 
            +
                          conditions << send("build_#{filter_type}_conditions", key, value)
         | 
| 78 | 
            +
                        end
         | 
| 79 | 
            +
                      end
         | 
| 80 | 
            +
                    end
         | 
| 81 | 
            +
             | 
| 82 | 
            +
                    def build_my_joins(params)
         | 
| 83 | 
            +
                      query_params = params.dup
         | 
| 84 | 
            +
                      query_params.reject! { |k, v| !model_relationships.keys.include?(k.to_sym) }
         | 
| 85 | 
            +
                      query_params.compact.map { |k, v| k.to_sym }
         | 
| 86 | 
            +
                    end
         | 
| 87 | 
            +
             | 
| 88 | 
            +
                  end
         | 
| 89 | 
            +
                end
         | 
| 90 | 
            +
              end
         | 
| 91 | 
            +
            end
         | 
    
        data/lib/typus/orm/mongoid.rb
    CHANGED
    
    | @@ -1,4 +1,15 @@ | |
| 1 | 
            +
            begin
         | 
| 2 | 
            +
              require 'mongoid'
         | 
| 3 | 
            +
            rescue LoadError
         | 
| 4 | 
            +
            end
         | 
| 5 | 
            +
             | 
| 1 6 | 
             
            if defined?(Mongoid)
         | 
| 2 | 
            -
              require ' | 
| 7 | 
            +
              require 'typus/orm/mongoid/class_methods'
         | 
| 3 8 | 
             
              Mongoid::Document::ClassMethods.send(:include, Typus::Orm::Mongoid::ClassMethods)
         | 
| 9 | 
            +
             | 
| 10 | 
            +
              require 'typus/orm/mongoid/instance_methods'
         | 
| 11 | 
            +
              Mongoid::Document.send(:include, Typus::Orm::Mongoid::InstanceMethods)
         | 
| 12 | 
            +
             | 
| 13 | 
            +
              require 'typus/orm/mongoid/search'
         | 
| 14 | 
            +
              Mongoid::Document::ClassMethods.send(:include, Typus::Orm::Mongoid::Search)
         | 
| 4 15 | 
             
            end
         | 
| @@ -3,12 +3,66 @@ module Typus | |
| 3 3 | 
             
                module Mongoid
         | 
| 4 4 | 
             
                  module ClassMethods
         | 
| 5 5 |  | 
| 6 | 
            -
                     | 
| 6 | 
            +
                    include Typus::Orm::Base::ClassMethods
         | 
| 7 | 
            +
             | 
| 8 | 
            +
                    delegate :any?, :to => :all
         | 
| 7 9 |  | 
| 8 10 | 
             
                    def table_name
         | 
| 9 11 | 
             
                      collection_name
         | 
| 10 12 | 
             
                    end
         | 
| 11 13 |  | 
| 14 | 
            +
                    def typus_order_by(order_field = nil, sort_order = nil)
         | 
| 15 | 
            +
                      if order_field.nil? || sort_order.nil?
         | 
| 16 | 
            +
                        order_array = typus_defaults_for(:order_by).map do |field|
         | 
| 17 | 
            +
                          field.include?('-') ? [field.delete('-'), :desc] : [field, :asc]
         | 
| 18 | 
            +
                        end
         | 
| 19 | 
            +
                      else
         | 
| 20 | 
            +
                        order_array = [[order_field, sort_order.downcase.to_sym]]
         | 
| 21 | 
            +
                      end
         | 
| 22 | 
            +
                      self.order_by(order_array)
         | 
| 23 | 
            +
                    end
         | 
| 24 | 
            +
             | 
| 25 | 
            +
                    # For the moment return model fields.
         | 
| 26 | 
            +
                    def typus_fields_for(filter)
         | 
| 27 | 
            +
                      model_fields
         | 
| 28 | 
            +
                    end
         | 
| 29 | 
            +
             | 
| 30 | 
            +
                    def virtual_attribute?(field)
         | 
| 31 | 
            +
                      :virtual if virtual_fields.include?(field.to_s)
         | 
| 32 | 
            +
                    end
         | 
| 33 | 
            +
             | 
| 34 | 
            +
                    def selector_attribute?(field)
         | 
| 35 | 
            +
                      :selector if typus_field_options_for(:selectors).include?(field)
         | 
| 36 | 
            +
                    end
         | 
| 37 | 
            +
             | 
| 38 | 
            +
                    def association_attribute?(field)
         | 
| 39 | 
            +
                      reflect_on_association(field).macro if reflect_on_association(field)
         | 
| 40 | 
            +
                    end
         | 
| 41 | 
            +
             | 
| 42 | 
            +
                    #
         | 
| 43 | 
            +
                    # Model fields as an <tt>ActiveSupport::OrderedHash</tt>.
         | 
| 44 | 
            +
                    def model_fields
         | 
| 45 | 
            +
                      hash = ActiveSupport::OrderedHash.new
         | 
| 46 | 
            +
             | 
| 47 | 
            +
                      fields.each do |key, value|
         | 
| 48 | 
            +
                        hash[key.to_sym] = value.options[:type].to_s.downcase.to_sym
         | 
| 49 | 
            +
                      end
         | 
| 50 | 
            +
             | 
| 51 | 
            +
                      rejections = [:_id, :_type]
         | 
| 52 | 
            +
                      hash.reject { |k, v| rejections.include?(k) }
         | 
| 53 | 
            +
                    end
         | 
| 54 | 
            +
             | 
| 55 | 
            +
                    # Model relationships as an <tt>ActiveSupport::OrderedHash</tt>.
         | 
| 56 | 
            +
                    def model_relationships
         | 
| 57 | 
            +
                      ActiveSupport::OrderedHash.new.tap do |hash|
         | 
| 58 | 
            +
                        relations.values.map { |i| hash[i.name] = i.macro }
         | 
| 59 | 
            +
                      end
         | 
| 60 | 
            +
                    end
         | 
| 61 | 
            +
             | 
| 62 | 
            +
                    def typus_user_id?
         | 
| 63 | 
            +
                      fields.keys.include?(Typus.user_foreign_key)
         | 
| 64 | 
            +
                    end
         | 
| 65 | 
            +
             | 
| 12 66 | 
             
                  end
         | 
| 13 67 | 
             
                end
         | 
| 14 68 | 
             
              end
         | 
| @@ -0,0 +1,18 @@ | |
| 1 | 
            +
            module Typus
         | 
| 2 | 
            +
              module Orm
         | 
| 3 | 
            +
                module Mongoid
         | 
| 4 | 
            +
                  module InstanceMethods
         | 
| 5 | 
            +
             | 
| 6 | 
            +
                    def update_attributes(attributes, options ={})
         | 
| 7 | 
            +
                      super(attributes)
         | 
| 8 | 
            +
                    end
         | 
| 9 | 
            +
             | 
| 10 | 
            +
                    def toggle(attribute)
         | 
| 11 | 
            +
                      self[attribute] = !send("#{attribute}?")
         | 
| 12 | 
            +
                      self
         | 
| 13 | 
            +
                    end
         | 
| 14 | 
            +
             | 
| 15 | 
            +
                  end
         | 
| 16 | 
            +
                end
         | 
| 17 | 
            +
              end
         | 
| 18 | 
            +
            end
         | 
| @@ -0,0 +1,46 @@ | |
| 1 | 
            +
            module Typus
         | 
| 2 | 
            +
              module Orm
         | 
| 3 | 
            +
                module Mongoid
         | 
| 4 | 
            +
                  module Search
         | 
| 5 | 
            +
             | 
| 6 | 
            +
                    include Typus::Orm::Base::Search
         | 
| 7 | 
            +
             | 
| 8 | 
            +
                    def build_search_conditions(key, value)
         | 
| 9 | 
            +
                      search_fields = typus_search_fields
         | 
| 10 | 
            +
                      search_fields = search_fields.empty? ? { "name" => "@" } : search_fields
         | 
| 11 | 
            +
             | 
| 12 | 
            +
                      search_query = search_fields.map do |key, type|
         | 
| 13 | 
            +
                        related_model = self
         | 
| 14 | 
            +
             | 
| 15 | 
            +
                        split_keys = key.split('.')
         | 
| 16 | 
            +
                        split_keys[0..-2].each do |split_key|
         | 
| 17 | 
            +
                          if related_model.responds_to? :relations && related_model.relations[split_key] && related_model.relations[split_key].embeded?
         | 
| 18 | 
            +
                            related_model = related_model.relations[split_key]
         | 
| 19 | 
            +
                          else
         | 
| 20 | 
            +
                            raise "Search key '#{key}' is invalid. #{split_key} is not an embeded document" if related_model.embeded?
         | 
| 21 | 
            +
                          end
         | 
| 22 | 
            +
                        end
         | 
| 23 | 
            +
             | 
| 24 | 
            +
                        field = related_model.fields[split_keys.last]
         | 
| 25 | 
            +
                        raise "Search key '#{field.name}' is invalid." unless field
         | 
| 26 | 
            +
                        value = field.serialize(value) if field.type.ancestors.include?(Numeric)
         | 
| 27 | 
            +
             | 
| 28 | 
            +
                        {key => value}
         | 
| 29 | 
            +
                      end
         | 
| 30 | 
            +
             | 
| 31 | 
            +
                      {'$or' => search_query}
         | 
| 32 | 
            +
                    end
         | 
| 33 | 
            +
             | 
| 34 | 
            +
                    def build_filter_interval(interval, key)
         | 
| 35 | 
            +
                      {key.to_sym.gt => interval.first, key.to_sym.lt => interval.last}
         | 
| 36 | 
            +
                    end
         | 
| 37 | 
            +
             | 
| 38 | 
            +
                    # TODO: Detect the primary_key for this object.
         | 
| 39 | 
            +
                    def build_has_many_conditions(key, value)
         | 
| 40 | 
            +
                      ["#{key}.id = ?", value]
         | 
| 41 | 
            +
                    end
         | 
| 42 | 
            +
             | 
| 43 | 
            +
                  end
         | 
| 44 | 
            +
                end
         | 
| 45 | 
            +
              end
         | 
| 46 | 
            +
            end
         | 
    
        data/lib/typus/version.rb
    CHANGED
    
    
    
        data/typus.gemspec
    CHANGED
    
    | @@ -28,8 +28,8 @@ Gem::Specification.new do |s| | |
| 28 28 |  | 
| 29 29 | 
             
              s.add_dependency "bcrypt-ruby", "~> 3.0.0"
         | 
| 30 30 | 
             
              s.add_dependency "jquery-rails"
         | 
| 31 | 
            -
              s.add_dependency "kaminari"
         | 
| 32 | 
            -
              s.add_dependency "rails", "~> 3.1. | 
| 31 | 
            +
              s.add_dependency "kaminari", "~> 0.12.4"
         | 
| 32 | 
            +
              s.add_dependency "rails", "~> 3.1.3"
         | 
| 33 33 |  | 
| 34 34 | 
             
              # Development dependencies are defined in the `Gemfile`.
         | 
| 35 35 | 
             
            end
         | 
| @@ -35,7 +35,7 @@ | |
| 35 35 | 
             
            	left: 0;
         | 
| 36 36 | 
             
            	width: 40px;
         | 
| 37 37 | 
             
            	height: 480px;
         | 
| 38 | 
            -
            	background-image: url(' | 
| 38 | 
            +
            	background-image: url('<%=asset_path "fancybox.png"%>');
         | 
| 39 39 | 
             
            }
         | 
| 40 40 |  | 
| 41 41 | 
             
            #fancybox-overlay {
         | 
| @@ -99,7 +99,7 @@ | |
| 99 99 | 
             
            	right: -15px;
         | 
| 100 100 | 
             
            	width: 30px;
         | 
| 101 101 | 
             
            	height: 30px;
         | 
| 102 | 
            -
            	background: transparent url(' | 
| 102 | 
            +
            	background: transparent url('<%=asset_path "fancybox.png"%>') -40px 0px;
         | 
| 103 103 | 
             
            	cursor: pointer;
         | 
| 104 104 | 
             
            	z-index: 1103;
         | 
| 105 105 | 
             
            	display: none;
         | 
| @@ -137,7 +137,7 @@ | |
| 137 137 | 
             
            	width: 35%;
         | 
| 138 138 | 
             
            	cursor: pointer;
         | 
| 139 139 | 
             
            	outline: none;
         | 
| 140 | 
            -
            	background: transparent url(' | 
| 140 | 
            +
            	background: transparent url('<%=asset_path "blank.gif"%>');
         | 
| 141 141 | 
             
            	z-index: 1102;
         | 
| 142 142 | 
             
            	display: none;
         | 
| 143 143 | 
             
            }
         | 
| @@ -163,12 +163,12 @@ | |
| 163 163 | 
             
            }
         | 
| 164 164 |  | 
| 165 165 | 
             
            #fancybox-left-ico {
         | 
| 166 | 
            -
            	background-image: url(' | 
| 166 | 
            +
            	background-image: url('<%=asset_path "fancybox.png"%>');
         | 
| 167 167 | 
             
            	background-position: -40px -30px;
         | 
| 168 168 | 
             
            }
         | 
| 169 169 |  | 
| 170 170 | 
             
            #fancybox-right-ico {
         | 
| 171 | 
            -
            	background-image: url(' | 
| 171 | 
            +
            	background-image: url('<%=asset_path "fancybox.png"%>');
         | 
| 172 172 | 
             
            	background-position: -40px -60px;
         | 
| 173 173 | 
             
            }
         | 
| 174 174 |  | 
| @@ -199,13 +199,13 @@ | |
| 199 199 | 
             
            	top: -20px;
         | 
| 200 200 | 
             
            	left: 0;
         | 
| 201 201 | 
             
            	width: 100%;
         | 
| 202 | 
            -
            	background-image: url(' | 
| 202 | 
            +
            	background-image: url('<%=asset_path "fancybox-x.png"%>');
         | 
| 203 203 | 
             
            }
         | 
| 204 204 |  | 
| 205 205 | 
             
            #fancybox-bg-ne {
         | 
| 206 206 | 
             
            	top: -20px;
         | 
| 207 207 | 
             
            	right: -20px;
         | 
| 208 | 
            -
            	background-image: url(' | 
| 208 | 
            +
            	background-image: url('<%=asset_path "fancybox.png"%>');
         | 
| 209 209 | 
             
            	background-position: -40px -162px;
         | 
| 210 210 | 
             
            }
         | 
| 211 211 |  | 
| @@ -213,14 +213,14 @@ | |
| 213 213 | 
             
            	top: 0;
         | 
| 214 214 | 
             
            	right: -20px;
         | 
| 215 215 | 
             
            	height: 100%;
         | 
| 216 | 
            -
            	background-image: url(' | 
| 216 | 
            +
            	background-image: url('<%=asset_path "fancybox-y.png"%>');
         | 
| 217 217 | 
             
            	background-position: -20px 0px;
         | 
| 218 218 | 
             
            }
         | 
| 219 219 |  | 
| 220 220 | 
             
            #fancybox-bg-se {
         | 
| 221 221 | 
             
            	bottom: -20px;
         | 
| 222 222 | 
             
            	right: -20px;
         | 
| 223 | 
            -
            	background-image: url(' | 
| 223 | 
            +
            	background-image: url('<%=asset_path "fancybox.png"%>');
         | 
| 224 224 | 
             
            	background-position: -40px -182px; 
         | 
| 225 225 | 
             
            }
         | 
| 226 226 |  | 
| @@ -228,14 +228,14 @@ | |
| 228 228 | 
             
            	bottom: -20px;
         | 
| 229 229 | 
             
            	left: 0;
         | 
| 230 230 | 
             
            	width: 100%;
         | 
| 231 | 
            -
            	background-image: url(' | 
| 231 | 
            +
            	background-image: url('<%=asset_path "fancybox-x.png"%>');
         | 
| 232 232 | 
             
            	background-position: 0px -20px;
         | 
| 233 233 | 
             
            }
         | 
| 234 234 |  | 
| 235 235 | 
             
            #fancybox-bg-sw {
         | 
| 236 236 | 
             
            	bottom: -20px;
         | 
| 237 237 | 
             
            	left: -20px;
         | 
| 238 | 
            -
            	background-image: url(' | 
| 238 | 
            +
            	background-image: url('<%=asset_path "fancybox.png"%>');
         | 
| 239 239 | 
             
            	background-position: -40px -142px;
         | 
| 240 240 | 
             
            }
         | 
| 241 241 |  | 
| @@ -243,13 +243,13 @@ | |
| 243 243 | 
             
            	top: 0;
         | 
| 244 244 | 
             
            	left: -20px;
         | 
| 245 245 | 
             
            	height: 100%;
         | 
| 246 | 
            -
            	background-image: url(' | 
| 246 | 
            +
            	background-image: url('<%=asset_path "fancybox-y.png"%>');
         | 
| 247 247 | 
             
            }
         | 
| 248 248 |  | 
| 249 249 | 
             
            #fancybox-bg-nw {
         | 
| 250 250 | 
             
            	top: -20px;
         | 
| 251 251 | 
             
            	left: -20px;
         | 
| 252 | 
            -
            	background-image: url(' | 
| 252 | 
            +
            	background-image: url('<%=asset_path "fancybox.png"%>');
         | 
| 253 253 | 
             
            	background-position: -40px -122px;
         | 
| 254 254 | 
             
            }
         | 
| 255 255 |  | 
| @@ -282,7 +282,7 @@ | |
| 282 282 |  | 
| 283 283 | 
             
            #fancybox-title-over {
         | 
| 284 284 | 
             
            	padding: 10px;
         | 
| 285 | 
            -
            	background-image: url(' | 
| 285 | 
            +
            	background-image: url('<%=asset_path "fancy_title_over.png"%>');
         | 
| 286 286 | 
             
            	display: block;
         | 
| 287 287 | 
             
            }
         | 
| 288 288 |  | 
| @@ -306,7 +306,7 @@ | |
| 306 306 |  | 
| 307 307 | 
             
            #fancybox-title-float-left {
         | 
| 308 308 | 
             
            	padding: 0 0 0 15px;
         | 
| 309 | 
            -
            	background: url(' | 
| 309 | 
            +
            	background: url('<%=asset_path "fancybox.png"%>') -40px -90px no-repeat;
         | 
| 310 310 | 
             
            }
         | 
| 311 311 |  | 
| 312 312 | 
             
            #fancybox-title-float-main {
         | 
| @@ -314,25 +314,25 @@ | |
| 314 314 | 
             
            	line-height: 29px;
         | 
| 315 315 | 
             
            	font-weight: bold;
         | 
| 316 316 | 
             
            	padding: 0 0 3px 0;
         | 
| 317 | 
            -
            	background: url(' | 
| 317 | 
            +
            	background: url('<%=asset_path "fancybox.png"%>') 0px -40px;
         | 
| 318 318 | 
             
            }
         | 
| 319 319 |  | 
| 320 320 | 
             
            #fancybox-title-float-right {
         | 
| 321 321 | 
             
            	padding: 0 0 0 15px;
         | 
| 322 | 
            -
            	background: url(' | 
| 322 | 
            +
            	background: url('<%=asset_path "fancybox.png"%>') -55px -90px no-repeat;
         | 
| 323 323 | 
             
            }
         | 
| 324 324 |  | 
| 325 325 | 
             
            /* IE6 */
         | 
| 326 326 |  | 
| 327 | 
            -
            .fancybox-ie6 #fancybox-close { background: transparent; filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src=' | 
| 327 | 
            +
            .fancybox-ie6 #fancybox-close { background: transparent; filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src='<%=asset_path "fancy_close.png"%>', sizingMethod='scale'); }
         | 
| 328 328 |  | 
| 329 | 
            -
            .fancybox-ie6 #fancybox-left-ico { background: transparent; filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src=' | 
| 330 | 
            -
            .fancybox-ie6 #fancybox-right-ico { background: transparent; filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src=' | 
| 329 | 
            +
            .fancybox-ie6 #fancybox-left-ico { background: transparent; filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src='<%=asset_path "fancybox_nav_left.png"%>', sizingMethod='scale'); }
         | 
| 330 | 
            +
            .fancybox-ie6 #fancybox-right-ico { background: transparent; filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src='<%=asset_path "fancybox_nav_right.png"%>', sizingMethod='scale'); }
         | 
| 331 331 |  | 
| 332 | 
            -
            .fancybox-ie6 #fancybox-title-over { background: transparent; filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src=' | 
| 333 | 
            -
            .fancybox-ie6 #fancybox-title-float-left { background: transparent; filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src=' | 
| 334 | 
            -
            .fancybox-ie6 #fancybox-title-float-main { background: transparent; filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src=' | 
| 335 | 
            -
            .fancybox-ie6 #fancybox-title-float-right { background: transparent; filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src=' | 
| 332 | 
            +
            .fancybox-ie6 #fancybox-title-over { background: transparent; filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src='<%=asset_path "fancy_title_over.png"%>', sizingMethod='scale'); zoom: 1; }
         | 
| 333 | 
            +
            .fancybox-ie6 #fancybox-title-float-left { background: transparent; filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src='<%=asset_path "fancy_title_left.png"%>', sizingMethod='scale'); }
         | 
| 334 | 
            +
            .fancybox-ie6 #fancybox-title-float-main { background: transparent; filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src='<%=asset_path "fancybox_title_main.png"%>', sizingMethod='scale'); }
         | 
| 335 | 
            +
            .fancybox-ie6 #fancybox-title-float-right { background: transparent; filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src='<%=asset_path "fancybox_title_right.png"%>', sizingMethod='scale'); }
         | 
| 336 336 |  | 
| 337 337 | 
             
            .fancybox-ie6 #fancybox-bg-w, .fancybox-ie6 #fancybox-bg-e, .fancybox-ie6 #fancybox-left, .fancybox-ie6 #fancybox-right, #fancybox-hide-sel-frame {
         | 
| 338 338 | 
             
            	height: expression(this.parentNode.clientHeight + "px");
         | 
| @@ -343,17 +343,17 @@ | |
| 343 343 | 
             
            	top: expression( (-20 + (document.documentElement.clientHeight ? document.documentElement.clientHeight/2 : document.body.clientHeight/2 ) + ( ignoreMe = document.documentElement.scrollTop ? document.documentElement.scrollTop : document.body.scrollTop )) + 'px');
         | 
| 344 344 | 
             
            }
         | 
| 345 345 |  | 
| 346 | 
            -
            #fancybox-loading.fancybox-ie6 div	{ background: transparent; filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src=' | 
| 346 | 
            +
            #fancybox-loading.fancybox-ie6 div	{ background: transparent; filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src='<%=asset_path "fancy_loading.png"%>', sizingMethod='scale'); }
         | 
| 347 347 |  | 
| 348 348 | 
             
            /* IE6, IE7, IE8 */
         | 
| 349 349 |  | 
| 350 350 | 
             
            .fancybox-ie .fancybox-bg { background: transparent !important; }
         | 
| 351 351 |  | 
| 352 | 
            -
            .fancybox-ie #fancybox-bg-n { filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src=' | 
| 353 | 
            -
            .fancybox-ie #fancybox-bg-ne { filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src=' | 
| 354 | 
            -
            .fancybox-ie #fancybox-bg-e { filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src=' | 
| 355 | 
            -
            .fancybox-ie #fancybox-bg-se { filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src=' | 
| 356 | 
            -
            .fancybox-ie #fancybox-bg-s { filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src=' | 
| 357 | 
            -
            .fancybox-ie #fancybox-bg-sw { filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src=' | 
| 358 | 
            -
            .fancybox-ie #fancybox-bg-w { filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src=' | 
| 359 | 
            -
            .fancybox-ie #fancybox-bg-nw { filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src=' | 
| 352 | 
            +
            .fancybox-ie #fancybox-bg-n { filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src='<%=asset_path "fancy_shadow_n.png"%>', sizingMethod='scale'); }
         | 
| 353 | 
            +
            .fancybox-ie #fancybox-bg-ne { filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src='<%=asset_path "fancy_shadow_ne.png"%>', sizingMethod='scale'); }
         | 
| 354 | 
            +
            .fancybox-ie #fancybox-bg-e { filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src='<%=asset_path "fancy_shadow_e.png"%>', sizingMethod='scale'); }
         | 
| 355 | 
            +
            .fancybox-ie #fancybox-bg-se { filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src='<%=asset_path "fancy_shadow_se.png"%>', sizingMethod='scale'); }
         | 
| 356 | 
            +
            .fancybox-ie #fancybox-bg-s { filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src='<%=asset_path "fancy_shadow_s.png"%>', sizingMethod='scale'); }
         | 
| 357 | 
            +
            .fancybox-ie #fancybox-bg-sw { filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src='<%=asset_path "fancy_shadow_sw.png"%>', sizingMethod='scale'); }
         | 
| 358 | 
            +
            .fancybox-ie #fancybox-bg-w { filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src='<%=asset_path "fancy_shadow_w.png"%>', sizingMethod='scale'); }
         | 
| 359 | 
            +
            .fancybox-ie #fancybox-bg-nw { filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src='<%=asset_path "fancy_shadow_nw.png"%>', sizingMethod='scale'); }
         |