spiderfw 0.6.23 → 0.6.24
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 +10 -1
 - data/README.rdoc +1 -1
 - data/VERSION +1 -1
 - data/apps/config_editor/_init.rb +1 -2
 - data/apps/config_editor/controllers/config_editor_controller.rb +1 -7
 - data/apps/core/admin/controllers/admin_controller.rb +1 -1
 - data/apps/core/admin/public/css/sass/admin.css +35 -31
 - data/apps/core/admin/public/sass/admin.scss +6 -1
 - data/apps/core/components/widgets/crud/crud.shtml +2 -2
 - data/apps/core/components/widgets/table/table.rb +5 -5
 - data/apps/core/forms/tags/element_row.erb +15 -10
 - data/apps/core/forms/widgets/form/form.rb +35 -22
 - data/apps/core/forms/widgets/inputs/checkbox/checkbox.shtml +2 -2
 - data/apps/core/forms/widgets/inputs/date_time/date_time.shtml +2 -2
 - data/apps/core/forms/widgets/inputs/file_input/file_input.shtml +2 -2
 - data/apps/core/forms/widgets/inputs/html_area/html_area.shtml +2 -2
 - data/apps/core/forms/widgets/inputs/input/input.shtml +2 -2
 - data/apps/core/forms/widgets/inputs/password/password.shtml +2 -2
 - data/apps/core/forms/widgets/inputs/search_select/search_select.shtml +1 -1
 - data/apps/core/forms/widgets/inputs/select/select.shtml +2 -2
 - data/apps/core/forms/widgets/inputs/text/text.shtml +2 -2
 - data/apps/core/forms/widgets/inputs/text_area/text_area.shtml +2 -2
 - data/apps/core/forms/widgets/inputs/time_span/time_span.shtml +1 -1
 - data/blueprints/home/config.ru +8 -0
 - data/lib/spiderfw/app.rb +416 -224
 - data/lib/spiderfw/cmd/commands/app.rb +243 -239
 - data/lib/spiderfw/cmd/commands/cert.rb +421 -417
 - data/lib/spiderfw/cmd/commands/config.rb +85 -82
 - data/lib/spiderfw/cmd/commands/console.rb +64 -40
 - data/lib/spiderfw/cmd/commands/content.rb +29 -25
 - data/lib/spiderfw/cmd/commands/create.rb +58 -54
 - data/lib/spiderfw/cmd/commands/model.rb +118 -114
 - data/lib/spiderfw/cmd/commands/setup.rb +55 -51
 - data/lib/spiderfw/cmd/commands/test.rb +63 -59
 - data/lib/spiderfw/cmd/commands/webserver.rb +56 -51
 - data/lib/spiderfw/config/options/spider.rb +4 -3
 - data/lib/spiderfw/controller/controller.rb +2 -0
 - data/lib/spiderfw/controller/http_controller.rb +1 -2
 - data/lib/spiderfw/controller/mixins/static_content.rb +3 -3
 - data/lib/spiderfw/controller/mixins/visual.rb +30 -15
 - data/lib/spiderfw/controller/response.rb +84 -0
 - data/lib/spiderfw/controller/session/file_session.rb +2 -2
 - data/lib/spiderfw/http/adapters/rack.rb +12 -13
 - data/lib/spiderfw/http/server.rb +80 -46
 - data/lib/spiderfw/i18n/cldr.rb +6 -9
 - data/lib/spiderfw/model/base_model.rb +103 -23
 - data/lib/spiderfw/model/condition.rb +110 -25
 - data/lib/spiderfw/model/mappers/db_mapper.rb +14 -6
 - data/lib/spiderfw/model/mappers/mapper.rb +440 -197
 - data/lib/spiderfw/model/model.rb +105 -21
 - data/lib/spiderfw/model/model_hash.rb +9 -1
 - data/lib/spiderfw/model/query.rb +50 -9
 - data/lib/spiderfw/model/query_set.rb +211 -44
 - data/lib/spiderfw/model/request.rb +28 -21
 - data/lib/spiderfw/model/storage/base_storage.rb +125 -10
 - data/lib/spiderfw/model/storage/db/db_storage.rb +7 -4
 - data/lib/spiderfw/model/storage.rb +8 -1
 - data/lib/spiderfw/setup/spider_setup_wizard.rb +9 -7
 - data/lib/spiderfw/spider.rb +270 -43
 - data/lib/spiderfw/templates/layout.rb +9 -4
 - data/lib/spiderfw/templates/resources/sass.rb +3 -2
 - data/lib/spiderfw/templates/template.rb +1 -0
 - data/lib/spiderfw/utils/annotations.rb +3 -1
 - data/lib/spiderfw/utils/logger.rb +1 -1
 - data/lib/spiderfw/utils/monkey/symbol.rb +4 -2
 - data/lib/spiderfw/utils/shared_store/file_shared_store.rb +2 -2
 - data/lib/spiderfw/utils/thread_out.rb +3 -1
 - data/public/css/error_page.css +83 -0
 - data/public/js/error_page.js +5 -0
 - data/spider.gemspec +4 -1
 - data/templates/email/error.erb +9 -0
 - metadata +28 -12
 - data/apps/config_editor/widgets/edit_bool/edit_bool.rb +0 -8
 - data/apps/config_editor/widgets/edit_bool/edit_bool.shtml +0 -5
 
| 
         @@ -1,22 +1,35 @@ 
     | 
|
| 
       1 
1 
     | 
    
         
             
            module Spider; module Model
         
     | 
| 
       2 
2 
     | 
    
         | 
| 
      
 3 
     | 
    
         
            +
                # @abstract
         
     | 
| 
       3 
4 
     | 
    
         
             
                # The Mapper connects a BaseModel to a Storage; it fetches data from the Storage and converts it to objects,
         
     | 
| 
       4 
5 
     | 
    
         
             
                # and vice versa.
         
     | 
| 
       5 
     | 
    
         
            -
                # 
     | 
| 
       6 
     | 
    
         
            -
                #  
     | 
| 
       7 
     | 
    
         
            -
                
         
     | 
| 
      
 6 
     | 
    
         
            +
                #
         
     | 
| 
      
 7 
     | 
    
         
            +
                # Each model has one instance of the mapper, retrieved by {BaseModel.mapper}. The mapper has a pointer to
         
     | 
| 
      
 8 
     | 
    
         
            +
                # its model, and one to a {Storage} instance, which is shared between all models accessing the same storage.
         
     | 
| 
      
 9 
     | 
    
         
            +
                #
         
     | 
| 
      
 10 
     | 
    
         
            +
                # The BaseModel provides methods for interacting with the mapper; it is not usually called directly,
         
     | 
| 
      
 11 
     | 
    
         
            +
                # but it can be if needed (for example, to call the {#delete_all!} method, which is not exposed on the model).
         
     | 
| 
      
 12 
     | 
    
         
            +
                #
         
     | 
| 
      
 13 
     | 
    
         
            +
                # 
         
     | 
| 
      
 14 
     | 
    
         
            +
                # Its methods may be overridden with BaseModel.with_mapper.
         
     | 
| 
       8 
15 
     | 
    
         
             
                class Mapper
         
     | 
| 
      
 16 
     | 
    
         
            +
                    # @return [BaseModel] pointer to the model instance
         
     | 
| 
       9 
17 
     | 
    
         
             
                    attr_reader :model
         
     | 
| 
      
 18 
     | 
    
         
            +
                    # @return [Storage] pointer to the Storage instance
         
     | 
| 
       10 
19 
     | 
    
         
             
                    attr_accessor :storage
         
     | 
| 
       11 
     | 
    
         
            -
                    #  
     | 
| 
      
 20 
     | 
    
         
            +
                    # A Symbolic name for the Mapper's subclass
         
     | 
| 
      
 21 
     | 
    
         
            +
                    # @return [Symbol]
         
     | 
| 
       12 
22 
     | 
    
         
             
                    attr_reader :type
         
     | 
| 
       13 
23 
     | 
    
         | 
| 
       14 
24 
     | 
    
         
             
                    # Returns whether this Mapper can write to the storage.
         
     | 
| 
      
 25 
     | 
    
         
            +
                    # return [true]
         
     | 
| 
       15 
26 
     | 
    
         
             
                    def self.write?
         
     | 
| 
       16 
27 
     | 
    
         
             
                        true
         
     | 
| 
       17 
28 
     | 
    
         
             
                    end
         
     | 
| 
       18 
29 
     | 
    
         | 
| 
       19 
30 
     | 
    
         
             
                    # Takes a BaseModel class and a storage instance.
         
     | 
| 
      
 31 
     | 
    
         
            +
                    # @param [BaseModel] model
         
     | 
| 
      
 32 
     | 
    
         
            +
                    # @param [Storage] storage
         
     | 
| 
       20 
33 
     | 
    
         
             
                    def initialize(model, storage)
         
     | 
| 
       21 
34 
     | 
    
         
             
                        @model = model
         
     | 
| 
       22 
35 
     | 
    
         
             
                        @storage = storage
         
     | 
| 
         @@ -28,12 +41,15 @@ module Spider; module Model 
     | 
|
| 
       28 
41 
     | 
    
         | 
| 
       29 
42 
     | 
    
         
             
                    # Configuration methods
         
     | 
| 
       30 
43 
     | 
    
         | 
| 
       31 
     | 
    
         
            -
                    #  
     | 
| 
      
 44 
     | 
    
         
            +
                    # Tells to the mapper that the given elements should not be handled.
         
     | 
| 
      
 45 
     | 
    
         
            +
                    # @param [*Element] Elements which should not be mapped
         
     | 
| 
      
 46 
     | 
    
         
            +
                    # @return [void]
         
     | 
| 
       32 
47 
     | 
    
         
             
                    def no_map(*els)
         
     | 
| 
       33 
48 
     | 
    
         
             
                        els.each{ |el| @no_map_elements[el] = true }
         
     | 
| 
       34 
49 
     | 
    
         
             
                    end
         
     | 
| 
       35 
50 
     | 
    
         | 
| 
       36 
51 
     | 
    
         
             
                    # Returns whether the given element can be handled by the mapper.
         
     | 
| 
      
 52 
     | 
    
         
            +
                    # @return [bool]
         
     | 
| 
       37 
53 
     | 
    
         
             
                    def mapped?(element)
         
     | 
| 
       38 
54 
     | 
    
         
             
                        element = element.name if (element.is_a? Element)
         
     | 
| 
       39 
55 
     | 
    
         
             
                        element = @model.elements[element]
         
     | 
| 
         @@ -43,25 +59,28 @@ module Spider; module Model 
     | 
|
| 
       43 
59 
     | 
    
         
             
                        return true
         
     | 
| 
       44 
60 
     | 
    
         
             
                    end
         
     | 
| 
       45 
61 
     | 
    
         | 
| 
      
 62 
     | 
    
         
            +
                    # @param [Symbol|Element] element
         
     | 
| 
      
 63 
     | 
    
         
            +
                    # @return [bool] True if the mapper can sort by this element
         
     | 
| 
       46 
64 
     | 
    
         
             
                    def sortable?(element)
         
     | 
| 
       47 
65 
     | 
    
         
             
                        element = element.name if (element.is_a? Element)
         
     | 
| 
       48 
66 
     | 
    
         
             
                        element = @model.elements[element]
         
     | 
| 
       49 
67 
     | 
    
         
             
                        mapped?(element) || element.attributes[:sortable]
         
     | 
| 
       50 
68 
     | 
    
         
             
                    end
         
     | 
| 
       51 
69 
     | 
    
         | 
| 
      
 70 
     | 
    
         
            +
                    # Returns the base type corresponding to a type; see {Model.base_type}
         
     | 
| 
      
 71 
     | 
    
         
            +
                    # @return [Class] the base type corresponding to type
         
     | 
| 
       52 
72 
     | 
    
         
             
                    def base_type(type)
         
     | 
| 
       53 
73 
     | 
    
         
             
                        Spider::Model.base_type(type)
         
     | 
| 
       54 
74 
     | 
    
         
             
                    end
         
     | 
| 
       55 
75 
     | 
    
         | 
| 
       56 
76 
     | 
    
         
             
                    # Utility methods
         
     | 
| 
       57 
77 
     | 
    
         | 
| 
       58 
     | 
    
         
            -
                    #  
     | 
| 
       59 
     | 
    
         
            -
                     
     | 
| 
       60 
     | 
    
         
            -
             
     | 
| 
       61 
     | 
    
         
            -
                     
     | 
| 
       62 
     | 
    
         
            -
             
     | 
| 
       63 
     | 
    
         
            -
                     
     | 
