datashift 0.15.0 → 0.16.0
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.
- checksums.yaml +7 -0
 - data/README.markdown +91 -55
 - data/VERSION +1 -1
 - data/datashift.gemspec +8 -23
 - data/lib/applications/jexcel_file.rb +1 -2
 - data/lib/datashift.rb +34 -15
 - data/lib/datashift/column_packer.rb +98 -34
 - data/lib/datashift/data_transforms.rb +83 -0
 - data/lib/datashift/delimiters.rb +58 -10
 - data/lib/datashift/excel_base.rb +123 -0
 - data/lib/datashift/exceptions.rb +45 -7
 - data/lib/datashift/load_object.rb +25 -0
 - data/lib/datashift/mapping_service.rb +91 -0
 - data/lib/datashift/method_detail.rb +40 -62
 - data/lib/datashift/method_details_manager.rb +18 -2
 - data/lib/datashift/method_dictionary.rb +27 -10
 - data/lib/datashift/method_mapper.rb +49 -41
 - data/lib/datashift/model_mapper.rb +42 -22
 - data/lib/datashift/populator.rb +258 -143
 - data/lib/datashift/thor_base.rb +38 -0
 - data/lib/exporters/csv_exporter.rb +57 -145
 - data/lib/exporters/excel_exporter.rb +73 -60
 - data/lib/generators/csv_generator.rb +65 -5
 - data/lib/generators/generator_base.rb +69 -3
 - data/lib/generators/mapping_generator.rb +112 -0
 - data/lib/helpers/core_ext/csv_file.rb +33 -0
 - data/lib/loaders/csv_loader.rb +41 -39
 - data/lib/loaders/excel_loader.rb +130 -116
 - data/lib/loaders/loader_base.rb +190 -146
 - data/lib/loaders/paperclip/attachment_loader.rb +4 -4
 - data/lib/loaders/paperclip/datashift_paperclip.rb +5 -3
 - data/lib/loaders/paperclip/image_loading.rb +9 -7
 - data/lib/loaders/reporter.rb +17 -8
 - data/lib/thor/export.thor +12 -13
 - data/lib/thor/generate.thor +1 -9
 - data/lib/thor/import.thor +13 -24
 - data/lib/thor/mapping.thor +65 -0
 - data/spec/Gemfile +13 -11
 - data/spec/Gemfile.lock +98 -93
 - data/spec/csv_exporter_spec.rb +104 -99
 - data/spec/csv_generator_spec.rb +159 -0
 - data/spec/csv_loader_spec.rb +197 -16
 - data/spec/datashift_spec.rb +9 -0
 - data/spec/excel_exporter_spec.rb +149 -58
 - data/spec/excel_generator_spec.rb +35 -44
 - data/spec/excel_loader_spec.rb +196 -178
 - data/spec/excel_spec.rb +8 -5
 - data/spec/loader_base_spec.rb +47 -7
 - data/spec/mapping_spec.rb +117 -0
 - data/spec/method_dictionary_spec.rb +24 -11
 - data/spec/method_mapper_spec.rb +5 -7
 - data/spec/model_mapper_spec.rb +41 -0
 - data/spec/paperclip_loader_spec.rb +3 -6
 - data/spec/populator_spec.rb +48 -14
 - data/spec/spec_helper.rb +85 -73
 - data/spec/thor_spec.rb +40 -5
 - metadata +93 -86
 - data/lib/applications/excel_base.rb +0 -63
 
    
        checksums.yaml
    ADDED
    
    | 
         @@ -0,0 +1,7 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            ---
         
     | 
| 
      
 2 
     | 
    
         
            +
            SHA1:
         
     | 
| 
      
 3 
     | 
    
         
            +
              metadata.gz: 4e73de99a2466b06c8dfb6bab01cb7c2ab00fb54
         
     | 
| 
      
 4 
     | 
    
         
            +
              data.tar.gz: 73c47634a567004886c55e75b1f03a63a75ff155
         
     | 
| 
      
 5 
     | 
    
         
            +
            SHA512:
         
     | 
| 
      
 6 
     | 
    
         
            +
              metadata.gz: ec2035080b4d6cfc1560530639084e35271f2716a6772f0b8ada9d2d62752f8c3e5756babc4e5bc9afa83636b9adef4c047bc5db99ad26e31e8e75e51ff3b89d
         
     | 
| 
      
 7 
     | 
    
         
            +
              data.tar.gz: 426c72aadaab70fa3e1a09c8b131a0b862e75d94ad138316474cf75cf9af0a27aaf7d72037f85404d94dbdab7c668b8a47f5939da56914d0c6591421fd79fd4a
         
     | 
    
        data/README.markdown
    CHANGED
    
    | 
         @@ -1,59 +1,20 @@ 
     | 
|
| 
       1 
1 
     | 
    
         
             
            ##  DataShift 
         
     | 
| 
       2 
2 
     | 
    
         | 