| 
       64 
     | 
    
         
            -
                    def execute_action(action, object, params={}) # :nodoc:
         
     | 
| 
      
 78 
     | 
    
         
            +
                    # Executes the given UnitOfWork action.
         
     | 
| 
      
 79 
     | 
    
         
            +
                    # @param [Symbol] action
         
     | 
| 
      
 80 
     | 
    
         
            +
                    # @param [BaseModel] object
         
     | 
| 
      
 81 
     | 
    
         
            +
                    # @param [Hash] params
         
     | 
| 
      
 82 
     | 
    
         
            +
                     # @return [void]
         
     | 
| 
      
 83 
     | 
    
         
            +
                    def execute_action(action, object, params={})
         
     | 
| 
       65 
84 
     | 
    
         
             
                        case action
         
     | 
| 
       66 
85 
     | 
    
         
             
                        when :save
         
     | 
| 
       67 
86 
     | 
    
         
             
                            if params[:force] == :insert
         
     | 
| 
         @@ -80,7 +99,9 @@ module Spider; module Model 
     | 
|
| 
       80 
99 
     | 
    
         
             
                        end
         
     | 
| 
       81 
100 
     | 
    
         
             
                    end
         
     | 
| 
       82 
101 
     | 
    
         | 
| 
       83 
     | 
    
         
            -
                    # Converts hashes and arrays to QuerySets and BaseModel instances.
         
     | 
| 
      
 102 
     | 
    
         
            +
                    # Converts hashes and arrays inside an object to QuerySets and BaseModel instances.
         
     | 
| 
      
 103 
     | 
    
         
            +
                    # @param [BaseModel] obj
         
     | 
| 
      
 104 
     | 
    
         
            +
                    # @return [void]
         
     | 
| 
       84 
105 
     | 
    
         
             
                    def normalize(obj)
         
     | 
| 
       85 
106 
     | 
    
         
             
                        obj.no_autoload do
         
     | 
| 
       86 