| 
      
 3 
     | 
    
         
            +
            - [Installation](#Installation)
         
     | 
| 
       3 
4 
     | 
    
         
             
            - [Features](#features)
         
     | 
| 
       4 
     | 
    
         
            -
            - [ 
     | 
| 
       5 
     | 
    
         
            -
            - [Active Record - Import/Export](#Active Record - Import/Export)
         
     | 
| 
      
 5 
     | 
    
         
            +
            - [Testing](#testing)
         
     | 
| 
       6 
6 
     | 
    
         
             
            - [License](#license)
         
     | 
| 
       7 
7 
     | 
    
         | 
| 
       8 
     | 
    
         
            -
             
     | 
| 
       9 
     | 
    
         
            -
             
     | 
| 
       10 
     | 
    
         
            -
            Import and export models fully with all associations.
         
     | 
| 
      
 8 
     | 
    
         
            +
            Shift data between Excel/CSV files and Rails or Ruby applications
         
     | 
| 
       11 
9 
     | 
    
         | 
| 
       12 
10 
     | 
    
         
             
            Comprehensive Wiki here : **https://github.com/autotelik/datashift/wiki**
         
     | 
| 
       13 
11 
     | 
    
         | 
| 
       14 
     | 
    
         
            -
             
     | 
| 
       15 
     | 
    
         
            -
            now separate gem at [datashift_spree](https://github.com/autotelik/datashift_spree "Datashift Spree")
         
     | 
| 
       16 
     | 
    
         
            -
             
     | 
| 
       17 
     | 
    
         
            -
             
     | 
| 
       18 
     | 
    
         
            -
            ### Features
         
     | 
| 
       19 
     | 
    
         
            -
             
     | 
| 
       20 
     | 
    
         
            -
            Import and Export ActiveRecord models direct to CSV or Excel/OpenOffice (.xls) (JRuby, 1.8.7, REE, 1.9.3)
         
     | 
| 
       21 
     | 
    
         
            -
             
     | 
| 
       22 
     | 
    
         
            -
            You can select which associations to include and for import, set configurable defaults or over rides.
         
     | 
| 
       23 
     | 
    
         
            -
             
     | 
| 
       24 
     | 
    
         
            -
            Create, parse and use Excel/OpenOffice (.xls) documents dynamically from Ruby (JRuby, 1.8.7, REE, 1.9.3)
         
     | 
| 
       25 
     | 
    
         
            -
             
     | 
| 
       26 
     | 
    
         
            -
            Generate a sample template with headers only.
         
     | 
| 
       27 
     | 
    
         
            -
             
     | 
| 
       28 
     | 
    
         
            -
            Export template and populate with model data 
         
     | 
| 
       29 
     | 
    
         
            -
             
     | 
| 
       30 
     | 
    
         
            -
            Bulk import tools for Paperclip attachments.
         
     | 
| 
       31 
     | 
    
         
            -
             
     | 
| 
       32 
     | 
    
         
            -
            Easily extendable Loader functionality to deal with non trivial import cases, such
         
     | 
| 
       33 
     | 
    
         
            -
            as complex association lookups.
         
     | 
| 
       34 
     | 
    
         
            -
             
     | 
| 
       35 
     | 
    
         
            -
            High level rake and thor command line tasks for import/export provided.
         
     | 
| 
       36 
     | 
    
         
            -
             
     | 
| 
       37 
     | 
    
         
            -
            Specific loaders and command line tasks provided out the box for **Spree E-Commerce**, 
         
     | 
| 
       38 
     | 
    
         
            -
            enabling import/export of Product data including creating Variants with different
         
     | 
| 
       39 
     | 
    
         
            -
             count on hands and all associations including Properties/Taxons/OptionTypes and Images.
         
     | 
| 
       40 
     | 
    
         
            -
             
     | 
| 
       41 
     | 
    
         
            -
            Loaders can be configured via YAML with over ride values, default values and mandatory column settings.
         
     | 
| 
       42 
     | 
    
         
            -
             
     | 
| 
       43 
     | 
    
         
            -
            Many example Spreadsheets/CSV files in spec/fixtures, fully documented with comments for each column.
         
     | 
| 
       44 
     | 
    
         
            -
             
     | 
| 
       45 
     | 
    
         
            -
            ## Installation
         
     | 
| 
      
 12 
     | 
    
         
            +
            ### <a name="Installation">Installation</a>
         
     | 
| 
       46 
13 
     | 
    
         | 
| 
       47 
14 
     | 
    
         
             
            Add gem 'datashift' to your Gemfile/bundle or use ```gem install```
         
     | 
| 
       48 
15 
     | 
    
         | 
| 
       49 
     | 
    
         
            -
            ```ruby 
     | 
| 
       50 
     | 
    
         
            -
            gem 'datashift' 
     | 
| 
       51 
     | 
    
         
            -
            ```
         
     | 
| 
       52 
     | 
    
         
            -
             
     | 
| 
       53 
     | 
    
         
            -
            For Spree support also add :
         
     | 
| 
       54 
     | 
    
         
            -
             
     | 
| 
       55 
     | 
    
         
            -
            ```ruby 
         
     | 
| 
       56 
     | 
    
         
            -
            gem 'datashift_spree'
         
     | 
| 
      
 16 
     | 
    
         
            +
            ```ruby
         
     | 
| 
      
 17 
     | 
    
         
            +
            gem 'datashift'
         
     | 
| 
       57 
18 
     | 
    
         
             
            ```
         
     | 
| 
       58 
19 
     | 
    
         | 
| 
       59 
20 
     | 
    
         
             
            To use :
         
     | 
| 
         @@ -64,7 +25,7 @@ To use the Thor command line applications, pull in the tasks. 
     | 
|
| 
       64 
25 
     | 
    
         | 
| 
       65 
26 
     | 
    
         
             
            Generally the easiest way is to, create a high level .thor file in your Rails root directory
         
     | 
| 
       66 
27 
     | 
    
         | 
| 
       67 
     | 
    
         
            -
                e.g mysite.thor 
     | 
| 
      
 28 
     | 
    
         
            +
                e.g mysite.thor
         
     | 
| 
       68 
29 
     | 
    
         | 
| 
       69 
30 
     | 
    
         
             
            Edit the file and add the following to pull in the thor commands :
         
     | 
| 
       70 
31 
     | 
    
         | 
| 
         @@ -89,6 +50,33 @@ To get usage information use thor help <command>, for example 
     | 
|
| 
       89 
50 
     | 
    
         | 
| 
       90 
51 
     | 
    
         
             
            To use Excel OLE and MS Excel are NOT required.
         
     | 
| 
       91 
52 
     | 
    
         | 
| 
      
 53 
     | 
    
         
            +
            Specific tools for Spree E-Commerce now separate gem [datashift_spree](https://github.com/autotelik/datashift_spree "Datashift Spree")
         
     | 
| 
      
 54 
     | 
    
         
            +
             
     | 
| 
      
 55 
     | 
    
         
            +
             
     | 
| 
      
 56 
     | 
    
         
            +
            #### <a name="Features">Features</a>
         
     | 
| 
      
 57 
     | 
    
         
            +
             
     | 
| 
      
 58 
     | 
    
         
            +
            Import and Export ActiveRecord models direct to CSV or Excel/OpenOffice (.xls)
         
     | 
| 
      
 59 
     | 
    
         
            +
             
     | 
| 
      
 60 
     | 
    
         
            +
            You can select which associations to include and for import, set configurable defaults or over rides.
         
     | 
| 
      
 61 
     | 
    
         
            +
             
     | 
| 
      
 62 
     | 
    
         
            +
            Create, parse and use Excel/OpenOffice (.xls) documents dynamically from Ruby
         
     | 
| 
      
 63 
     | 
    
         
            +
             
     | 
| 
      
 64 
     | 
    
         
            +
            Generate a sample template with headers only.
         
     | 
| 
      
 65 
     | 
    
         
            +
             
     | 
| 
      
 66 
     | 
    
         
            +
            Export template and populate with model data 
         
     | 
| 
      
 67 
     | 
    
         
            +
             
     | 
| 
      
 68 
     | 
    
         
            +
            Bulk import tools for Paperclip attachments.
         
     | 
| 
      
 69 
     | 
    
         
            +
             
     | 
| 
      
 70 
     | 
    
         
            +
            Easily extendable Loader functionality to deal with non trivial import cases, such
         
     | 
| 
      
 71 
     | 
    
         
            +
            as complex association lookups.
         
     | 
| 
      
 72 
     | 
    
         
            +
             
     | 
| 
      
 73 
     | 
    
         
            +
            High level rake and thor command line tasks for import/export provided.
         
     | 
| 
      
 74 
     | 
    
         
            +
             
     | 
| 
      
 75 
     | 
    
         
            +
             
     | 
| 
      
 76 
     | 
    
         
            +
            Loaders can be configured via YAML with over ride values, default values and mandatory column settings.
         
     | 
| 
      
 77 
     | 
    
         
            +
             
     | 
| 
      
 78 
     | 
    
         
            +
            Many example Spreadsheets/CSV files in spec/fixtures, fully documented with comments for each column.
         
     | 
| 
      
 79 
     | 
    
         
            +
             
     | 
| 
       92 
80 
     | 
    
         
             
            Features a common Excel interface over both our own wrapper around Apache POI (JRuby) and spreadsheet gem (all main Rubies) 
         
     | 
| 
       93 
81 
     | 
    
         | 
| 
       94 
82 
     | 
    
         
             
            This means you can switch seamlessly between the two libraries, and if required drop down to make use of advanced
         
     | 
| 
         @@ -102,7 +90,7 @@ Guards are provided, and used internally, for mixed Ruby setups. Can be used lik 
     | 
|
| 
       102 
90 
     | 
    
         
             
                    ..do something with speadsheet
         
     | 
| 
       103 
91 
     | 
    
         
             
                end
         
     | 
| 
       104 
92 
     | 
    
         | 
| 
       105 
     | 
    
         
            -
             
     | 
| 
      
 93 
     | 
    
         
            +
            #### Active Record - Import/Export
         
     | 
| 
       106 
94 
     | 
    
         | 
| 
       107 
95 
     | 
    
         
             
            Provides high level tasks for importing data via ActiveRecord models into a DB,
         
     | 
| 
       108 
96 
     | 
    
         
             
             from various sources, currently csv or .xls files (Excel/Open Office)
         
     | 
| 
         @@ -145,7 +133,7 @@ complicated lookup requirements. Spree is the prime Open Source e-commerce proje 
     | 
|
| 
       145 
133 
     | 
    
         
             
            and the specific loaders and tasks support loading Spree Products, and associated data such as Variants,
         
     | 
| 
       146 
134 
     | 
    
         
             
            OptionTypes, Properties and Images.
         
     | 
| 
       147 
135 
     | 
    
         | 
| 
       148 
     | 
    
         
            -
             
     | 
| 
      
 136 
     | 
    
         
            +
            #### Template Generation and Export
         
     | 
| 
       149 
137 
     | 
    
         | 
| 
       150 
138 
     | 
    
         
             
            Template generation tasks can be used to export a model's definition as column headings to CSV or .xls.
         
     | 
| 
       151 
139 
     | 
    
         
             
            These can be provided to developers or business users, as a template for data collection and then loading.
         
     | 
| 
         @@ -155,7 +143,7 @@ Export tasks can be used to export of a model's definition and any existing data 
     | 
|
| 
       155 
143 
     | 
    
         
             
            This data can be exported directly to CSV or Excel/OpenOffice spreadsheets.
         
     | 
| 
       156 
144 
     | 
    
         | 
| 
       157 
145 
     | 
    
         | 
| 
       158 
     | 
    
         
            -
             
     | 
| 
      
 146 
     | 
    
         
            +
            #### Example Spreadsheets
         
     | 
| 
       159 
147 
     | 
    
         | 
| 
       160 
148 
     | 
    
         
             
              A number of example Spreadsheets with headers and comments, can be found in the spec/fixtures directory.
         
     | 
| 
       161 
149 
     | 
    
         | 
| 
         @@ -165,7 +153,7 @@ This data can be exported directly to CSV or Excel/OpenOffice spreadsheets. 
     | 
|
| 
       165 
153 
     | 
    
         
             
              Column headings contain comments with full descriptions and instructions on syntax. 
         
     | 
| 
       166 
154 
     | 
    
         | 
| 
       167 
155 
     | 
    
         | 
| 
       168 
     | 
    
         
            -
             
     | 
| 
      
 156 
     | 
    
         
            +
            #### Excel
         
     | 
| 
       169 
157 
     | 
    
         | 
| 
       170 
158 
     | 
    
         | 
| 
       171 
159 
     | 
    
         
             
              MS Excel itself does not need to be installed.
         
     | 
| 
         @@ -181,7 +169,7 @@ This data can be exported directly to CSV or Excel/OpenOffice spreadsheets. 
     | 
|
| 
       181 
169 
     | 
    
         
             
              without converting first to CSV or YAML.
         
     | 
| 
       182 
170 
     | 
    
         | 
| 
       183 
171 
     | 
    
         | 
| 
       184 
     | 
    
         
            -
             
     | 
| 
      
 172 
     | 
    
         
            +
            #### Associations
         
     | 
| 
       185 
173 
     | 
    
         | 
| 
       186 
174 
     | 
    
         
             
            To perform a lookup for an associated model, the primary column(s) must be supplied, along with required select values for those columns.
         
     | 
| 
       187 
175 
     | 
    
         | 
| 
         @@ -199,7 +187,7 @@ During loading, a call to find_all_by_reference will be made, picking up the 2 c 
     | 
|
| 
       199 
187 
     | 
    
         
             
             and our Project model will contain those two i.e project.categories = [category_002,category_003]
         
     | 
| 
       200 
188 
     | 
    
         | 
| 
       201 
189 
     | 
    
         | 
| 
       202 
     | 
    
         
            -
             
     | 
| 
      
 190 
     | 
    
         
            +
            ### TODO
         
     | 
| 
       203 
191 
     | 
    
         | 
| 
       204 
192 
     | 
    
         
             
              - Smart sorting of column processing order ....
         
     | 
| 
       205 
193 
     | 
    
         | 
| 
         @@ -208,14 +196,62 @@ During loading, a call to find_all_by_reference will be made, picking up the 2 c 
     | 
|
| 
       208 
196 
     | 
    
         
             
              - Look at implementing import/export API using something like https://github.com/ianwhite/orm_adapter 
         
     | 
| 
       209 
197 
     | 
    
         
             
                rather than active record, so we can support additional ORMs
         
     | 
| 
       210 
198 
     | 
    
         | 
| 
       211 
     | 
    
         
            -
             
     | 
| 
      
 199 
     | 
    
         
            +
             
     | 
| 
      
 200 
     | 
    
         
            +
            ### <a name="Testing">Testing</a>
         
     | 
| 
      
 201 
     | 
    
         
            +
                Specs have own Gemfile, so you can specify versions of active record that you want  specs to run against :
         
     | 
| 
      
 202 
     | 
    
         
            +
             
     | 
| 
      
 203 
     | 
    
         
            +
                Edit
         
     | 
| 
      
 204 
     | 
    
         
            +
                    ```ruby spec/Gemfile. ```
         
     | 
| 
      
 205 
     | 
    
         
            +
             
     | 
| 
      
 206 
     | 
    
         
            +
                Then run :
         
     | 
| 
      
 207 
     | 
    
         
            +
             
     | 
| 
      
 208 
     | 
    
         
            +
                ```ruby
         
     | 
| 
      
 209 
     | 
    
         
            +
                cd spec
         
     | 
| 
      
 210 
     | 
    
         
            +
                bundle install
         
     | 
| 
      
 211 
     | 
    
         
            +
                ```
         
     | 
| 
      
 212 
     | 
    
         
            +
             
     | 
| 
      
 213 
     | 
    
         
            +
            ####  Changing Versions
         
     | 
| 
      
 214 
     | 
    
         
            +
             
     | 
| 
      
 215 
     | 
    
         
            +
                A sandbox will be generated in spec/sandbox if no such directory exists.
         
     | 
| 
      
 216 
     | 
    
         
            +
             
     | 
| 
      
 217 
     | 
    
         
            +
                **N.B Manual Step**
         
     | 
| 
      
 218 
     | 
    
         
            +
                When changing versions you probably need to **delete this whole directory**  spec/sandbox. Next time you run spree specs it will be auto generated using latest Rails versions
         
     | 
| 
      
 219 
     | 
    
         
            +
             
     | 
| 
      
 220 
     | 
    
         
            +
                The database are created in sqlite3 and are stored in spec/fixtures. When switching versions, of say Spree,
         
     | 
| 
      
 221 
     | 
    
         
            +
                 you will probably want to and to clear out old versions and retrigger the migrations
         
     | 
| 
      
 222 
     | 
    
         
            +
             
     | 
| 
      
 223 
     | 
    
         
            +
                    rm spec/fixtures/*.sqlite
         
     | 
| 
      
 224 
     | 
    
         
            +
             
     | 
| 
      
 225 
     | 
    
         
            +
                You will probably also want to remove lock file :
         
     | 
| 
      
 226 
     | 
    
         
            +
             
     | 
| 
      
 227 
     | 
    
         
            +
                    rm spec/Gemfile.lock
         
     | 
| 
      
 228 
     | 
    
         
            +
             
     | 
| 
      
 229 
     | 
    
         
            +
                First time the sandbox is regenerated, alot of tests may fail,perhaps not everything loads correctly during regeneration process.
         
     | 
| 
      
 230 
     | 
    
         
            +
             
     | 
| 
      
 231 
     | 
    
         
            +
                Invariably the next run, the specs pass, so a fix is low priority.
         
     | 
| 
      
 232 
     | 
    
         
            +
             
     | 
| 
      
 233 
     | 
    
         
            +
            #### Run the Tests
         
     | 
| 
      
 234 
     | 
    
         
            +
             
     | 
| 
      
 235 
     | 
    
         
            +
                ** N.B You should run the specs from within the specs directory. **
         
     | 
| 
      
 236 
     | 
    
         
            +
                ```ruby
         
     | 
| 
      
 237 
     | 
    
         
            +
                    bundle exec rspec -c .
         
     | 
| 
      
 238 
     | 
    
         
            +
                ```
         
     | 
| 
      
 239 
     | 
    
         
            +
             
     | 
| 
      
 240 
     | 
    
         
            +
                A datashift **log **will be written within **spec/logs**, which hooks into the standard active record logger
         
     | 
| 
      
 241 
     | 
    
         
            +
             
     | 
| 
      
 242 
     | 
    
         
            +
                      /log/datashift.log
         
     | 
| 
      
 243 
     | 
    
         
            +
                      spec/logs/datashift_spec.log
         
     | 
| 
      
 244 
     | 
    
         
            +
             
     | 
| 
      
 245 
     | 
    
         
            +
             
     | 
| 
      
 246 
     | 
    
         
            +
             
     | 
| 
      
 247 
     | 
    
         
            +
             
     | 
| 
       212 
248 
     | 
    
         
             
            ## License
         
     | 
| 
       213 
249 
     | 
    
         | 
| 
       214 
     | 
    
         
            -
            Copyright:: (c) Autotelik Media Ltd  
     | 
| 
      
 250 
     | 
    
         
            +
            Copyright:: (c) Autotelik Media Ltd 2015
         
     | 
| 
       215 
251 
     | 
    
         | 
| 
       216 
252 
     | 
    
         
             
            Author ::   Tom Statter
         
     | 
| 
       217 
253 
     | 
    
         | 
| 
       218 
     | 
    
         
            -
            Date ::     Dec  
     | 
| 
      
 254 
     | 
    
         
            +
            Date ::     Dec 2015
         
     | 
| 
       219 
255 
     | 
    
         | 
| 
       220 
256 
     | 
    
         
             
            The MIT License
         
     | 
| 
       221 
257 
     | 
    
         | 
    
        data/VERSION
    CHANGED
    
    | 
         @@ -1 +1 @@ 
     | 
|
| 
       1 
     | 
    
         
            -
            0. 
     | 
| 
      
 1 
     | 
    
         
            +
            0.16.0
         
     | 
    
        data/datashift.gemspec
    CHANGED
    
    | 
         @@ -1,21 +1,16 @@ 
     | 
|
| 
       1 
1 
     | 
    
         
             
            require 'rake'
         
     | 
| 
       2 
2 
     | 
    
         | 
| 
       3 
     | 
    
         
            -
             
     | 
| 
       4 
     | 
    
         
            -
             
     | 
| 
       5 
     | 
    
         
            -
            $:.unshift lib unless $:.include?(lib)
         
     | 
| 
       6 
     | 
    
         
            -
             
     | 
| 
       7 
     | 
    
         
            -
            require 'datashift'
         
     | 
| 
      
 3 
     | 
    
         
            +
            #TODO version = File.read("VERSION").strip
         
     | 
| 
       8 
4 
     | 
    
         | 
| 
       9 
5 
     | 
    
         
             
            Gem::Specification.new do |s|
         
     | 
| 
       10 
6 
     | 
    
         
             
              s.name = "datashift"
         
     | 
| 
       11 
     | 
    
         
            -
              s.version =  
     | 
| 
       12 
     | 
    
         
            -
              s.date = Date.today.to_s
         
     | 
| 
      
 7 
     | 
    
         
            +
              s.version = "0.16.0"
         
     | 
| 
       13 
8 
     | 
    
         | 
| 
       14 
9 
     | 
    
         
             
              s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
         
     | 
| 
       15 
10 
     | 
    
         | 
| 
       16 
11 
     | 
    
         
             
              s.authors = ["Thomas Statter"]
         
     | 
| 
       17 
12 
     | 
    
         | 
| 
       18 
     | 
    
         
            -
              s.description = "Comprehensive  
     | 
| 
      
 13 
     | 
    
         
            +
              s.description = "Comprehensive import/export tools between Excel/CSV & ActiveRecord Databases, Rails apps, and any Ruby project."
         
     | 
| 
       19 
14 
     | 
    
         
             
              s.email = "rubygems@autotelik.co.uk"
         
     | 
| 
       20 
15 
     | 
    
         
             
              s.extra_rdoc_files = [
         
     | 
| 
       21 
16 
     | 
    
         
             
                "LICENSE.txt",
         
     | 
| 
         @@ -42,22 +37,12 @@ Gem::Specification.new do |s| 
     | 
|
| 
       42 
37 
     | 
    
         
             
              s.homepage = "http://github.com/autotelik/datashift"
         
     | 
| 
       43 
38 
     | 
    
         
             
              s.licenses = ["MIT"]
         
     | 
| 
       44 
39 
     | 
    
         
             
              s.require_paths = ["lib"]
         
     | 
| 
       45 
     | 
    
         
            -
             
     | 
| 
      
 40 
     | 
    
         
            +
             
     | 
| 
       46 
41 
     | 
    
         
             
              s.summary = "Shift data betwen Excel/CSV and any Ruby app"
         
     | 
| 
       47 
42 
     | 
    
         | 
| 
       48 
     | 
    
         
            -
               
     | 
| 
       49 
     | 
    
         
            -
             
     | 
| 
       50 
     | 
    
         
            -
             
     | 
| 
       51 
     | 
    
         
            -
             
     | 
| 
       52 
     | 
    
         
            -
                  s.add_runtime_dependency(%q<spreadsheet>, [">= 0"])
         
     | 
| 
       53 
     | 
    
         
            -
                  s.add_runtime_dependency(%q<rubyzip>, [">= 0"])
         
     | 
| 
       54 
     | 
    
         
            -
                else
         
     | 
| 
       55 
     | 
    
         
            -
                  s.add_dependency(%q<spreadsheet>, [">= 0"])
         
     | 
| 
       56 
     | 
    
         
            -
                  s.add_dependency(%q<rubyzip>, [">= 0"])
         
     | 
| 
       57 
     | 
    
         
            -
                end
         
     | 
| 
       58 
     | 
    
         
            -
              else
         
     | 
| 
       59 
     | 
    
         
            -
                s.add_dependency(%q<spreadsheet>, [">= 0"])
         
     | 
| 
       60 
     | 
    
         
            -
                s.add_dependency(%q<rubyzip>, [">= 0"])
         
     | 
| 
       61 
     | 
    
         
            -
              end
         
     | 
| 
      
 43 
     | 
    
         
            +
              s.add_dependency 'spreadsheet'
         
     | 
| 
      
 44 
     | 
    
         
            +
              s.add_dependency 'rubyzip'
         
     | 
| 
      
 45 
     | 
    
         
            +
             
     | 
| 
      
 46 
     | 
    
         
            +
             
     | 
| 
       62 
47 
     | 
    
         
             
            end
         
     | 
| 
       63 
48 
     | 
    
         | 
    
        data/lib/datashift.rb
    CHANGED
    
    | 
         @@ -25,7 +25,7 @@ 
     | 
|
| 
       25 
25 
     | 
    
         | 
| 
       26 
26 
     | 
    
         | 
| 
       27 
27 
     | 
    
         
             
            # Details::   Active Record Import/Export for .xls or CSV
         
     | 
| 
       28 
     | 
    
         
            -
            # 
     | 
| 
      
 28 
     | 
    
         
            +
            #
         
     | 
| 
       29 
29 
     | 
    
         
             
            # To pull DataShift commands into your main application :
         
     | 
| 
       30 
30 
     | 
    
         
             
            #
         
     | 
| 
       31 
31 
     | 
    
         
             
            #     require 'datashift'
         
     | 
| 
         @@ -58,9 +58,9 @@ module DataShift 
     | 
|
| 
       58 
58 
     | 
    
         
             
              def self.library_path
         
     | 
| 
       59 
59 
     | 
    
         
             
                File.expand_path("#{File.dirname(__FILE__)}/../lib")
         
     | 
| 
       60 
60 
     | 
    
         
             
              end
         
     | 
| 
       61 
     | 
    
         
            -
             
     | 
| 
      
 61 
     | 
    
         
            +
             
     | 
| 
       62 
62 
     | 
    
         
             
              def self.require_libraries
         
     | 
| 
       63 
     | 
    
         
            -
             
     | 
| 
      
 63 
     | 
    
         
            +
             
     | 
| 
       64 
64 
     | 
    
         
             
                loader_libs = %w{ lib  }
         
     | 
| 
       65 
65 
     | 
    
         | 
| 
       66 
66 
     | 
    
         
             
                # Base search paths - these will be searched recursively
         
     | 
| 
         @@ -78,8 +78,8 @@ module DataShift 
     | 
|
| 
       78 
78 
     | 
    
         
             
                    end
         
     | 
| 
       79 
79 
     | 
    
         
             
                  end
         
     | 
| 
       80 
80 
     | 
    
         
             
                end
         
     | 
| 
       81 
     | 
    
         
            -
             
     | 
| 
       82 
     | 
    
         
            -
                require_libs = %w{ datashift loaders helpers }
         
     | 
| 
      
 81 
     | 
    
         
            +
             
     | 
| 
      
 82 
     | 
    
         
            +
                require_libs = %w{ datashift loaders generators helpers }
         
     | 
| 
       83 
83 
     | 
    
         | 
| 
       84 
84 
     | 
    
         
             
                require_libs.each do |base|
         
     | 
| 
       85 
85 
     | 
    
         
             
                  Dir[File.join(library_path, base, '*.rb')].each do |rb|
         
     | 
| 
         @@ -90,6 +90,15 @@ module DataShift 
     | 
|
| 
       90 
90 
     | 
    
         
             
                  end
         
     | 
| 
       91 
91 
     | 
    
         
             
                end
         
     | 
| 
       92 
92 
     | 
    
         | 
| 
      
 93 
     | 
    
         
            +
                if(DataShift::Guards.jruby?)
         
     | 
| 
      
 94 
     | 
    
         
            +
                  require 'jexcel_file'
         
     | 
| 
      
 95 
     | 
    
         
            +
                  JExcelFile
         
     | 
| 
      
 96 
     | 
    
         
            +
                else
         
     | 
| 
      
 97 
     | 
    
         
            +
                  require 'spreadsheet'
         
     | 
| 
      
 98 
     | 
    
         
            +
                  require 'spreadsheet_extensions'
         
     | 
| 
      
 99 
     | 
    
         
            +
                  Spreadsheet
         
     | 
| 
      
 100 
     | 
    
         
            +
                end
         
     | 
| 
      
 101 
     | 
    
         
            +
             
     | 
| 
       93 
102 
     | 
    
         
             
              end
         
     | 
| 
       94 
103 
     | 
    
         | 
| 
       95 
104 
     | 
    
         
             
              # Load all the datashift rake tasks and make them available throughout app
         
     | 
| 
         @@ -100,36 +109,46 @@ module DataShift 
     | 
|
| 
       100 
109 
     | 
    
         
             
                Dir["#{base}/*.rake"].sort.each { |ext| load ext }
         
     | 
| 
       101 
110 
     | 
    
         
             
              end
         
     | 
| 
       102 
111 
     | 
    
         | 
| 
       103 
     | 
    
         
            -
             
     | 
| 
      
 112 
     | 
    
         
            +
             
     | 
| 
       104 
113 
     | 
    
         
             
              # Load all the datashift Thor commands and make them available throughout app
         
     | 
| 
       105 
114 
     | 
    
         | 
| 
       106 
115 
     | 
    
         
             
              def self.load_commands()
         
     | 
| 
       107 
116 
     | 
    
         
             
                base = File.join(library_path, 'thor', '**')
         
     | 
| 
       108 
     | 
    
         
            -
             
     | 
| 
      
 117 
     | 
    
         
            +
             
     | 
| 
       109 
118 
     | 
    
         
             
                Dir["#{base}/*.thor"].each do |f|
         
     | 
| 
       110 
119 
     | 
    
         
             
                  next unless File.file?(f)
         
     | 
| 
       111 
120 
     | 
    
         
             
                  Thor::Util.load_thorfile(f)
         
     | 
| 
       112 
121 
     | 
    
         
             
                end
         
     | 
| 
       113 
122 
     | 
    
         
             
              end
         
     | 
| 
       114 
     | 
    
         
            -
             
     | 
| 
      
 123 
     | 
    
         
            +
             
     | 
| 
       115 
124 
     | 
    
         
             
            end
         
     | 
| 
       116 
125 
     | 
    
         | 
| 
      
 126 
     | 
    
         
            +
             
     | 
| 
      
 127 
     | 
    
         
            +
            require_relative 'datashift/delimiters'
         
     | 
| 
      
 128 
     | 
    
         
            +
            require_relative 'datashift/column_packer'
         
     | 
| 
      
 129 
     | 
    
         
            +
            require_relative 'datashift/logging'
         
     | 
| 
      
 130 
     | 
    
         
            +
            require_relative 'datashift/exceptions'
         
     | 
| 
      
 131 
     | 
    
         
            +
            require_relative 'datashift/guards'
         
     | 
| 
      
 132 
     | 
    
         
            +
             
     | 
| 
      
 133 
     | 
    
         
            +
            require_relative 'helpers/core_ext/to_b'
         
     | 
| 
      
 134 
     | 
    
         
            +
            require_relative 'helpers/core_ext/csv_file'
         
     | 
| 
      
 135 
     | 
    
         
            +
             
     | 
| 
      
 136 
     | 
    
         
            +
            require_relative 'datashift/method_detail'
         
     | 
| 
      
 137 
     | 
    
         
            +
            require_relative 'datashift/method_dictionary'
         
     | 
| 
      
 138 
     | 
    
         
            +
            require_relative 'datashift/method_mapper'
         
     | 
| 
      
 139 
     | 
    
         
            +
            require_relative 'datashift/model_mapper'
         
     | 
| 
      
 140 
     | 
    
         
            +
             
     | 
| 
       117 
141 
     | 
    
         
             
            DataShift::require_libraries
         
     | 
| 
       118 
142 
     | 
    
         | 
| 
       119 
     | 
    
         
            -
            require 'datashift/guards'
         
     | 
| 
       120 
     | 
    
         
            -
            require 'datashift/logging'
         
     | 
| 
       121 
     | 
    
         
            -
            require 'datashift/method_detail'
         
     | 
| 
       122 
     | 
    
         
            -
            require 'datashift/method_dictionary'
         
     | 
| 
       123 
     | 
    
         
            -
            require 'datashift/method_mapper'
         
     | 
| 
       124 
143 
     | 
    
         | 
| 
       125 
144 
     | 
    
         
             
            module DataShift
         
     | 
| 
       126 
145 
     | 
    
         
             
              if(Guards::jruby?)
         
     | 
| 
       127 
146 
     | 
    
         
             
                require 'java'
         
     | 
| 
       128 
     | 
    
         
            -
             
     | 
| 
      
 147 
     | 
    
         
            +
             
     | 
| 
       129 
148 
     | 
    
         
             
                class Object
         
     | 
| 
       130 
149 
     | 
    
         
             
                  def add_to_classpath(path)
         
     | 
| 
       131 
150 
     | 
    
         
             
                    $CLASSPATH << File.join( DataShift.root_path, 'lib', path.gsub("\\", "/") )
         
     | 
| 
       132 
151 
     | 
    
         
             
                  end
         
     | 
| 
       133 
152 
     | 
    
         
             
                end
         
     | 
| 
       134 
153 
     | 
    
         
             
              end
         
     | 
| 
       135 
     | 
    
         
            -
            end
         
     | 
| 
      
 154 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -5,60 +5,124 @@ 
     | 
|
| 
       5 
5 
     | 
    
         
             
            #
         
     | 
| 
       6 
6 
     | 
    
         
             
            # Details::   Helper for creating consistent import/export format
         
     | 
| 
       7 
7 
     | 
    
         
             
            #             of model's attributes/associations
         
     | 
| 
       8 
     | 
    
         
            -
            # 
         
     | 
| 
       9 
8 
     | 
    
         
             
            #
         
     | 
| 
       10 
     | 
    
         
            -
            require 'exporter_base'
         
     | 
| 
       11 
     | 
    
         
            -
            require 'csv'
         
     | 
| 
       12 
     | 
    
         
            -
             
     | 
| 
       13 
9 
     | 
    
         
             
            module DataShift
         
     | 
| 
       14 
10 
     | 
    
         | 
| 
       15 
11 
     | 
    
         
             
              module ColumnPacker
         
     | 
| 
       16 
12 
     | 
    
         | 
| 
       17 
     | 
    
         
            -
                
         
     | 
| 
       18 
     | 
    
         
            -
                def text_delim
         
     | 
| 
       19 
     | 
    
         
            -
                  @text_delim ||= "\'"
         
     | 
| 
       20 
     | 
    
         
            -
                end
         
     | 
| 
      
 13 
     | 
    
         
            +
                include Delimiters
         
     | 
| 
       21 
14 
     | 
    
         | 
| 
       22 
     | 
    
         
            -
                def text_delim=(x)
         
     | 
| 
       23 
     | 
    
         
            -
                  @text_delim = x
         
     | 
| 
       24 
     | 
    
         
            -
                end
         
     | 
| 
       25 
     | 
    
         
            -
                
         
     | 
| 
       26 
15 
     | 
    
         
             
                # Return opposite of text delim - "hello, 'barry'" => '"hello, "barry""'
         
     | 
| 
       27 
16 
     | 
    
         
             
                def escape_text_delim
         
     | 
| 
       28 
17 
     | 
    
         
             
                  return '"' if text_delim == "\'"
         
     | 
| 
       29 
18 
     | 
    
         
             
                  "\'"
         
     | 
| 
       30 
19 
     | 
    
         
             
                end
         
     | 
| 
       31 
     | 
    
         
            -
             
     | 
| 
       32 
     | 
    
         
            -
             
     | 
| 
      
 20 
     | 
    
         
            +
             
     | 
| 
      
 21 
     | 
    
         
            +
             
     | 
| 
      
 22 
     | 
    
         
            +
                # Ensure a value is written to CSV correctly
         
     | 
| 
      
 23 
     | 
    
         
            +
                # TODO - better ways ?? - see transcoding and String#encode
         
     | 
| 
      
 24 
     | 
    
         
            +
             
     | 
| 
      
 25 
     | 
    
         
            +
                def escape_for_csv(value)
         
     | 
| 
      
 26 
     | 
    
         
            +
                  text = value.to_s.gsub(text_delim, escape_text_delim()).gsub("\n", "\\n")
         
     | 
| 
      
 27 
     | 
    
         
            +
             
     | 
| 
      
 28 
     | 
    
         
            +
                  text = "#{text_delim}#{text}#{text_delim}" if(text.include?(Delimiters::csv_delim))
         
     | 
| 
      
 29 
     | 
    
         
            +
                  text
         
     | 
| 
      
 30 
     | 
    
         
            +
                end
         
     | 
| 
      
 31 
     | 
    
         
            +
             
     | 
| 
      
 32 
     | 
    
         
            +
             
     | 
| 
      
 33 
     | 
    
         
            +
                def to_headers( records, associations = nil, options = {} )
         
     | 
| 
      
 34 
     | 
    
         
            +
                  return if( !records.first.is_a?(ActiveRecord::Base) || records.empty?)
         
     | 
| 
      
 35 
     | 
    
         
            +
             
     | 
| 
      
 36 
     | 
    
         
            +
                  only = *options[:only] ? [*options[:only]] : nil
         
     | 
| 
      
 37 
     | 
    
         
            +
             
     | 
| 
      
 38 
     | 
    
         
            +
                  headers =[]
         
     | 
| 
      
 39 
     | 
    
         
            +
             
     | 
| 
      
 40 
     | 
    
         
            +
                  if associations
         
     | 
| 
      
 41 
     | 
    
         
            +
                    details_mgr = DataShift::MethodDictionary.method_details_mgrs[records.first.class]
         
     | 
| 
      
 42 
     | 
    
         
            +
             
     | 
| 
      
 43 
     | 
    
         
            +
                    [*associations].each do |a|
         
     | 
| 
      
 44 
     | 
    
         
            +
             
     | 
| 
      
 45 
     | 
    
         
            +
                      details_mgr.get_list(a).each do  |md|
         
     | 
| 
      
 46 
     | 
    
         
            +
             
     | 
| 
      
 47 
     | 
    
         
            +
                        next if(only && !only.include?( md.name.to_sym ) )
         
     | 
| 
      
 48 
     | 
    
         
            +
             
     | 
| 
      
 49 
     | 
    
         
            +
                        headers << "#{md.operator}"
         
     | 
| 
      
 50 
     | 
    
         
            +
             
     | 
| 
      
 51 
     | 
    
         
            +
                      end
         
     | 
| 
      
 52 
     | 
    
         
            +
                    end if(details_mgr)
         
     | 
| 
      
 53 
     | 
    
         
            +
             
     | 
| 
      
 54 
     | 
    
         
            +
                  else
         
     | 
| 
      
 55 
     | 
    
         
            +
             
     | 
| 
      
 56 
     | 
    
         
            +
                    headers = records.first.class.columns.collect( &:name )
         
     | 
| 
      
 57 
     | 
    
         
            +
                  end
         
     | 
| 
      
 58 
     | 
    
         
            +
             
     | 
| 
      
 59 
     | 
    
         
            +
                  headers
         
     | 
| 
      
 60 
     | 
    
         
            +
                end
         
     | 
| 
      
 61 
     | 
    
         
            +
             
     | 
| 
      
 62 
     | 
    
         
            +
             
     | 
| 
       33 
63 
     | 
    
         
             
                # Convert an AR instance to a single column
         
     | 
| 
       34 
     | 
    
         
            -
              
         
     | 
| 
       35 
     | 
    
         
            -
                 
     | 
| 
       36 
     | 
    
         
            -
                
         
     | 
| 
       37 
     | 
    
         
            -
             
     | 
| 
       38 
     | 
    
         
            -
             
     | 
| 
       39 
     | 
    
         
            -
             
     | 
| 
       40 
     | 
    
         
            -
             
     | 
| 
       41 
     | 
    
         
            -
             
     | 
| 
      
 64 
     | 
    
         
            +
                #    e.g User  :  ":name = > 'tom', :role => 'developer'"
         
     | 
| 
      
 65 
     | 
    
         
            +
                #
         
     | 
| 
      
 66 
     | 
    
         
            +
                # OPTIONS
         
     | 
| 
      
 67 
     | 
    
         
            +
                #     with_only  Specify (as symbols) columns for association types to export
         
     | 
| 
      
 68 
     | 
    
         
            +
                #     json:         Export association data in single column in JSON format
         
     | 
| 
      
 69 
     | 
    
         
            +
                #
         
     | 
| 
      
 70 
     | 
    
         
            +
                def record_to_column(record, options = {})
         
     | 
| 
      
 71 
     | 
    
         
            +
             
     | 
| 
      
 72 
     | 
    
         
            +
                  return "" if(record.nil? || (record.respond_to?(:each) && record.empty?) )
         
     | 
| 
      
 73 
     | 
    
         
            +
             
     | 
| 
      
 74 
     | 
    
         
            +
                  with_only = *options[:with_only] ? [*options[:with_only]] : nil
         
     | 
| 
      
 75 
     | 
    
         
            +
             
     | 
| 
      
 76 
     | 
    
         
            +
                  return record.to_json if(options[:json] && !with_only) # packs associations into single column
         
     | 
| 
      
 77 
     | 
    
         
            +
             
     | 
| 
      
 78 
     | 
    
         
            +
                  if( record.respond_to?(:each) )
         
     | 
| 
      
 79 
     | 
    
         
            +
             
     | 
| 
      
 80 
     | 
    
         
            +
                    return "" if(record.empty?)
         
     | 
| 
      
 81 
     | 
    
         
            +
             
     | 
| 
      
 82 
     | 
    
         
            +
                    data = []
         
     | 
| 
      
 83 
     | 
    
         
            +
             
     | 
| 
      
 84 
     | 
    
         
            +
                    record.each { |r| data << record_to_column(r, options); }
         
     | 
| 
      
 85 
     | 
    
         
            +
             
     | 
| 
      
 86 
     | 
    
         
            +
                    if(options[:json])
         
     | 
| 
      
 87 
     | 
    
         
            +
                      return data.to_json
         
     | 
| 
      
 88 
     | 
    
         
            +
                    else
         
     | 
| 
      
 89 
     | 
    
         
            +
                      return "#{data.join(Delimiters::multi_assoc_delim)}"
         
     | 
| 
      
 90 
     | 
    
         
            +
                    end
         
     | 
| 
      
 91 
     | 
    
         
            +
             
     | 
| 
      
 92 
     | 
    
         
            +
                  else
         
     | 
| 
      
 93 
     | 
    
         
            +
             
     | 
| 
      
 94 
     | 
    
         
            +
                    data = options[:json] ? {} : []
         
     | 
| 
      
 95 
     | 
    
         
            +
             
     | 
| 
      
 96 
     | 
    
         
            +
                    record.serializable_hash.each do |name, value|
         
     | 
| 
      
 97 
     | 
    
         
            +
                      next if(with_only && !with_only.include?( name.to_sym ) )
         
     | 
| 
      
 98 
     | 
    
         
            +
             
     | 
| 
      
 99 
     | 
    
         
            +
                      if(options[:json])
         
     | 
| 
      
 100 
     | 
    
         
            +
                        data[name] = value
         
     | 
| 
      
 101 
     | 
    
         
            +
                      else
         
     | 
| 
      
 102 
     | 
    
         
            +
                        data << "#{name.to_sym} #{Delimiters::key_value_sep} #{value.to_s.gsub(text_delim, escape_text_delim)}"
         
     | 
| 
      
 103 
     | 
    
         
            +
                      end
         
     | 
| 
      
 104 
     | 
    
         
            +
                    end
         
     | 
| 
      
 105 
     | 
    
         
            +
             
     | 
| 
      
 106 
     | 
    
         
            +
                    if(options[:json])#
         
     | 
| 
      
 107 
     | 
    
         
            +
                      return data.to_json
         
     | 
| 
      
 108 
     | 
    
         
            +
                    else
         
     | 
| 
      
 109 
     | 
    
         
            +
                      "#{Delimiters::attribute_list_start}#{data.join(Delimiters::multi_value_delim)}#{Delimiters::attribute_list_end}"
         
     | 
| 
      
 110 
     | 
    
         
            +
                    end
         
     | 
| 
      
 111 
     | 
    
         
            +
             
     | 
| 
       42 
112 
     | 
    
         
             
                  end
         
     | 
| 
       43 
     | 
    
         
            -
             
     | 
| 
      
 113 
     | 
    
         
            +
             
     | 
| 
       44 
114 
     | 
    
         
             
                end
         
     | 
| 
       45 
     | 
    
         
            -
             
     | 
| 
       46 
     | 
    
         
            -
             
     | 
| 
      
 115 
     | 
    
         
            +
             
     | 
| 
      
 116 
     | 
    
         
            +
             
     | 
| 
       47 
117 
     | 
    
         
             
                # Convert an AR instance to a set of CSV columns
         
     | 
| 
       48 
118 
     | 
    
         
             
                def record_to_csv(record, options = {})
         
     | 
| 
       49 
119 
     | 
    
         
             
                  csv_data = record.serializable_hash.values.collect { |value| escape_for_csv(value) }
         
     | 
| 
       50 
120 
     | 
    
         | 
| 
       51 
121 
     | 
    
         
             
                  [*options[:methods]].each { |x| csv_data << escape_for_csv(record.send(x)) if(record.respond_to?(x)) } if(options[:methods])
         
     | 
| 
       52 
     | 
    
         
            -
             
     | 
| 
      
 122 
     | 
    
         
            +
             
     | 
| 
       53 
123 
     | 
    
         
             
                  csv_data.join( Delimiters::csv_delim )
         
     | 
| 
       54 
124 
     | 
    
         
             
                end
         
     | 
| 
       55 
     | 
    
         
            -
             
     | 
| 
       56 
     | 
    
         
            -
             
     | 
| 
       57 
     | 
    
         
            -
                  text = value.to_s.gsub(@text_delim, escape_text_delim())
         
     | 
| 
       58 
     | 
    
         
            -
                  
         
     | 
| 
       59 
     | 
    
         
            -
                  text = "#{@text_delim}#{text}#{@text_delim}" if(text.include?(Delimiters::csv_delim)) 
         
     | 
| 
       60 
     | 
    
         
            -
                  text
         
     | 
| 
       61 
     | 
    
         
            -
                end
         
     | 
| 
       62 
     | 
    
         
            -
                
         
     | 
| 
      
 125 
     | 
    
         
            +
             
     | 
| 
      
 126 
     | 
    
         
            +
             
     | 
| 
       63 
127 
     | 
    
         
             
              end
         
     | 
| 
       64 
128 
     | 
    
         
             
            end
         
     |