107 
     | 
    
         
             
                            @model.elements.select{ |n, el| 
         
     | 
| 
         @@ -103,18 +124,16 @@ module Spider; module Model 
     | 
|
| 
       103 
124 
     | 
    
         
             
                    #   Info                                                    #
         
     | 
| 
       104 
125 
     | 
    
         
             
                    #############################################################
         
     | 
| 
       105 
126 
     | 
    
         | 
| 
       106 
     | 
    
         
            -
                    #  
     | 
| 
       107 
     | 
    
         
            -
                    #  
     | 
| 
      
 127 
     | 
    
         
            +
                    # @abstract
         
     | 
| 
      
 128 
     | 
    
         
            +
                    # Returns true if information to find the given element is accessible to the mapper
         
     | 
| 
      
 129 
     | 
    
         
            +
                    # (see {DbMapper#have_references?} for an implementation)
         
     | 
| 
      
 130 
     | 
    
         
            +
                    # @param [Symbol|Element] element
         
     | 
| 
      
 131 
     | 
    
         
            +
                    # @return [bool] True if the storage has a field to write the element or a reference to the element (primary keys),
         
     | 
| 
      
 132 
     | 
    
         
            +
                    #                false otherwise
         
     | 
| 
       108 
133 
     | 
    
         
             
                    def have_references?(element)
         
     | 
| 
       109 
134 
     | 
    
         
             
                        raise MapperError, "Unimplemented"
         
     | 
| 
       110 
135 
     | 
    
         
             
                    end
         
     | 
| 
       111 
136 
     | 
    
         | 
| 
       112 
     | 
    
         
            -
                    # Returns true if information to find the given element is accessible to the mapper, or to an integrated model's mapper.
         
     | 
| 
       113 
     | 
    
         
            -
                    # (see for example DbMapper#someone_have_references?)
         
     | 
| 
       114 
     | 
    
         
            -
                    def someone_have_references?(element)
         
     | 
| 
       115 
     | 
    
         
            -
                        raise MapperError, "Unimplemented"
         
     | 
| 
       116 
     | 
    
         
            -
                    end
         
     | 
| 
       117 
     | 
    
         
            -
                    
         
     | 
| 
       118 
137 
     | 
    
         | 
| 
       119 
138 
     | 
    
         
             
                    ##############################################################
         
     | 
| 
       120 
139 
     | 
    
         
             
                    #   Save (insert and update)                                 #
         
     | 
| 
         @@ -122,8 +141,12 @@ module Spider; module Model 
     | 
|
| 
       122 
141 
     | 
    
         | 
| 
       123 
142 
     | 
    
         
             
                    # This method is called before a save operation, normalizing and preparing the object.
         
     | 
| 
       124 
143 
     | 
    
         
             
                    # 'mode' can be :insert or :update.
         
     | 
| 
       125 
     | 
    
         
            -
                    # This method is well suited for being overridden 
     | 
| 
       126 
     | 
    
         
            -
                    #  
     | 
| 
      
 144 
     | 
    
         
            +
                    # This method is well suited for being overridden (with {BaseModel.with_mapper}, 
         
     | 
| 
      
 145 
     | 
    
         
            +
                    # to add custom preprocessing of the object; just
         
     | 
| 
      
 146 
     | 
    
         
            +
                    # remember to call super, or use #before_insert and #before_update instead.
         
     | 
| 
      
 147 
     | 
    
         
            +
                    # @param [BaseModel] obj
         
     | 
| 
      
 148 
     | 
    
         
            +
                    # @param [Symbol] mode :insert or :update
         
     | 
| 
      
 149 
     | 
    
         
            +
                    # @return [void]
         
     | 
| 
       127 
150 
     | 
    
         
             
                    def before_save(obj, mode)
         
     | 
| 
       128 
151 
     | 
    
         
             
                        obj.trigger(:before_save, mode)
         
     | 
| 
       129 
152 
     | 
    
         
             
                        normalize(obj)
         
     | 
| 
         @@ -166,6 +189,10 @@ module Spider; module Model 
     | 
|
| 
       166 
189 
     | 
    
         
             
                        end
         
     | 
| 
       167 
190 
     | 
    
         
             
                    end
         
     | 
| 
       168 
191 
     | 
    
         | 
| 
      
 192 
     | 
    
         
            +
                    # Saves models that obj's model extends (see {BaseModel.extend_model})
         
     | 
| 
      
 193 
     | 
    
         
            +
                    # @param [BaseModel] obj
         
     | 
| 
      
 194 
     | 
    
         
            +
                    # @param [Symbol] mode
         
     | 
| 
      
 195 
     | 
    
         
            +
                    # @return [void]
         
     | 
| 
       169 
196 
     | 
    
         
             
                    def save_extended_models(obj, mode)
         
     | 
| 
       170 
197 
     | 
    
         
             
                        if @model.extended_models
         
     | 
| 
       171 
198 
     | 
    
         
             
                            @model.extended_models.each do |m, el|
         
     | 
| 
         @@ -179,6 +206,10 @@ module Spider; module Model 
     | 
|
| 
       179 
206 
     | 
    
         
             
                        end
         
     | 
| 
       180 
207 
     | 
    
         
             
                    end
         
     | 
| 
       181 
208 
     | 
    
         | 
| 
      
 209 
     | 
    
         
            +
                    # Saves objects integrated in obj (see {BaseModel.integrate})
         
     | 
| 
      
 210 
     | 
    
         
            +
                    # @param [BaseModel] obj
         
     | 
| 
      
 211 
     | 
    
         
            +
                    # @param [Symbol] mode
         
     | 
| 
      
 212 
     | 
    
         
            +
                    # @return [void]
         
     | 
| 
       182 
213 
     | 
    
         
             
                    def save_integrated(obj, mode)
         
     | 
| 
       183 
214 
     | 
    
         
             
                        @model.elements_array.select{ |el| !el.integrated? && el.attributes[:integrated_model] && !el.attributes[:extended_model] }.each do |el|
         
     | 
| 
       184 
215 
     | 
    
         
             
                            sub_obj = obj.get(el)
         
     | 
| 
         @@ -187,44 +218,71 @@ module Spider; module Model 
     | 
|
| 
       187 
218 
     | 
    
         
             
                    end
         
     | 
| 
       188 
219 
     | 
    
         | 
| 
       189 
220 
     | 
    
         
             
                    # Hook to provide custom preprocessing. The default implementation does nothing.
         
     | 
| 
      
 221 
     | 
    
         
            +
                    # 
         
     | 
| 
      
 222 
     | 
    
         
            +
                    # If needed, override using {BaseModel.with_mapper}
         
     | 
| 
      
 223 
     | 
    
         
            +
                    # @param [BaseModel] obj
         
     | 
| 
      
 224 
     | 
    
         
            +
                    # @return [void]
         
     | 
| 
       190 
225 
     | 
    
         
             
                    def before_insert(obj)
         
     | 
| 
       191 
226 
     | 
    
         
             
                    end
         
     | 
| 
       192 
227 
     | 
    
         | 
| 
       193 
228 
     | 
    
         
             
                    # Hook to provide custom preprocessing. The default implementation does nothing.
         
     | 
| 
      
 229 
     | 
    
         
            +
                    # 
         
     | 
| 
      
 230 
     | 
    
         
            +
                    # If needed, override using {BaseModel.with_mapper}
         
     | 
| 
      
 231 
     | 
    
         
            +
                    # @param [BaseModel] obj
         
     | 
| 
      
 232 
     | 
    
         
            +
                    # @return [void]
         
     | 
| 
       194 
233 
     | 
    
         
             
                    def before_update(obj)
         
     | 
| 
       195 
234 
     | 
    
         
             
                    end
         
     | 
| 
       196 
235 
     | 
    
         | 
| 
       197 
236 
     | 
    
         
             
                    # Hook to provide custom preprocessing. Will be passed a QuerySet. The default implementation does nothing.
         
     | 
| 
      
 237 
     | 
    
         
            +
                    # 
         
     | 
| 
      
 238 
     | 
    
         
            +
                    # If needed, override using {BaseModel.with_mapper}
         
     | 
| 
      
 239 
     | 
    
         
            +
                    # @param [QuerySet] objects
         
     | 
| 
      
 240 
     | 
    
         
            +
                    # @return [void]
         
     | 
| 
       198 
241 
     | 
    
         
             
                    def before_delete(objects)
         
     | 
| 
       199 
242 
     | 
    
         
             
                    end
         
     | 
| 
       200 
243 
     | 
    
         | 
| 
       201 
244 
     | 
    
         
             
                    # Called after a succesful save. 'mode' can be :insert or :update.
         
     | 
| 
      
 245 
     | 
    
         
            +
                    #
         
     | 
| 
      
 246 
     | 
    
         
            +
                    # If needed, override using {BaseModel.with_mapper}; but make sure to call super, since this method's
         
     | 
| 
      
 247 
     | 
    
         
            +
                    # implementation is not empty.
         
     | 
| 
      
 248 
     | 
    
         
            +
                    # Otherwise, override {#save_done}
         
     | 
| 
      
 249 
     | 
    
         
            +
                    # @param [BaseModel] obj
         
     | 
| 
      
 250 
     | 
    
         
            +
                    # @param [Symbol] mode :insert or :update
         
     | 
| 
      
 251 
     | 
    
         
            +
                    # @return [void]
         
     | 
| 
       202 
252 
     | 
    
         
             
                    def after_save(obj, mode)
         
     | 
| 
       203 
253 
     | 
    
         
             
                        obj.reset_modified_elements
         
     | 
| 
       204 
254 
     | 
    
         
             
                        save_associations(obj, mode)
         
     | 
| 
       205 
255 
     | 
    
         | 
| 
       206 
256 
     | 
    
         
             
                    end
         
     | 
| 
       207 
257 
     | 
    
         | 
| 
       208 
     | 
    
         
            -
                    # Hook called after a succesful save 
     | 
| 
      
 258 
     | 
    
         
            +
                    # Hook called after a succesful save, when the object is not in save mode (see {BaseModel#save_mode}) anymore.
         
     | 
| 
      
 259 
     | 
    
         
            +
                    # 
         
     | 
| 
      
 260 
     | 
    
         
            +
                    # If needed, override using {BaseModel.with_mapper}
         
     | 
| 
      
 261 
     | 
    
         
            +
                    # @param [BaseModel] obj
         
     | 
| 
      
 262 
     | 
    
         
            +
                    # @param [Symbol] mode :insert or :update
         
     | 
| 
      
 263 
     | 
    
         
            +
                    # @return [void]
         
     | 
| 
       209 
264 
     | 
    
         
             
                    def save_done(obj, mode)
         
     | 
| 
       210 
265 
     | 
    
         
             
                    end
         
     | 
| 
       211 
266 
     | 
    
         | 
| 
       212 
267 
     | 
    
         
             
                    # Hook to provide custom preprocessing. Will be passed a QuerySet. The default implementation does nothing.
         
     | 
| 
      
 268 
     | 
    
         
            +
                    #
         
     | 
| 
      
 269 
     | 
    
         
            +
                    # If needed, override using {BaseModel.with_mapper}
         
     | 
| 
      
 270 
     | 
    
         
            +
                    # @param [QuerySet] objects
         
     | 
| 
      
 271 
     | 
    
         
            +
                    # @return [void]
         
     | 
| 
       213 
272 
     | 
    
         
             
                    def after_delete(objects)
         
     | 
| 
       214 
273 
     | 
    
         
             
                    end
         
     | 
| 
       215 
274 
     | 
    
         | 
| 
       216 
275 
     | 
    
         
             
                    # Saves the object to the storage.
         
     | 
| 
      
 276 
     | 
    
         
            +
                    # @param [BaseModel] obj
         
     | 
| 
      
 277 
     | 
    
         
            +
                    # @param [Model::Request] request Save only elements in the fiven request.
         
     | 
| 
      
 278 
     | 
    
         
            +
                    # @return [true]
         
     | 
| 
       217 
279 
     | 
    
         
             
                    def save(obj, request=nil)
         
     | 
| 
       218 
280 
     | 
    
         
             
                        prev_autoload = obj.autoload?
         
     | 
| 
       219 
281 
     | 
    
         
             
                        obj.save_mode
         
     | 
| 
       220 
282 
     | 
    
         
             
                        storage.in_transaction
         
     | 
| 
       221 
283 
     | 
    
         
             
                        save_mode = determine_save_mode(obj)
         
     | 
| 
       222 
284 
     | 
    
         
             
                        before_save(obj, save_mode)
         
     | 
| 
       223 
     | 
    
         
            -
                         
     | 
| 
       224 
     | 
    
         
            -
                        #     obj.get(el).save if obj.element_modified?(el)
         
     | 
| 
       225 
     | 
    
         
            -
                        # end
         
     | 
| 
       226 
     | 
    
         
            -
                        
         
     | 
| 
       227 
     | 
    
         
            -
                        if (save_mode == :update)
         
     | 
| 
      
 285 
     | 
    
         
            +
                        if save_mode == :update
         
     | 
| 
       228 
286 
     | 
    
         
             
                            do_update(obj)
         
     | 
| 
       229 
287 
     | 
    
         
             
                        else
         
     | 
| 
       230 
288 
     | 
    
         
             
                            do_insert(obj)
         
     | 
| 
         @@ -241,6 +299,9 @@ module Spider; module Model 
     | 
|
| 
       241 
299 
     | 
    
         
             
                        true
         
     | 
| 
       242 
300 
     | 
    
         
             
                    end
         
     | 
| 
       243 
301 
     | 
    
         | 
| 
      
 302 
     | 
    
         
            +
                    # Determines whether the object needs to be inserted or updated.
         
     | 
| 
      
 303 
     | 
    
         
            +
                    # @param [BaseModel] obj
         
     | 
| 
      
 304 
     | 
    
         
            +
                    # @return [Symbol] :insert or :update
         
     | 
| 
       244 
305 
     | 
    
         
             
                    def determine_save_mode(obj)
         
     | 
| 
       245 
306 
     | 
    
         
             
                        if @model.extended_models && !@model.extended_models.empty?
         
     | 
| 
       246 
307 
     | 
    
         
             
                            is_insert = false
         
     | 
| 
         @@ -263,6 +324,8 @@ module Spider; module Model 
     | 
|
| 
       263 
324 
     | 
    
         | 
| 
       264 
325 
     | 
    
         | 
| 
       265 
326 
     | 
    
         
             
                    # Elements that are associated to this one externally.
         
     | 
| 
      
 327 
     | 
    
         
            +
                    # @return [Array] An Array of elements for which the storage does not hold keys (see {#have_references?}),
         
     | 
| 
      
 328 
     | 
    
         
            +
                    #                 and which must be associated through other ways
         
     | 
| 
       266 
329 
     | 
    
         
             
                    def association_elements
         
     | 
| 
       267 
330 
     | 
    
         
             
                        return [] if Spider::Model.unit_of_work_running?
         
     | 
| 
       268 
331 
     | 
    
         
             
                        els = @model.elements_array.select{ |el| 
         
     | 
| 
         @@ -271,7 +334,8 @@ module Spider; module Model 
     | 
|
| 
       271 
334 
     | 
    
         
             
                        els
         
     | 
| 
       272 
335 
     | 
    
         
             
                    end
         
     | 
| 
       273 
336 
     | 
    
         | 
| 
       274 
     | 
    
         
            -
                    # Saves  
     | 
| 
      
 337 
     | 
    
         
            +
                    # Saves externally associated objects (the ones corresponding to elements returned by #association_elements)
         
     | 
| 
      
 338 
     | 
    
         
            +
                    # @return [void]
         
     | 
| 
       275 
339 
     | 
    
         
             
                    def save_associations(obj, mode)
         
     | 
| 
       276 
340 
     | 
    
         
             
                        association_elements.select{ |el| obj.element_has_value?(el) }.each do |el|
         
     | 
| 
       277 
341 
     | 
    
         
             
                            save_element_associations(obj, el, mode)
         
     | 
| 
         @@ -279,6 +343,10 @@ module Spider; module Model 
     | 
|
| 
       279 
343 
     | 
    
         
             
                    end
         
     | 
| 
       280 
344 
     | 
    
         | 
| 
       281 
345 
     | 
    
         
             
                    # Deletes all associations from the given object to the element.
         
     | 
| 
      
 346 
     | 
    
         
            +
                    # @param [BaseModel] obj
         
     | 
| 
      
 347 
     | 
    
         
            +
                    # @param [Element] element
         
     | 
| 
      
 348 
     | 
    
         
            +
                    # @param [BaseModel] associated The currently associated objects
         
     | 
| 
      
 349 
     | 
    
         
            +
                    # @return [void]
         
     | 
| 
       282 
350 
     | 
    
         
             
                    def delete_element_associations(obj, element, associated=nil)
         
     | 
| 
       283 
351 
     | 
    
         
             
                        if element.attributes[:junction]
         
     | 
| 
       284 
352 
     | 
    
         
             
                            condition = {element.attributes[:reverse] => obj.primary_keys}
         
     | 
| 
         @@ -307,6 +375,10 @@ module Spider; module Model 
     | 
|
| 
       307 
375 
     | 
    
         
             
                    end
         
     | 
| 
       308 
376 
     | 
    
         | 
| 
       309 
377 
     | 
    
         
             
                    # Saves the associations from the given object to the element.
         
     | 
| 
      
 378 
     | 
    
         
            +
                    # @param [BaseModel] obj
         
     | 
| 
      
 379 
     | 
    
         
            +
                    # @param [Element] element
         
     | 
| 
      
 380 
     | 
    
         
            +
                    # @param [Symbol] mode :insert or :update
         
     | 
| 
      
 381 
     | 
    
         
            +
                    # @return [void]
         
     | 
| 
       310 
382 
     | 
    
         
             
                    def save_element_associations(obj, element, mode)
         
     | 
| 
       311 
383 
     | 
    
         
             
                        our_element = element.attributes[:reverse]
         
     | 
| 
       312 
384 
     | 
    
         
             
                        val = obj.get(element)
         
     | 
| 
         @@ -380,6 +452,8 @@ module Spider; module Model 
     | 
|
| 
       380 
452 
     | 
    
         
             
                    end
         
     | 
| 
       381 
453 
     | 
    
         | 
| 
       382 
454 
     | 
    
         
             
                    # Saves the given object and all objects reachable from it.
         
     | 
| 
      
 455 
     | 
    
         
            +
                    # @param [BaseModel] root The root object
         
     | 
| 
      
 456 
     | 
    
         
            +
                    # @return [void]
         
     | 
| 
       383 
457 
     | 
    
         
             
                    def save_all(root)
         
     | 
| 
       384 
458 
     | 
    
         
             
                        UnitOfWork.new do |uow|
         
     | 
| 
       385 
459 
     | 
    
         
             
                            uow.add(root)
         
     | 
| 
         @@ -388,6 +462,8 @@ module Spider; module Model 
     | 
|
| 
       388 
462 
     | 
    
         
             
                    end
         
     | 
| 
       389 
463 
     | 
    
         | 
| 
       390 
464 
     | 
    
         
             
                    # Inserts the object in the storage.
         
     | 
| 
      
 465 
     | 
    
         
            +
                    # @param [BaseModel] obj
         
     | 
| 
      
 466 
     | 
    
         
            +
                    # @return [void]
         
     | 
| 
       391 
467 
     | 
    
         
             
                    def insert(obj)
         
     | 
| 
       392 
468 
     | 
    
         
             
                        prev_autoload = obj.save_mode()
         
     | 
| 
       393 
469 
     | 
    
         
             
                        storage.in_transaction
         
     | 
| 
         @@ -399,6 +475,8 @@ module Spider; module Model 
     | 
|
| 
       399 
475 
     | 
    
         
             
                    end
         
     | 
| 
       400 
476 
     | 
    
         | 
| 
       401 
477 
     | 
    
         
             
                    # Updates the object in the storage.
         
     | 
| 
      
 478 
     | 
    
         
            +
                    # @param [BaseModel] obj
         
     | 
| 
      
 479 
     | 
    
         
            +
                    # @return [void]
         
     | 
| 
       402 
480 
     | 
    
         
             
                    def update(obj)
         
     | 
| 
       403 
481 
     | 
    
         
             
                        prev_autoload = obj.save_mode()
         
     | 
| 
       404 
482 
     | 
    
         
             
                        storage.in_transaction
         
     | 
| 
         @@ -409,15 +487,23 @@ module Spider; module Model 
     | 
|
| 
       409 
487 
     | 
    
         
             
                        obj.autoload = prev_autoload
         
     | 
| 
       410 
488 
     | 
    
         
             
                    end
         
     | 
| 
       411 
489 
     | 
    
         | 
| 
       412 
     | 
    
         
            -
                    #  
     | 
| 
       413 
     | 
    
         
            -
                     
     | 
| 
      
 490 
     | 
    
         
            +
                    # @abstract
         
     | 
| 
      
 491 
     | 
    
         
            +
                    # Executes a mass update for given condition.
         
     | 
| 
      
 492 
     | 
    
         
            +
                    # @param [Hash] values
         
     | 
| 
      
 493 
     | 
    
         
            +
                    # @param [Condition] condition
         
     | 
| 
      
 494 
     | 
    
         
            +
                    # @return [nil]
         
     | 
| 
      
 495 
     | 
    
         
            +
                    def bulk_update(values, conditon)
         
     | 
| 
       414 
496 
     | 
    
         
             
                    end
         
     | 
| 
       415 
497 
     | 
    
         | 
| 
       416 
498 
     | 
    
         
             
                    # Deletes an object, or objects according to a condition.
         
     | 
| 
       417 
499 
     | 
    
         
             
                    # Will not delete with null condition (i.e. all objects) unless force is true
         
     | 
| 
       418 
     | 
    
         
            -
                    # 
     | 
| 
       419 
     | 
    
         
            -
                    #  
     | 
| 
       420 
     | 
    
         
            -
                    #  
     | 
| 
      
 500 
     | 
    
         
            +
                    #
         
     | 
| 
      
 501 
     | 
    
         
            +
                    # @param [BaseModel|Condition] obj_or_condition
         
     | 
| 
      
 502 
     | 
    
         
            +
                    # @param [bool] force
         
     | 
| 
      
 503 
     | 
    
         
            +
                    # @param [Hash] options Available options:
         
     | 
| 
      
 504 
     | 
    
         
            +
                    #                       * :keep_single_reverse: don't delete associations that have a single reverse.
         
     | 
| 
      
 505 
     | 
    
         
            +
                    #                         Useful when an object will be re-inserted with the same keys.
         
     | 
| 
      
 506 
     | 
    
         
            +
                    # @return [void]
         
     | 
| 
       421 
507 
     | 
    
         
             
                    def delete(obj_or_condition, force=false, options={})
         
     | 
| 
       422 
508 
     | 
    
         | 
| 
       423 
509 
     | 
    
         
             
                        def prepare_delete_condition(obj)
         
     | 
| 
         @@ -484,56 +570,42 @@ module Spider; module Model 
     | 
|
| 
       484 
570 
     | 
    
         
             
                    end
         
     | 
| 
       485 
571 
     | 
    
         | 
| 
       486 
572 
     | 
    
         
             
                    # Deletes all objects from the storage.
         
     | 
| 
      
 573 
     | 
    
         
            +
                    # @return [void]
         
     | 
| 
       487 
574 
     | 
    
         
             
                    def delete_all!
         
     | 
| 
       488 
575 
     | 
    
         
             
                        all = @model.all
         
     | 
| 
       489 
576 
     | 
    
         
             
                        #all.fetch_window = 100
         
     | 
| 
       490 
577 
     | 
    
         
             
                        delete(all, true)
         
     | 
| 
       491 
578 
     | 
    
         
             
                    end
         
     | 
| 
       492 
579 
     | 
    
         | 
| 
       493 
     | 
    
         
            -
             
     | 
| 
       494 
     | 
    
         
            -
                        raise MapperError, "Unimplemented"
         
     | 
| 
       495 
     | 
    
         
            -
                    end
         
     | 
| 
       496 
     | 
    
         
            -
                    
         
     | 
| 
       497 
     | 
    
         
            -
                    # Actual interaction with the storage. May be implemented by subclasses.
         
     | 
| 
       498 
     | 
    
         
            -
                    def do_delete(obj, force=false)
         
     | 
| 
       499 
     | 
    
         
            -
                        raise MapperError, "Unimplemented"
         
     | 
| 
       500 
     | 
    
         
            -
                    end
         
     | 
| 
       501 
     | 
    
         
            -
                    
         
     | 
| 
       502 
     | 
    
         
            -
                    # Actual interaction with the storage. May be implemented by subclasses.
         
     | 
| 
       503 
     | 
    
         
            -
                    def do_insert(obj)
         
     | 
| 
       504 
     | 
    
         
            -
                        raise MapperError, "Unimplemented"
         
     | 
| 
       505 
     | 
    
         
            -
                    end
         
     | 
| 
       506 
     | 
    
         
            -
                    
         
     | 
| 
       507 
     | 
    
         
            -
                    # Actual interaction with the storage. May be implemented by subclasses.
         
     | 
| 
       508 
     | 
    
         
            -
                    def do_update(obj)
         
     | 
| 
       509 
     | 
    
         
            -
                        raise MapperError, "Unimplemented"
         
     | 
| 
       510 
     | 
    
         
            -
                    end
         
     | 
| 
       511 
     | 
    
         
            -
                    
         
     | 
| 
       512 
     | 
    
         
            -
                    # Actual interaction with the storage. May be implemented by subclasses.
         
     | 
| 
       513 
     | 
    
         
            -
                    def lock(obj=nil, mode=:exclusive)
         
     | 
| 
       514 
     | 
    
         
            -
                        raise MapperError, "Unimplemented"
         
     | 
| 
       515 
     | 
    
         
            -
                    end
         
     | 
| 
       516 
     | 
    
         
            -
                    
         
     | 
| 
       517 
     | 
    
         
            -
                    # Actual interaction with the storage. May be implemented by subclasses.
         
     | 
| 
       518 
     | 
    
         
            -
                    def sequence_next(name)
         
     | 
| 
       519 
     | 
    
         
            -
                        raise MapperError, "Unimplemented"
         
     | 
| 
       520 
     | 
    
         
            -
                    end
         
     | 
| 
      
 580 
     | 
    
         
            +
             
     | 
| 
       521 
581 
     | 
    
         | 
| 
       522 
582 
     | 
    
         
             
                    ##############################################################
         
     | 
| 
       523 
583 
     | 
    
         
             
                    #   Load (and find)                                          #
         
     | 
| 
       524 
584 
     | 
    
         
             
                    ##############################################################        
         
     | 
| 
       525 
585 
     | 
    
         | 
| 
       526 
586 
     | 
    
         
             
                    # Loads an element. Other elements may be loaded as well, according to lazy groups.
         
     | 
| 
      
 587 
     | 
    
         
            +
                    # @param [QuerySet] objects Objects for which to load given element
         
     | 
| 
      
 588 
     | 
    
         
            +
                    # @param [Element] element
         
     | 
| 
      
 589 
     | 
    
         
            +
                    # @return [QuerySet]
         
     | 
| 
       527 
590 
     | 
    
         
             
                    def load_element(objects, element)
         
     | 
| 
       528 
591 
     | 
    
         
             
                        load(objects, Query.new(nil, [element.name]))
         
     | 
| 
       529 
592 
     | 
    
         
             
                    end
         
     | 
| 
       530 
593 
     | 
    
         | 
| 
       531 
594 
     | 
    
         
             
                    # Loads only the given element, ignoring lazy groups.
         
     | 
| 
      
 595 
     | 
    
         
            +
                    # @param [QuerySet] objects Objects for which to load given element
         
     | 
| 
      
 596 
     | 
    
         
            +
                    # @param [Element] element
         
     | 
| 
      
 597 
     | 
    
         
            +
                    # @return [QuerySet]
         
     | 
| 
       532 
598 
     | 
    
         
             
                    def load_element!(objects, element)
         
     | 
| 
       533 
599 
     | 
    
         
             
                        load(objects, Query.new(nil, [element.name]), :no_expand_request => true)
         
     | 
| 
       534 
600 
     | 
    
         
             
                    end
         
     | 
| 
       535 
601 
     | 
    
         | 
| 
       536 
602 
     | 
    
         
             
                    # Loads elements of given objects according to query.request.
         
     | 
| 
      
 603 
     | 
    
         
            +
                    #
         
     | 
| 
      
 604 
     | 
    
         
            +
                    # See also {#find} 
         
     | 
| 
      
 605 
     | 
    
         
            +
                    # @param [QuerySet] objects Objects to expand
         
     | 
| 
      
 606 
     | 
    
         
            +
                    # @param [Query] query
         
     | 
| 
      
 607 
     | 
    
         
            +
                    # @param [Hash] options
         
     | 
| 
      
 608 
     | 
    
         
            +
                    # @return [QuerySet]
         
     | 
| 
       537 
609 
     | 
    
         
             
                    def load(objects, query, options={})
         
     | 
| 
       538 
610 
     | 
    
         
             
                        objects = queryset_siblings(objects) unless objects.is_a?(QuerySet)
         
     | 
| 
       539 
611 
     | 
    
         
             
                        request = query.request
         
     | 
| 
         @@ -545,6 +617,12 @@ module Spider; module Model 
     | 
|
| 
       545 
617 
     | 
    
         
             
                    end
         
     | 
| 
       546 
618 
     | 
    
         | 
| 
       547 
619 
     | 
    
         
             
                    # Finds objects according to a query, merging the results into a query_set if given.
         
     | 
| 
      
 620 
     | 
    
         
            +
                    # 
         
     | 
| 
      
 621 
     | 
    
         
            +
                    # @param [Query] query
         
     | 
| 
      
 622 
     | 
    
         
            +
                    # @param [QuerySet] query_set QuerySet to merge results into, if given
         
     | 
| 
      
 623 
     | 
    
         
            +
                    # @param [Hash] options Options can be:
         
     | 
| 
      
 624 
     | 
    
         
            +
                    #                       * :no_expand_request: don't expand request using lazy loading groups
         
     | 
| 
      
 625 
     | 
    
         
            +
                    # @return [QuerySet]
         
     | 
| 
       548 
626 
     | 
    
         
             
                    def find(query, query_set=nil, options={})
         
     | 
| 
       549 
627 
     | 
    
         
             
                        set = nil
         
     | 
| 
       550 
628 
     | 
    
         
             
                        Spider::Model.with_identity_mapper do |im|
         
     | 
| 
         @@ -621,9 +699,166 @@ module Spider; module Model 
     | 
|
| 
       621 
699 
     | 
    
         
             
                        end
         
     | 
| 
       622 
700 
     | 
    
         
             
                        return set
         
     | 
| 
       623 
701 
     | 
    
         
             
                    end
         
     | 
| 
      
 702 
     | 
    
         
            +
             
     | 
| 
      
 703 
     | 
    
         
            +
                    # Does a count query on the storage for given condition
         
     | 
| 
      
 704 
     | 
    
         
            +
                    # @param [Condition]
         
     | 
| 
      
 705 
     | 
    
         
            +
                    # @return [Fixnum]
         
     | 
| 
      
 706 
     | 
    
         
            +
                    def count(condition)
         
     | 
| 
      
 707 
     | 
    
         
            +
                        query = Query.new(condition)
         
     | 
| 
      
 708 
     | 
    
         
            +
                        result = fetch(query)
         
     | 
| 
      
 709 
     | 
    
         
            +
                        return result.length
         
     | 
| 
      
 710 
     | 
    
         
            +
                    end
         
     | 
| 
       624 
711 
     | 
    
         | 
| 
      
 712 
     | 
    
         
            +
             
         
     | 
| 
      
 713 
     | 
    
         
            +
                    
         
     | 
| 
      
 714 
     | 
    
         
            +
                    # Returns the siblings, if any, of the object, in its ancestor QuerySet.
         
     | 
| 
      
 715 
     | 
    
         
            +
                    # 
         
     | 
| 
      
 716 
     | 
    
         
            +
                    # Siblings are objects in the same branch of the object tree.
         
     | 
| 
      
 717 
     | 
    
         
            +
                    # 
         
     | 
| 
      
 718 
     | 
    
         
            +
                    # This method is used to load related data, avoiding N+1 queries
         
     | 
| 
      
 719 
     | 
    
         
            +
                    # @param [BaseModel|QuerySet] obj
         
     | 
| 
      
 720 
     | 
    
         
            +
                    # @return [QuerySet]
         
     | 
| 
      
 721 
     | 
    
         
            +
                    def queryset_siblings(obj)
         
     | 
| 
      
 722 
     | 
    
         
            +
                        return QuerySet.new(@model, obj) unless obj._parent
         
     | 
| 
      
 723 
     | 
    
         
            +
                        orig_obj = obj
         
     | 
| 
      
 724 
     | 
    
         
            +
                        path = []
         
     | 
| 
      
 725 
     | 
    
         
            +
                        seen = {obj => true}
         
     | 
| 
      
 726 
     | 
    
         
            +
                        while (obj._parent && !seen[obj._parent])
         
     | 
| 
      
 727 
     | 
    
         
            +
                            path.unshift(obj._parent_element) if (obj._parent_element) # otherwise it's a query set
         
     | 
| 
      
 728 
     | 
    
         
            +
                            obj = obj._parent
         
     | 
| 
      
 729 
     | 
    
         
            +
                            seen[obj] = true
         
     | 
| 
      
 730 
     | 
    
         
            +
                        end
         
     | 
| 
      
 731 
     | 
    
         
            +
                        res = path.empty? ? obj : obj.all_children(path)
         
     | 
| 
      
 732 
     | 
    
         
            +
                        raise RuntimeError, "Broken object path" if (obj && !path.empty? &&  res.length < 1)
         
     | 
| 
      
 733 
     | 
    
         
            +
                        res = QuerySet.new(@model, res) unless res.is_a?(QuerySet)
         
     | 
| 
      
 734 
     | 
    
         
            +
                        res = res.select{ |obj| obj.primary_keys_set? }
         
     | 
| 
      
 735 
     | 
    
         
            +
                        return res
         
     | 
| 
      
 736 
     | 
    
         
            +
                    end
         
     | 
| 
       625 
737 
     | 
    
         | 
| 
       626 
     | 
    
         
            -
                     
     | 
| 
      
 738 
     | 
    
         
            +
                    # Prepares a value going to be bound to an insert or update statement
         
     | 
| 
      
 739 
     | 
    
         
            +
                    # @param [Class] type Value's type
         
     | 
| 
      
 740 
     | 
    
         
            +
                    # @param [Object] value
         
     | 
| 
      
 741 
     | 
    
         
            +
                    # @param [Symbol] save_mode :insert, :update, or generically :save
         
     | 
| 
      
 742 
     | 
    
         
            +
                    # @return [Object]
         
     | 
| 
      
 743 
     | 
    
         
            +
                     def map_save_value(type, value, save_mode=:save)
         
     | 
| 
      
 744 
     | 
    
         
            +
                         value = map_value(type, value, :save)
         
     | 
| 
      
 745 
     | 
    
         
            +
                         return @storage.value_for_save(Model.simplify_type(type), value, save_mode)
         
     | 
| 
      
 746 
     | 
    
         
            +
                     end
         
     | 
| 
      
 747 
     | 
    
         
            +
             
     | 
| 
      
 748 
     | 
    
         
            +
                    # Prepares a value for a condition.
         
     | 
| 
      
 749 
     | 
    
         
            +
                    # @param [Class] type Value's type
         
     | 
| 
      
 750 
     | 
    
         
            +
                    # @param [Object] value
         
     | 
| 
      
 751 
     | 
    
         
            +
                    # @param [Symbol] save_mode :insert, :update, or generically :save
         
     | 
| 
      
 752 
     | 
    
         
            +
                    # @return [Object]
         
     | 
| 
      
 753 
     | 
    
         
            +
                    def map_condition_value(type, value)
         
     | 
| 
      
 754 
     | 
    
         
            +
                        if value.is_a?(Range)
         
     | 
| 
      
 755 
     | 
    
         
            +
                            return Range.new(map_condition_value(type, value.first), map_condition_value(type, value.last))
         
     | 
| 
      
 756 
     | 
    
         
            +
                        end
         
     | 
| 
      
 757 
     | 
    
         
            +
                        return value if ( type.class == Class && type.subclass_of?(Spider::Model::BaseModel) )
         
     | 
| 
      
 758 
     | 
    
         
            +
                        value = map_value(type, value, :condition)
         
     | 
| 
      
 759 
     | 
    
         
            +
                        return @storage.value_for_condition(Model.simplify_type(type), value)
         
     | 
| 
      
 760 
     | 
    
         
            +
                    end
         
     | 
| 
      
 761 
     | 
    
         
            +
             
     | 
| 
      
 762 
     | 
    
         
            +
                    # Calls {Storage#value_to_mapper}. It is repeated in Mapper for easier overriding.
         
     | 
| 
      
 763 
     | 
    
         
            +
                    # @param [Class] type Value's type
         
     | 
| 
      
 764 
     | 
    
         
            +
                    # @param [Object] value
         
     | 
| 
      
 765 
     | 
    
         
            +
                    # @return [Object]
         
     | 
| 
      
 766 
     | 
    
         
            +
                    def storage_value_to_mapper(type, value)
         
     | 
| 
      
 767 
     | 
    
         
            +
                        storage.value_to_mapper(type, value)
         
     | 
| 
      
 768 
     | 
    
         
            +
                    end
         
     | 
| 
      
 769 
     | 
    
         
            +
                    
         
     | 
| 
      
 770 
     | 
    
         
            +
                    
         
     | 
| 
      
 771 
     | 
    
         
            +
                    # Converts a value into one that is accepted by the storage.
         
     | 
| 
      
 772 
     | 
    
         
            +
                    # @param [Class] type Value's type
         
     | 
| 
      
 773 
     | 
    
         
            +
                    # @param [Object] value
         
     | 
| 
      
 774 
     | 
    
         
            +
                    # @param [Symbol] save_mode :insert, :update, or generically :save
         
     | 
| 
      
 775 
     | 
    
         
            +
                    # @return [Object]
         
     | 
| 
      
 776 
     | 
    
         
            +
                    def map_value(type, value, mode=nil)
         
     | 
| 
      
 777 
     | 
    
         
            +
                        return value if value.nil?
         
     | 
| 
      
 778 
     | 
    
         
            +
                        if type == Spider::DataTypes::PK
         
     | 
| 
      
 779 
     | 
    
         
            +
                            value = value.obj if value.is_a?(Spider::DataTypes::PK)
         
     | 
| 
      
 780 
     | 
    
         
            +
                        elsif type < Spider::DataType
         
     | 
| 
      
 781 
     | 
    
         
            +
                            value = type.from_value(value) unless value.is_a?(type)
         
     | 
| 
      
 782 
     | 
    
         
            +
                            value = value.map(self.type)
         
     | 
| 
      
 783 
     | 
    
         
            +
                        elsif type.class == Class && type.subclass_of?(Spider::Model::BaseModel)
         
     | 
| 
      
 784 
     | 
    
         
            +
                            value = type.primary_keys.map{ |key| value.send(key.name) }
         
     | 
| 
      
 785 
     | 
    
         
            +
                        end
         
     | 
| 
      
 786 
     | 
    
         
            +
                        value
         
     | 
| 
      
 787 
     | 
    
         
            +
                    end
         
     | 
| 
      
 788 
     | 
    
         
            +
                    
         
     | 
| 
      
 789 
     | 
    
         
            +
             
     | 
| 
      
 790 
     | 
    
         
            +
                    # Converts a storage value back to the corresponding base type or DataType.
         
     | 
| 
      
 791 
     | 
    
         
            +
                    # @param [Class] type Value's type
         
     | 
| 
      
 792 
     | 
    
         
            +
                    # @param [Object] value
         
     | 
| 
      
 793 
     | 
    
         
            +
                    # @return [Object]
         
     | 
| 
      
 794 
     | 
    
         
            +
                    def map_back_value(type, value)
         
     | 
| 
      
 795 
     | 
    
         
            +
                        value = value[0] if value.class == Array
         
     | 
| 
      
 796 
     | 
    
         
            +
                        value = storage_value_to_mapper(Model.simplify_type(type), value)
         
     | 
| 
      
 797 
     | 
    
         
            +
             
     | 
| 
      
 798 
     | 
    
         
            +
                        if type <= Spider::DataTypes::PK
         
     | 
| 
      
 799 
     | 
    
         
            +
                            value = value.is_a?(Spider::DataTypes::PK) ? value.obj : value
         
     | 
| 
      
 800 
     | 
    
         
            +
                        elsif type < Spider::DataType && type.maps_back_to
         
     | 
| 
      
 801 
     | 
    
         
            +
                            type = type.maps_back_to
         
     | 
| 
      
 802 
     | 
    
         
            +
                        end
         
     | 
| 
      
 803 
     | 
    
         
            +
                        case type.name
         
     | 
| 
      
 804 
     | 
    
         
            +
                        when 'Fixnum'
         
     | 
| 
      
 805 
     | 
    
         
            +
                            return value ? value.to_i : nil
         
     | 
| 
      
 806 
     | 
    
         
            +
                        when 'Float'
         
     | 
| 
      
 807 
     | 
    
         
            +
                            return value ? value.to_f : nil
         
     | 
| 
      
 808 
     | 
    
         
            +
                        end
         
     | 
| 
      
 809 
     | 
    
         
            +
                        return nil unless value
         
     | 
| 
      
 810 
     | 
    
         
            +
                        case type.name
         
     | 
| 
      
 811 
     | 
    
         
            +
                        when 'Date', 'DateTime'
         
     | 
| 
      
 812 
     | 
    
         
            +
                            return type.parse(value) unless value.is_a?(Date)
         
     | 
| 
      
 813 
     | 
    
         
            +
                        end
         
     | 
| 
      
 814 
     | 
    
         
            +
                        if type < Spider::DataType && type.force_wrap?
         
     | 
| 
      
 815 
     | 
    
         
            +
                            value = type.from_value(value)
         
     | 
| 
      
 816 
     | 
    
         
            +
                        end
         
     | 
| 
      
 817 
     | 
    
         
            +
                        return value
         
     | 
| 
      
 818 
     | 
    
         
            +
                    end        
         
     | 
| 
      
 819 
     | 
    
         
            +
                    
         
     | 
| 
      
 820 
     | 
    
         
            +
                    # Unit of work
         
     | 
| 
      
 821 
     | 
    
         
            +
                    
         
     | 
| 
      
 822 
     | 
    
         
            +
                    # @abstract
         
     | 
| 
      
 823 
     | 
    
         
            +
                    # Returns task dependecies for the UnitOfWork. May be implemented by subclasses.
         
     | 
| 
      
 824 
     | 
    
         
            +
                    # @param [MapperTask] task
         
     | 
| 
      
 825 
     | 
    
         
            +
                    # @return [Array] Dependencies for the task
         
     | 
| 
      
 826 
     | 
    
         
            +
                    def get_dependencies(task)
         
     | 
| 
      
 827 
     | 
    
         
            +
                        return []
         
     | 
| 
      
 828 
     | 
    
         
            +
                    end
         
     | 
| 
      
 829 
     | 
    
         
            +
                    
         
     | 
| 
      
 830 
     | 
    
         
            +
                    # @param [BaseModel] obj
         
     | 
| 
      
 831 
     | 
    
         
            +
                    # @param [Symbol] action UnitOfWork action
         
     | 
| 
      
 832 
     | 
    
         
            +
                    # @return [Array] Objects to be added to the UnitOfWork when obj is added
         
     | 
| 
      
 833 
     | 
    
         
            +
                    def children_for_unit_of_work(obj, action)
         
     | 
| 
      
 834 
     | 
    
         
            +
                        children = []
         
     | 
| 
      
 835 
     | 
    
         
            +
                        obj.class.elements_array.each do |el|
         
     | 
| 
      
 836 
     | 
    
         
            +
                            next unless obj.element_has_value?(el)
         
     | 
| 
      
 837 
     | 
    
         
            +
                            next unless el.model?
         
     | 
| 
      
 838 
     | 
    
         
            +
                            next unless obj.element_modified?(el)
         
     | 
| 
      
 839 
     | 
    
         
            +
                            val = obj.get(el)
         
     | 
| 
      
 840 
     | 
    
         
            +
                            next unless val.modified?
         
     | 
| 
      
 841 
     | 
    
         
            +
                            children << val
         
     | 
| 
      
 842 
     | 
    
         
            +
                        end
         
     | 
| 
      
 843 
     | 
    
         
            +
                        children
         
     | 
| 
      
 844 
     | 
    
         
            +
                    end
         
     | 
| 
      
 845 
     | 
    
         
            +
             
     | 
| 
      
 846 
     | 
    
         
            +
                    protected
         
     | 
| 
      
 847 
     | 
    
         
            +
             
     | 
| 
      
 848 
     | 
    
         
            +
                    # @return [Array] An array of all elements which are handled by the mapper
         
     | 
| 
      
 849 
     | 
    
         
            +
                    def map_elements
         
     | 
| 
      
 850 
     | 
    
         
            +
                        @model.elements_array.select{ |el| !@no_map_elements[el.name] }
         
     | 
| 
      
 851 
     | 
    
         
            +
                    end
         
     | 
| 
      
 852 
     | 
    
         
            +
             
     | 
| 
      
 853 
     | 
    
         
            +
             
     | 
| 
      
 854 
     | 
    
         
            +
                    # Given a QuerySet and a model object, searches for an object with the same keys
         
     | 
| 
      
 855 
     | 
    
         
            +
                    # in the QuerySet; if found, merges the object, otherwise, adds the object to the set
         
     | 
| 
      
 856 
     | 
    
         
            +
                    #
         
     | 
| 
      
 857 
     | 
    
         
            +
                    # @param [QuerySet] set
         
     | 
| 
      
 858 
     | 
    
         
            +
                    # @param [BaseModel] obj Object to merge
         
     | 
| 
      
 859 
     | 
    
         
            +
                    # @param [Model::Request] request Only elements in request will be merged
         
     | 
| 
      
 860 
     | 
    
         
            +
                    # @return [void]
         
     | 
| 
      
 861 
     | 
    
         
            +
                    def merge_object(set, obj, request)
         
     | 
| 
       627 
862 
     | 
    
         
             
                        search = {} 
         
     | 
| 
       628 
863 
     | 
    
         
             
                        @model.primary_keys.each{ |k| search[k.name] = obj.get(k.name) }
         
     | 
| 
       629 
864 
     | 
    
         
             
                        obj_res = set.find(search)  # FIXME: find a better way
         
     | 
| 
         @@ -637,8 +872,14 @@ module Spider; module Model 
     | 
|
| 
       637 
872 
     | 
    
         
             
                            obj
         
     | 
| 
       638 
873 
     | 
    
         
             
                        end
         
     | 
| 
       639 
874 
     | 
    
         
             
                    end
         
     | 
| 
       640 
     | 
    
         
            -
             
     | 
| 
       641 
     | 
    
         
            -
                     
     | 
| 
      
 875 
     | 
    
         
            +
             
     | 
| 
      
 876 
     | 
    
         
            +
                    # Like #find, but also retrieves instances of the object's superclass (assuming it is a BaseModel as well)
         
     | 
| 
      
 877 
     | 
    
         
            +
                    # 
         
     | 
| 
      
 878 
     | 
    
         
            +
                    # @param [Query] query
         
     | 
| 
      
 879 
     | 
    
         
            +
                    # @param [QuerySet] set
         
     | 
| 
      
 880 
     | 
    
         
            +
                    # @param [Hash] options
         
     | 
| 
      
 881 
     | 
    
         
            +
                    # @return [QuerySet]
         
     | 
| 
      
 882 
     | 
    
         
            +
                    def find_with_superclass(query, set=nil, options={})
         
     | 
| 
       642 
883 
     | 
    
         
             
                        q = query.clone
         
     | 
| 
       643 
884 
     | 
    
         
             
                        polym_request = Request.new
         
     | 
| 
       644 
885 
     | 
    
         
             
                        polym_condition = Condition.new
         
     | 
| 
         @@ -656,26 +897,12 @@ module Spider; module Model 
     | 
|
| 
       656 
897 
     | 
    
         
             
                        end
         
     | 
| 
       657 
898 
     | 
    
         
             
                        return set
         
     | 
| 
       658 
899 
     | 
    
         
             
                    end
         
     | 
| 
       659 
     | 
    
         
            -
             
     | 
| 
       660 
     | 
    
         
            -
             
     | 
| 
       661 
     | 
    
         
            -
                     
     | 
| 
       662 
     | 
    
         
            -
             
     | 
| 
       663 
     | 
    
         
            -
             
     | 
| 
       664 
     | 
    
         
            -
             
     | 
| 
       665 
     | 
    
         
            -
                    end
         
     | 
| 
       666 
     | 
    
         
            -
                    
         
     | 
| 
       667 
     | 
    
         
            -
                    # Actual interaction with the storage. Should be implemented by subclasses.
         
     | 
| 
       668 
     | 
    
         
            -
                    def fetch(query)
         
     | 
| 
       669 
     | 
    
         
            -
                        raise MapperError, "Unimplemented"
         
     | 
| 
       670 
     | 
    
         
            -
                    end
         
     | 
| 
       671 
     | 
    
         
            -
                    
         
     | 
| 
       672 
     | 
    
         
            -
                    
         
     | 
| 
       673 
     | 
    
         
            -
                    # Transforms a Storage result into an object. Should be implemented by subclasses.
         
     | 
| 
       674 
     | 
    
         
            -
                    def map(request, result, obj_or_model)
         
     | 
| 
       675 
     | 
    
         
            -
                        raise MapperError, "Unimplemented"
         
     | 
| 
       676 
     | 
    
         
            -
                    end
         
     | 
| 
       677 
     | 
    
         
            -
                    
         
     | 
| 
       678 
     | 
    
         
            -
                    # Loads external elements, according to query,  and merges them into an object or a QuerySet
         
     | 
| 
      
 900 
     | 
    
         
            +
             
     | 
| 
      
 901 
     | 
    
         
            +
             
     | 
| 
      
 902 
     | 
    
         
            +
                    # Loads external elements, according to query, and merges them into an object or a QuerySet
         
     | 
| 
      
 903 
     | 
    
         
            +
                    # @param [QuerySet|BaseModel] objects
         
     | 
| 
      
 904 
     | 
    
         
            +
                    # @param [Query] query
         
     | 
| 
      
 905 
     | 
    
         
            +
                    # @return [QuerySet]
         
     | 
| 
       679 
906 
     | 
    
         
             
                    def get_external(objects, query)
         
     | 
| 
       680 
907 
     | 
    
         
             
                        objects = queryset_siblings(objects) unless objects.is_a?(QuerySet)
         
     | 
| 
       681 
908 
     | 
    
         
             
                        return objects if objects.length < 1
         
     | 
| 
         @@ -711,6 +938,10 @@ module Spider; module Model 
     | 
|
| 
       711 
938 
     | 
    
         
             
                    end
         
     | 
| 
       712 
939 
     | 
    
         | 
| 
       713 
940 
     | 
    
         
             
                    # Loads an external element, according to query, and merges the result into an object or QuerySet.
         
     | 
| 
      
 941 
     | 
    
         
            +
                    # @param [Element] element
         
     | 
| 
      
 942 
     | 
    
         
            +
                    # @param [Query] query
         
     | 
| 
      
 943 
     | 
    
         
            +
                    # @param [QuerySet] result
         
     | 
| 
      
 944 
     | 
    
         
            +
                    # @return [QuerySet]
         
     | 
| 
       714 
945 
     | 
    
         
             
                    def get_external_element(element, query, objects)
         
     | 
| 
       715 
946 
     | 
    
         
             
            #            Spider::Logger.debug("Getting external element #{element.name} for #{@model}")
         
     | 
| 
       716 
947 
     | 
    
         
             
                        return load_element(objects, element) if have_references?(element)
         
     | 
| 
         @@ -733,6 +964,10 @@ module Spider; module Model 
     | 
|
| 
       733 
964 
     | 
    
         | 
| 
       734 
965 
     | 
    
         
             
                    # Given the results of a query for an element, and a set of objects, associates
         
     | 
| 
       735 
966 
     | 
    
         
             
                    # the result with the corresponding objects.
         
     | 
| 
      
 967 
     | 
    
         
            +
                    # @param [Element] element
         
     | 
| 
      
 968 
     | 
    
         
            +
                    # @param [QuerySet] objects
         
     | 
| 
      
 969 
     | 
    
         
            +
                    # @param [QuerySet] result
         
     | 
| 
      
 970 
     | 
    
         
            +
                    # @return [QuerySet]
         
     | 
| 
       736 
971 
     | 
    
         
             
                    def associate_external(element, objects, result)
         
     | 
| 
       737 
972 
     | 
    
         
             
            #            result.reindex
         
     | 
| 
       738 
973 
     | 
    
         
             
                        objects.element_loaded(element.name)
         
     | 
| 
         @@ -751,92 +986,15 @@ module Spider; module Model 
     | 
|
| 
       751 
986 
     | 
    
         
             
                        end
         
     | 
| 
       752 
987 
     | 
    
         
             
                        return objects
         
     | 
| 
       753 
988 
     | 
    
         
             
                    end
         
     | 
| 
       754 
     | 
    
         
            -
                    
         
     | 
| 
       755 
     | 
    
         
            -
                    # Returns the siblings, if any, of the object, in its ancestor QuerySet.
         
     | 
| 
       756 
     | 
    
         
            -
                    def queryset_siblings(obj)
         
     | 
| 
       757 
     | 
    
         
            -
                        return QuerySet.new(@model, obj) unless obj._parent
         
     | 
| 
       758 
     | 
    
         
            -
                        orig_obj = obj
         
     | 
| 
       759 
     | 
    
         
            -
                        path = []
         
     | 
| 
       760 
     | 
    
         
            -
                        seen = {obj => true}
         
     | 
| 
       761 
     | 
    
         
            -
                        while (obj._parent && !seen[obj._parent])
         
     | 
| 
       762 
     | 
    
         
            -
                            path.unshift(obj._parent_element) if (obj._parent_element) # otherwise it's a query set
         
     | 
| 
       763 
     | 
    
         
            -
                            obj = obj._parent
         
     | 
| 
       764 
     | 
    
         
            -
                            seen[obj] = true
         
     | 
| 
       765 
     | 
    
         
            -
                        end
         
     | 
| 
       766 
     | 
    
         
            -
                        res = path.empty? ? obj : obj.all_children(path)
         
     | 
| 
       767 
     | 
    
         
            -
                        raise RuntimeError, "Broken object path" if (obj && !path.empty? &&  res.length < 1)
         
     | 
| 
       768 
     | 
    
         
            -
                        res = QuerySet.new(@model, res) unless res.is_a?(QuerySet)
         
     | 
| 
       769 
     | 
    
         
            -
                        res = res.select{ |obj| obj.primary_keys_set? }
         
     | 
| 
       770 
     | 
    
         
            -
                        return res
         
     | 
| 
       771 
     | 
    
         
            -
                    end
         
     | 
| 
       772 
     | 
    
         
            -
                    
         
     | 
| 
       773 
     | 
    
         
            -
                    # Prepares a value going to be bound to an insert or update statement
         
     | 
| 
       774 
     | 
    
         
            -
                     def map_save_value(type, value, save_mode=:save)
         
     | 
| 
       775 
     | 
    
         
            -
                         value = map_value(type, value, :save)
         
     | 
| 
       776 
     | 
    
         
            -
                         return @storage.value_for_save(Model.simplify_type(type), value, save_mode)
         
     | 
| 
       777 
     | 
    
         
            -
                     end
         
     | 
| 
       778 
     | 
    
         
            -
             
     | 
| 
       779 
     | 
    
         
            -
                    # Prepares a value for a condition.
         
     | 
| 
       780 
     | 
    
         
            -
                    def map_condition_value(type, value)
         
     | 
| 
       781 
     | 
    
         
            -
                        if value.is_a?(Range)
         
     | 
| 
       782 
     | 
    
         
            -
                            return Range.new(map_condition_value(type, value.first), map_condition_value(type, value.last))
         
     | 
| 
       783 
     | 
    
         
            -
                        end
         
     | 
| 
       784 
     | 
    
         
            -
                        return value if ( type.class == Class && type.subclass_of?(Spider::Model::BaseModel) )
         
     | 
| 
       785 
     | 
    
         
            -
                        value = map_value(type, value, :condition)
         
     | 
| 
       786 
     | 
    
         
            -
                        return @storage.value_for_condition(Model.simplify_type(type), value)
         
     | 
| 
       787 
     | 
    
         
            -
                    end
         
     | 
| 
       788 
     | 
    
         
            -
             
     | 
| 
       789 
     | 
    
         
            -
                    def storage_value_to_mapper(type, value)
         
     | 
| 
       790 
     | 
    
         
            -
                        storage.value_to_mapper(type, value)
         
     | 
| 
       791 
     | 
    
         
            -
                    end
         
     | 
| 
       792 
     | 
    
         
            -
                    
         
     | 
| 
       793 
     | 
    
         
            -
                    
         
     | 
| 
       794 
     | 
    
         
            -
                    # Converts a value in one accepted by the storage.
         
     | 
| 
       795 
     | 
    
         
            -
                    def map_value(type, value, mode=nil)
         
     | 
| 
       796 
     | 
    
         
            -
                        return value if value.nil?
         
     | 
| 
       797 
     | 
    
         
            -
                        if type == Spider::DataTypes::PK
         
     | 
| 
       798 
     | 
    
         
            -
                            value = value.obj if value.is_a?(Spider::DataTypes::PK)
         
     | 
| 
       799 
     | 
    
         
            -
                        elsif type < Spider::DataType
         
     | 
| 
       800 
     | 
    
         
            -
                            value = type.from_value(value) unless value.is_a?(type)
         
     | 
| 
       801 
     | 
    
         
            -
                            value = value.map(self.type)
         
     | 
| 
       802 
     | 
    
         
            -
                        elsif type.class == Class && type.subclass_of?(Spider::Model::BaseModel)
         
     | 
| 
       803 
     | 
    
         
            -
                            value = type.primary_keys.map{ |key| value.send(key.name) }
         
     | 
| 
       804 
     | 
    
         
            -
                        end
         
     | 
| 
       805 
     | 
    
         
            -
                        value
         
     | 
| 
       806 
     | 
    
         
            -
                    end
         
     | 
| 
       807 
     | 
    
         
            -
                    
         
     | 
| 
       808 
     | 
    
         
            -
             
     | 
| 
       809 
     | 
    
         
            -
                    # Converts a storage value back to the corresponding base type or DataType.
         
     | 
| 
       810 
     | 
    
         
            -
                    def map_back_value(type, value)
         
     | 
| 
       811 
     | 
    
         
            -
                        value = value[0] if value.class == Array
         
     | 
| 
       812 
     | 
    
         
            -
                        value = storage_value_to_mapper(Model.simplify_type(type), value)
         
     | 
| 
       813 
989 
     | 
    
         | 
| 
       814 
     | 
    
         
            -
                        if type <= Spider::DataTypes::PK
         
     | 
| 
       815 
     | 
    
         
            -
                            value = value.is_a?(Spider::DataTypes::PK) ? value.obj : value
         
     | 
| 
       816 
     | 
    
         
            -
                        elsif type < Spider::DataType && type.maps_back_to
         
     | 
| 
       817 
     | 
    
         
            -
                            type = type.maps_back_to
         
     | 
| 
       818 
     | 
    
         
            -
                        end
         
     | 
| 
       819 
     | 
    
         
            -
                        case type.name
         
     | 
| 
       820 
     | 
    
         
            -
                        when 'Fixnum'
         
     | 
| 
       821 
     | 
    
         
            -
                            return value ? value.to_i : nil
         
     | 
| 
       822 
     | 
    
         
            -
                        when 'Float'
         
     | 
| 
       823 
     | 
    
         
            -
                            return value ? value.to_f : nil
         
     | 
| 
       824 
     | 
    
         
            -
                        end
         
     | 
| 
       825 
     | 
    
         
            -
                        return nil unless value
         
     | 
| 
       826 
     | 
    
         
            -
                        case type.name
         
     | 
| 
       827 
     | 
    
         
            -
                        when 'Date', 'DateTime'
         
     | 
| 
       828 
     | 
    
         
            -
                            return type.parse(value) unless value.is_a?(Date)
         
     | 
| 
       829 
     | 
    
         
            -
                        end
         
     | 
| 
       830 
     | 
    
         
            -
                        if type < Spider::DataType && type.force_wrap?
         
     | 
| 
       831 
     | 
    
         
            -
                            value = type.from_value(value)
         
     | 
| 
       832 
     | 
    
         
            -
                        end
         
     | 
| 
       833 
     | 
    
         
            -
                        return value
         
     | 
| 
       834 
     | 
    
         
            -
                    end        
         
     | 
| 
       835 
     | 
    
         
            -
                    
         
     | 
| 
       836 
990 
     | 
    
         
             
                    ##############################################################
         
     | 
| 
       837 
991 
     | 
    
         
             
                    #   Strategy                                                 #
         
     | 
| 
       838 
992 
     | 
    
         
             
                    ##############################################################
         
     | 
| 
       839 
993 
     | 
    
         | 
| 
      
 994 
     | 
    
         
            +
                    # Ensures a Query is ready for being used by the mapper
         
     | 
| 
      
 995 
     | 
    
         
            +
                    # @param [Query] query
         
     | 
| 
      
 996 
     | 
    
         
            +
                    # @param [BaseModel] obj Optional object; if passed, will be used to ensure the Query Request corresponds to the object
         
     | 
| 
      
 997 
     | 
    
         
            +
                    # @return [Query] The prepared query
         
     | 
| 
       840 
998 
     | 
    
         
             
                    def prepare_query(query, obj=nil)
         
     | 
| 
       841 
999 
     | 
    
         
             
                        if (query.request.polymorphs?)
         
     | 
| 
       842 
1000 
     | 
    
         
             
                            conds = split_condition_polymorphs(query.condition, query.request.polymorphs.keys) 
         
     | 
| 
         @@ -852,6 +1010,11 @@ module Spider; module Model 
     | 
|
| 
       852 
1010 
     | 
    
         
             
                        return query
         
     | 
| 
       853 
1011 
     | 
    
         
             
                    end
         
     | 
| 
       854 
1012 
     | 
    
         | 
| 
      
 1013 
     | 
    
         
            +
                    # Helper method to split conditions for polymorphic elements
         
     | 
| 
      
 1014 
     | 
    
         
            +
                    # into the correct classes
         
     | 
| 
      
 1015 
     | 
    
         
            +
                    # @param [Condition] condition
         
     | 
| 
      
 1016 
     | 
    
         
            +
                    # @param [Array] polymorphs Array of polymorphic model classes
         
     | 
| 
      
 1017 
     | 
    
         
            +
                    # @return [Array] An array of conditions
         
     | 
| 
       855 
1018 
     | 
    
         
             
                    def split_condition_polymorphs(condition, polymorphs)
         
     | 
| 
       856 
1019 
     | 
    
         
             
                        conditions = {}
         
     | 
| 
       857 
1020 
     | 
    
         
             
                        return conditions if condition.polymorph && polymorphs.include?(condition.polymorph)
         
     | 
| 
         @@ -884,6 +1047,9 @@ module Spider; module Model 
     | 
|
| 
       884 
1047 
     | 
    
         | 
| 
       885 
1048 
     | 
    
         | 
| 
       886 
1049 
     | 
    
         
             
                    # Normalizes a request.
         
     | 
| 
      
 1050 
     | 
    
         
            +
                    # @param [Request] request
         
     | 
| 
      
 1051 
     | 
    
         
            +
                    # @param [BaseModel] obj
         
     | 
| 
      
 1052 
     | 
    
         
            +
                    # @return [void]
         
     | 
| 
       887 
1053 
     | 
    
         
             
                    def prepare_query_request(request, obj=nil)
         
     | 
| 
       888 
1054 
     | 
    
         
             
                        @model.primary_keys.each do |key|
         
     | 
| 
       889 
1055 
     | 
    
         
             
                            request[key] = true
         
     | 
| 
         @@ -900,7 +1066,11 @@ module Spider; module Model 
     | 
|
| 
       900 
1066 
     | 
    
         
             
                        new_requests.each{ |r| request.request(r) }
         
     | 
| 
       901 
1067 
     | 
    
         
             
                    end
         
     | 
| 
       902 
1068 
     | 
    
         | 
| 
       903 
     | 
    
         
            -
                    # Adds lazy groups to request.
         
     | 
| 
      
 1069 
     | 
    
         
            +
                    # Adds lazy groups to request. That is, load more data than was requested, to avoid making more
         
     | 
| 
      
 1070 
     | 
    
         
            +
                    # trips to the storage.
         
     | 
| 
      
 1071 
     | 
    
         
            +
                    # @param [Request] request
         
     | 
| 
      
 1072 
     | 
    
         
            +
                    # @param [BaseModel] obj Optional model instance
         
     | 
| 
      
 1073 
     | 
    
         
            +
                    # @return [void]
         
     | 
| 
       904 
1074 
     | 
    
         
             
                    def expand_request(request, obj=nil)
         
     | 
| 
       905 
1075 
     | 
    
         
             
                        lazy_groups = []
         
     | 
| 
       906 
1076 
     | 
    
         
             
                        request.each do |k, v|
         
     | 
| 
         @@ -924,6 +1094,8 @@ module Spider; module Model 
     | 
|
| 
       924 
1094 
     | 
    
         
             
                    end
         
     | 
| 
       925 
1095 
     | 
    
         | 
| 
       926 
1096 
     | 
    
         
             
                    # Preprocessing of the condition
         
     | 
| 
      
 1097 
     | 
    
         
            +
                    # @param [Condition] condition
         
     | 
| 
      
 1098 
     | 
    
         
            +
                    # @return [Condition] The preprocessed condition
         
     | 
| 
       927 
1099 
     | 
    
         
             
                    def preprocess_condition(condition)
         
     | 
| 
       928 
1100 
     | 
    
         
             
                        model = condition.polymorph ? condition.polymorph : @model
         
     | 
| 
       929 
1101 
     | 
    
         
             
                        condition.simplify
         
     | 
| 
         @@ -1044,25 +1216,86 @@ module Spider; module Model 
     | 
|
| 
       1044 
1216 
     | 
    
         
             
                        end
         
     | 
| 
       1045 
1217 
     | 
    
         
             
                        return condition
         
     | 
| 
       1046 
1218 
     | 
    
         
             
                    end
         
     | 
| 
      
 1219 
     | 
    
         
            +
             
     | 
| 
      
 1220 
     | 
    
         
            +
                    # @abstract
         
     | 
| 
      
 1221 
     | 
    
         
            +
                    # Returns true if information to find the given element is accessible to the mapper, or to an integrated model's mapper
         
     | 
| 
      
 1222 
     | 
    
         
            +
                    # (see also {#have_references?}, and  {DbMapper#someone_have_references?} for an implementation).
         
     | 
| 
      
 1223 
     | 
    
         
            +
                    #
         
     | 
| 
      
 1224 
     | 
    
         
            +
                    # @param [Symbol|Element] element
         
     | 
| 
      
 1225 
     | 
    
         
            +
                    # @return [bool] True if this mapper, or an integrated model's mapper, has references, false otherwise.
         
     | 
| 
      
 1226 
     | 
    
         
            +
                    def someone_have_references?(element)
         
     | 
| 
      
 1227 
     | 
    
         
            +
                        raise MapperError, "Unimplemented"
         
     | 
| 
      
 1228 
     | 
    
         
            +
                    end
         
     | 
| 
      
 1229 
     | 
    
         
            +
             
     | 
| 
      
 1230 
     | 
    
         
            +
                    # Abstract methods
         
     | 
| 
      
 1231 
     | 
    
         
            +
             
     | 
| 
      
 1232 
     | 
    
         
            +
                    # @abstract
         
     | 
| 
      
 1233 
     | 
    
         
            +
                    # Deletes all data associated to the model from the storage
         
     | 
| 
      
 1234 
     | 
    
         
            +
                    # @return [void]
         
     | 
| 
      
 1235 
     | 
    
         
            +
                    def truncate!
         
     | 
| 
      
 1236 
     | 
    
         
            +
                        raise MapperError, "Unimplemented"
         
     | 
| 
      
 1237 
     | 
    
         
            +
                    end
         
     | 
| 
       1047 
1238 
     | 
    
         | 
| 
       1048 
     | 
    
         
            -
                    #  
     | 
| 
       1049 
     | 
    
         
            -
                     
     | 
| 
       1050 
     | 
    
         
            -
             
     | 
| 
      
 1239 
     | 
    
         
            +
                    # @abstract
         
     | 
| 
      
 1240 
     | 
    
         
            +
                    # Actual interaction with the storage. May be implemented by subclasses.
         
     | 
| 
      
 1241 
     | 
    
         
            +
                    # @return [void]
         
     | 
| 
      
 1242 
     | 
    
         
            +
                    def do_delete(obj, force=false)
         
     | 
| 
      
 1243 
     | 
    
         
            +
                        raise MapperError, "Unimplemented"
         
     | 
| 
       1051 
1244 
     | 
    
         
             
                    end
         
     | 
| 
       1052 
1245 
     | 
    
         | 
| 
       1053 
     | 
    
         
            -
                     
     | 
| 
       1054 
     | 
    
         
            -
             
     | 
| 
       1055 
     | 
    
         
            -
             
     | 
| 
       1056 
     | 
    
         
            -
             
     | 
| 
       1057 
     | 
    
         
            -
             
     | 
| 
       1058 
     | 
    
         
            -
             
     | 
| 
       1059 
     | 
    
         
            -
             
     | 
| 
       1060 
     | 
    
         
            -
             
     | 
| 
       1061 
     | 
    
         
            -
             
     | 
| 
       1062 
     | 
    
         
            -
             
     | 
| 
       1063 
     | 
    
         
            -
             
     | 
| 
      
 1246 
     | 
    
         
            +
                    # @abstract
         
     | 
| 
      
 1247 
     | 
    
         
            +
                    # Actual interaction with the storage. May be implemented by subclasses.
         
     | 
| 
      
 1248 
     | 
    
         
            +
                    # @return [void]
         
     | 
| 
      
 1249 
     | 
    
         
            +
                    def do_insert(obj)
         
     | 
| 
      
 1250 
     | 
    
         
            +
                        raise MapperError, "Unimplemented"
         
     | 
| 
      
 1251 
     | 
    
         
            +
                    end
         
     | 
| 
      
 1252 
     | 
    
         
            +
                    
         
     | 
| 
      
 1253 
     | 
    
         
            +
                    # @abstract
         
     | 
| 
      
 1254 
     | 
    
         
            +
                    # Actual interaction with the storage. May be implemented by subclasses.
         
     | 
| 
      
 1255 
     | 
    
         
            +
                    # @return [void]
         
     | 
| 
      
 1256 
     | 
    
         
            +
                    def do_update(obj)
         
     | 
| 
      
 1257 
     | 
    
         
            +
                        raise MapperError, "Unimplemented"
         
     | 
| 
       1064 
1258 
     | 
    
         
             
                    end
         
     | 
| 
       1065 
1259 
     | 
    
         | 
| 
      
 1260 
     | 
    
         
            +
                    # @abstract
         
     | 
| 
      
 1261 
     | 
    
         
            +
                    # Actual interaction with the storage. May be implemented by subclasses.
         
     | 
| 
      
 1262 
     | 
    
         
            +
                    # @return [void]
         
     | 
| 
      
 1263 
     | 
    
         
            +
                    def lock(obj=nil, mode=:exclusive)
         
     | 
| 
      
 1264 
     | 
    
         
            +
                        raise MapperError, "Unimplemented"
         
     | 
| 
      
 1265 
     | 
    
         
            +
                    end
         
     | 
| 
      
 1266 
     | 
    
         
            +
                    
         
     | 
| 
      
 1267 
     | 
    
         
            +
                    # @abstract
         
     | 
| 
      
 1268 
     | 
    
         
            +
                    # Actual interaction with the storage. May be implemented by subclasses.
         
     | 
| 
      
 1269 
     | 
    
         
            +
                    # @param [Symbol] name
         
     | 
| 
      
 1270 
     | 
    
         
            +
                    # @return [void]
         
     | 
| 
      
 1271 
     | 
    
         
            +
                    def sequence_next(name)
         
     | 
| 
      
 1272 
     | 
    
         
            +
                        raise MapperError, "Unimplemented"
         
     | 
| 
      
 1273 
     | 
    
         
            +
                    end
         
     | 
| 
      
 1274 
     | 
    
         
            +
             
     | 
| 
      
 1275 
     | 
    
         
            +
                    # @abstract
         
     | 
| 
      
 1276 
     | 
    
         
            +
                    # Actual interaction with the storage. Should be implemented by subclasses.
         
     | 
| 
      
 1277 
     | 
    
         
            +
                    # @param [Query]
         
     | 
| 
      
 1278 
     | 
    
         
            +
                    # @return [QuerySet]
         
     | 
| 
      
 1279 
     | 
    
         
            +
                    def fetch(query)
         
     | 
| 
      
 1280 
     | 
    
         
            +
                        raise MapperError, "Unimplemented"
         
     | 
| 
      
 1281 
     | 
    
         
            +
                    end
         
     | 
| 
      
 1282 
     | 
    
         
            +
             
     | 
| 
      
 1283 
     | 
    
         
            +
                    # @abstract
         
     | 
| 
      
 1284 
     | 
    
         
            +
                    # Transforms a Storage result into an object. Should be implemented by subclasses.
         
     | 
| 
      
 1285 
     | 
    
         
            +
                    # @return [BaseModel]
         
     | 
| 
      
 1286 
     | 
    
         
            +
                    def map(request, result, obj_or_model)
         
     | 
| 
      
 1287 
     | 
    
         
            +
                        raise MapperError, "Unimplemented"
         
     | 
| 
      
 1288 
     | 
    
         
            +
                    end
         
     | 
| 
      
 1289 
     | 
    
         
            +
             
     | 
| 
      
 1290 
     | 
    
         
            +
                    # @abstract
         
     | 
| 
      
 1291 
     | 
    
         
            +
                    # @param [Element|Symbol] element
         
     | 
| 
      
 1292 
     | 
    
         
            +
                    # @param [Condition]
         
     | 
| 
      
 1293 
     | 
    
         
            +
                    # @return [Fixnum] The max value for an element   
         
     | 
| 
      
 1294 
     | 
    
         
            +
                    def max(element, condition=nil)
         
     | 
| 
      
 1295 
     | 
    
         
            +
                        raise "Unimplemented"
         
     | 
| 
      
 1296 
     | 
    
         
            +
                    end
         
     | 
| 
      
 1297 
     | 
    
         
            +
                
         
     | 
| 
      
 1298 
     | 
    
         
            +
                    
         
     | 
| 
       1066 
1299 
     | 
    
         | 
| 
       1067 
1300 
     | 
    
         
             
                end
         
     | 
| 
       1068 
1301 
     | 
    
         | 
| 
         @@ -1070,10 +1303,21 @@ module Spider; module Model 
     | 
|
| 
       1070 
1303 
     | 
    
         
             
                #   MapperTask                                               #
         
     | 
| 
       1071 
1304 
     | 
    
         
             
                ##############################################################
         
     | 
| 
       1072 
1305 
     | 
    
         | 
| 
       1073 
     | 
    
         
            -
                # The MapperTask is used by the UnitOfWork.
         
     | 
| 
      
 1306 
     | 
    
         
            +
                # The MapperTask is used by the UnitOfWork. It represents an action that needs to be done,
         
     | 
| 
      
 1307 
     | 
    
         
            +
                # and allows to specify dependences between tasks
         
     | 
| 
       1074 
1308 
     | 
    
         
             
                class MapperTask
         
     | 
| 
       1075 
     | 
    
         
            -
                     
     | 
| 
      
 1309 
     | 
    
         
            +
                    # @return [Array] Array of MapperTasks this one depends on
         
     | 
| 
      
 1310 
     | 
    
         
            +
                    attr_reader :dependencies
         
     | 
| 
      
 1311 
     | 
    
         
            +
                    # @return [BaseModel] The task's subject
         
     | 
| 
      
 1312 
     | 
    
         
            +
                    attr_reader :object 
         
     | 
| 
      
 1313 
     | 
    
         
            +
                    # @return [Symbol] The task's action
         
     | 
| 
      
 1314 
     | 
    
         
            +
                    attr_reader :action
         
     | 
| 
      
 1315 
     | 
    
         
            +
                    # @return [Hash] Params for the task
         
     | 
| 
      
 1316 
     | 
    
         
            +
                    attr_reader :params
         
     | 
| 
       1076 
1317 
     | 
    
         | 
| 
      
 1318 
     | 
    
         
            +
                    # @param [BaseModel] object The task's subject
         
     | 
| 
      
 1319 
     | 
    
         
            +
                    # @param [Symbol] action
         
     | 
| 
      
 1320 
     | 
    
         
            +
                    # @param [Hash] params
         
     | 
| 
       1077 
1321 
     | 
    
         
             
                    def initialize(object, action, params={})
         
     | 
| 
       1078 
1322 
     | 
    
         
             
                        @object = object
         
     | 
| 
       1079 
1323 
     | 
    
         
             
                        @action = action
         
     | 
| 
         @@ -1081,17 +1325,23 @@ module Spider; module Model 
     | 
|
| 
       1081 
1325 
     | 
    
         
             
                        @dependencies = []
         
     | 
| 
       1082 
1326 
     | 
    
         
             
                    end
         
     | 
| 
       1083 
1327 
     | 
    
         | 
| 
      
 1328 
     | 
    
         
            +
                    # Addes a dependency to the Task
         
     | 
| 
      
 1329 
     | 
    
         
            +
                    # @param [MapperTask] task
         
     | 
| 
      
 1330 
     | 
    
         
            +
                    # @return [void]
         
     | 
| 
       1084 
1331 
     | 
    
         
             
                    def <<(task)
         
     | 
| 
       1085 
1332 
     | 
    
         
             
                        @dependencies << task
         
     | 
| 
       1086 
1333 
     | 
    
         
             
                    end
         
     | 
| 
       1087 
1334 
     | 
    
         | 
| 
       1088 
     | 
    
         
            -
                     
     | 
| 
      
 1335 
     | 
    
         
            +
                    # Makes the objects' mapper run the task
         
     | 
| 
      
 1336 
     | 
    
         
            +
                    # @return [void]
         
     | 
| 
      
 1337 
     | 
    
         
            +
                    def execute
         
     | 
| 
       1089 
1338 
     | 
    
         
             
                        debug_str = "Executing #{@action} on #{@object.inspect}"
         
     | 
| 
       1090 
1339 
     | 
    
         
             
                        debug_str += " (#{@params.inspect})" unless @params.empty?
         
     | 
| 
       1091 
1340 
     | 
    
         
             
                        Spider::Logger.debug debug_str
         
     | 
| 
       1092 
1341 
     | 
    
         
             
                        @object.mapper.execute_action(@action, @object, @params)
         
     | 
| 
       1093 
1342 
     | 
    
         
             
                    end
         
     | 
| 
       1094 
1343 
     | 
    
         | 
| 
      
 1344 
     | 
    
         
            +
                    # @return [bool] True if the other task has the same object, action and params, false otherwise
         
     | 
| 
       1095 
1345 
     | 
    
         
             
                    def eql?(task)
         
     | 
| 
       1096 
1346 
     | 
    
         
             
                        return false unless task.class == self.class
         
     | 
| 
       1097 
1347 
     | 
    
         
             
                        return false unless (task.object == self.object && task.action == self.action)
         
     | 
| 
         @@ -1101,10 +1351,12 @@ module Spider; module Model 
     | 
|
| 
       1101 
1351 
     | 
    
         
             
                        return true
         
     | 
| 
       1102 
1352 
     | 
    
         
             
                    end
         
     | 
| 
       1103 
1353 
     | 
    
         | 
| 
      
 1354 
     | 
    
         
            +
                    # @return [String] Hash for keying
         
     | 
| 
       1104 
1355 
     | 
    
         
             
                    def hash
         
     | 
| 
       1105 
1356 
     | 
    
         
             
                        return @object.hash + @action.hash
         
     | 
| 
       1106 
1357 
     | 
    
         
             
                    end
         
     | 
| 
       1107 
1358 
     | 
    
         | 
| 
      
 1359 
     | 
    
         
            +
                    # @return [bool] Same as #eql?
         
     | 
| 
       1108 
1360 
     | 
    
         
             
                    def ===(task)
         
     | 
| 
       1109 
1361 
     | 
    
         
             
                        return eql?(task)
         
     | 
| 
       1110 
1362 
     | 
    
         
             
                    end
         
     | 
| 
         @@ -1113,6 +1365,7 @@ module Spider; module Model 
     | 
|
| 
       1113 
1365 
     | 
    
         
             
                    #     "#{@action} on #{@object} (#{object.class})\n"
         
     | 
| 
       1114 
1366 
     | 
    
         
             
                    # end
         
     | 
| 
       1115 
1367 
     | 
    
         | 
| 
      
 1368 
     | 
    
         
            +
                    # @return [String] A textual representation of the Task
         
     | 
| 
       1116 
1369 
     | 
    
         
             
                    def inspect
         
     | 
| 
       1117 
1370 
     | 
    
         
             
                        if (@action && @object)
         
     | 
| 
       1118 
1371 
     | 
    
         
             
                            str = "#{@action} on #{@object}##{@object.object_id} (#{object.class})"
         
     | 
| 
         @@ -1132,25 +1385,16 @@ module Spider; module Model 
     | 
|
| 
       1132 
1385 
     | 
    
         | 
| 
       1133 
1386 
     | 
    
         
             
                end
         
     | 
| 
       1134 
1387 
     | 
    
         | 
| 
       1135 
     | 
    
         
            -
             
     | 
| 
       1136 
     | 
    
         
            -
                #   Aggregates                                               #
         
     | 
| 
       1137 
     | 
    
         
            -
                ##############################################################
         
     | 
| 
       1138 
     | 
    
         
            -
                
         
     | 
| 
       1139 
     | 
    
         
            -
                def max(element, condition=nil)
         
     | 
| 
       1140 
     | 
    
         
            -
                    raise "Unimplemented"
         
     | 
| 
       1141 
     | 
    
         
            -
                end
         
     | 
| 
       1142 
     | 
    
         
            -
                
         
     | 
| 
      
 1388 
     | 
    
         
            +
             
         
     | 
| 
       1143 
1389 
     | 
    
         | 
| 
       1144 
1390 
     | 
    
         
             
                ##############################################################
         
     | 
| 
       1145 
1391 
     | 
    
         
             
                #   Exceptions                                               #
         
     | 
| 
       1146 
1392 
     | 
    
         
             
                ##############################################################
         
     | 
| 
       1147 
1393 
     | 
    
         | 
| 
       1148 
1394 
     | 
    
         
             
                # Generic Mapper error.
         
     | 
| 
       1149 
     | 
    
         
            -
                
         
     | 
| 
       1150 
1395 
     | 
    
         
             
                class MapperError < RuntimeError; end
         
     | 
| 
       1151 
1396 
     | 
    
         | 
| 
       1152 
1397 
     | 
    
         
             
                # Generic Mapper error regarding an element.
         
     | 
| 
       1153 
     | 
    
         
            -
                
         
     | 
| 
       1154 
1398 
     | 
    
         
             
                class MapperElementError < MapperError
         
     | 
| 
       1155 
1399 
     | 
    
         
             
                    def initialize(element)
         
     | 
| 
       1156 
1400 
     | 
    
         
             
                        @element = element
         
     | 
| 
         @@ -1178,14 +1422,13 @@ module Spider; module Model 
     | 
|
| 
       1178 
1422 
     | 
    
         
             
                end
         
     | 
| 
       1179 
1423 
     | 
    
         | 
| 
       1180 
1424 
     | 
    
         
             
                # A required element has no value
         
     | 
| 
       1181 
     | 
    
         
            -
                
         
     | 
| 
       1182 
1425 
     | 
    
         
             
                RequiredError = MapperElementError.create_subclass(_("Element %s is required"))
         
     | 
| 
       1183 
1426 
     | 
    
         | 
| 
       1184 
1427 
     | 
    
         
             
                # An uniqueness constraint has been violated.
         
     | 
| 
       1185 
     | 
    
         
            -
                
         
     | 
| 
       1186 
1428 
     | 
    
         
             
                NotUniqueError = MapperElementError.create_subclass(_("Another item with the same %s is already present"))
         
     | 
| 
       1187 
1429 
     | 
    
         | 
| 
       1188 
1430 
     | 
    
         | 
| 
      
 1431 
     | 
    
         
            +
                # Helper module to hold methods overridden by {BaseModel.with_mapper}
         
     | 
| 
       1189 
1432 
     | 
    
         
             
                module MapperIncludeModule
         
     | 
| 
       1190 
1433 
     | 
    
         | 
| 
       1191 
1434 
     | 
    
         
             
                    def self.included(mod)
         
     |