sprig 0.1.6 → 0.3.1

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.
Files changed (64) hide show
  1. checksums.yaml +5 -5
  2. data/README.md +61 -10
  3. data/lib/generators/sprig/install_generator.rb +5 -1
  4. data/lib/sprig.rb +21 -0
  5. data/lib/sprig/configuration.rb +19 -2
  6. data/lib/sprig/directive.rb +3 -3
  7. data/lib/sprig/helpers.rb +15 -3
  8. data/lib/sprig/planter.rb +1 -1
  9. data/lib/sprig/process_notifier.rb +4 -4
  10. data/lib/sprig/seed/attribute.rb +27 -3
  11. data/lib/sprig/seed/entry.rb +8 -4
  12. data/lib/sprig/seed/factory.rb +1 -1
  13. data/lib/sprig/source.rb +10 -1
  14. data/lib/sprig/version.rb +8 -1
  15. data/spec/adapters/active_record.rb +34 -0
  16. data/spec/adapters/mongoid.rb +19 -0
  17. data/spec/adapters/mongoid.yml +12 -0
  18. data/spec/feature/configurations_spec.rb +5 -5
  19. data/spec/fixtures/models/{comment.rb → active_record/comment.rb} +0 -0
  20. data/spec/fixtures/models/{post.rb → active_record/post.rb} +0 -0
  21. data/spec/fixtures/models/{tag.rb → active_record/tag.rb} +0 -0
  22. data/spec/fixtures/models/{user.rb → active_record/user.rb} +0 -0
  23. data/spec/fixtures/models/mongoid/comment.rb +9 -0
  24. data/spec/fixtures/models/mongoid/post.rb +18 -0
  25. data/spec/fixtures/models/mongoid/tag.rb +7 -0
  26. data/spec/fixtures/models/mongoid/user.rb +9 -0
  27. data/spec/fixtures/seeds/shared/comments.yml +4 -0
  28. data/spec/fixtures/seeds/shared/files/cat.png +0 -0
  29. data/spec/fixtures/seeds/shared/invalid_users.yml +4 -0
  30. data/spec/fixtures/seeds/shared/legacy_posts.yml +4 -0
  31. data/spec/fixtures/seeds/shared/posts.csv +2 -0
  32. data/spec/fixtures/seeds/shared/posts.json +1 -0
  33. data/spec/fixtures/seeds/shared/posts.md +5 -0
  34. data/spec/fixtures/seeds/shared/posts.yml +4 -0
  35. data/spec/fixtures/seeds/shared/posts_delete_existing_by.yml +7 -0
  36. data/spec/fixtures/seeds/shared/posts_find_existing_by_missing.yml +7 -0
  37. data/spec/fixtures/seeds/shared/posts_find_existing_by_multiple.yml +8 -0
  38. data/spec/fixtures/seeds/shared/posts_find_existing_by_single.yml +7 -0
  39. data/spec/fixtures/seeds/shared/posts_missing_dependency.yml +5 -0
  40. data/spec/fixtures/seeds/shared/posts_missing_record.yml +5 -0
  41. data/spec/fixtures/seeds/shared/posts_partially_dynamic_value.yml +4 -0
  42. data/spec/fixtures/seeds/shared/posts_with_cyclic_dependencies.yml +4 -0
  43. data/spec/fixtures/seeds/shared/posts_with_files.yml +5 -0
  44. data/spec/fixtures/seeds/shared/posts_with_habtm.yml +7 -0
  45. data/spec/fixtures/seeds/shared/tags.yml +5 -0
  46. data/spec/fixtures/seeds/test/posts_partially_dynamic_value.yml +4 -0
  47. data/spec/lib/generators/sprig/install_generator_spec.rb +6 -2
  48. data/spec/lib/sprig/configuration_spec.rb +6 -6
  49. data/spec/lib/sprig/directive_list_spec.rb +4 -4
  50. data/spec/lib/sprig/directive_spec.rb +21 -11
  51. data/spec/lib/sprig/null_record_spec.rb +2 -2
  52. data/spec/lib/sprig/parser/base_spec.rb +1 -1
  53. data/spec/lib/sprig/process_notifier_spec.rb +5 -3
  54. data/spec/lib/sprig/seed/entry_spec.rb +3 -3
  55. data/spec/lib/sprig/seed/record_spec.rb +3 -3
  56. data/spec/lib/sprig/source_spec.rb +2 -2
  57. data/spec/lib/sprig_spec.rb +59 -8
  58. data/spec/spec_helper.rb +35 -31
  59. data/spec/sprig_shared_spec.rb +467 -0
  60. data/spec/sprig_spec.rb +105 -34
  61. data/spec/support/helpers/logger_mock.rb +2 -1
  62. metadata +167 -87
  63. data/lib/sprig/data.rb +0 -6
  64. data/spec/db/activerecord.db +0 -0
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
- SHA1:
3
- metadata.gz: a11f717b26ca547b63e3a10d77e90e5fb0b34f99
4
- data.tar.gz: 875a60cf93f12dda5e3cf04f17dca18c1201f53c
2
+ SHA256:
3
+ metadata.gz: 467afaf41af6215b9da174e770e94265ae30774763a0b3f650086a56d15ecaea
4
+ data.tar.gz: 15ca2de82777633d207c659acef1bbd4aed1cfa0c4eb579a36ac8f74a12e9ae9
5
5
  SHA512:
6
- metadata.gz: 3c5b80e9fbc98aeca33b2f535336a4ac577f4837ecc88b5315351f5cef5582bf67b6fad52a4af4b706c045bdb3120461c1c74b5e118eb177406f66a824e5cf99
7
- data.tar.gz: 7660d42b5f0ca71849c63de2abaef6cc4ad324ee08598b00676b4196c80050eeb49264589258e601504ad5bac97514edfe42d5ec0624dbdb87193a903d0db875
6
+ metadata.gz: 29ffd4703a02baed76c2b6c4f1a1a30d56eed668e7bdf9ae4da07902e6271196e6f846ec734c0cd1aa6f24b52b4bf222b61bb9e62cd6a5a65933deed0d55fa7a
7
+ data.tar.gz: 69cb476a52cec76ca0752ef562dad5d5ee4c260367d7d4d62ae30e1adadf346d5adb69670142e4ce285a048c652bcd1acda934ebb00125aaeac77d8a702f9531
data/README.md CHANGED
@@ -10,9 +10,13 @@ Learn more about Sprig and view documentation at [http://vigetlabs.github.io/spr
10
10
 
11
11
  ## Installation
12
12
 
13
- Use `rails generate sprig:install` to create environment-specific seed directories.
13
+ Add into your Gemfile
14
+ ```ruby
15
+ gem "sprig"
16
+ ```
17
+ Use `rails generate sprig:install` to create environment-specific and shared seed directories.
14
18
 
15
- ##The Sprig Directive
19
+ ## The Sprig Directive
16
20
 
17
21
  Within your seed file, you can use the `sprig` directive to initiate Sprig's dark magicks. A simple directive might look like this.
18
22
 
@@ -22,18 +26,30 @@ Within your seed file, you can use the `sprig` directive to initiate Sprig's dar
22
26
  include Sprig::Helpers
23
27
 
24
28
  sprig [User, Post, Comment]
29
+
30
+ For shared seeds:
31
+ sprig_shared [User, Post, Comment]
25
32
  ```
26
33
 
27
34
  This directive tells Sprig to go find your datafiles for the `User`, `Post`, and `Comment` seed resources, build records from the data entries, and insert them into the database. Sprig will automatically detect known datafile types like `.yml`, `.json`, or `.csv` within your environment-specific seed directory.
28
35
 
29
- ##Environment
36
+ ## Environment
30
37
 
31
38
  Seed files are unique to the environment in which your Rails application is running. Within `db/seeds` create an environment-specific directory (i.e. `/development` for your 'development' environment).
32
39
 
33
- Todo: [Support for shared seed files]
40
+ ### Shared
34
41
 
42
+ Shared seed files default directory is `shared` (eg `db/seeds/shared`)
43
+ You can change it by settings`
44
+
45
+ To insert env specific together with shared seeds use:
46
+ ```ruby
47
+ sprig [User]
48
+ sprig_shared [User]
49
+ ```
50
+ This will insert `:env/users` and `shared/users` seeds
35
51
 
36
- ##Seed files
52
+ ## Seed files
37
53
 
38
54
  Hang your seed definitions on a `records` key for *yaml* and *json* files.
39
55
 
@@ -47,7 +63,7 @@ records:
47
63
  first_name: 'Lawson'
48
64
  last_name: 'Kurtz'
49
65
  username: 'lawdawg'
50
- - sprig_id: 2
66
+ - sprig_id: 'ryan' # Note: Sprig IDs can be integers or strings
51
67
  first_name: 'Ryan'
52
68
  last_name: 'Foster'
53
69
  username: 'mc_rubs'
@@ -74,6 +90,8 @@ records:
74
90
 
75
91
  Each seed record needs a `sprig_id` defined that must be *unique across all seed files per class*. It can be an integer, string, whatever you prefer; as long as it is unique, Sprig can sort your seeds for insertion and detect any cyclic relationships.
76
92
 
93
+ ### Relationships
94
+
77
95
  Create relationships between seed records with the `sprig_record` helper:
78
96
 
79
97
  ```yaml
@@ -85,6 +103,28 @@ records:
85
103
  body: "Yaml Comment body"
86
104
  ```
87
105
 
106
+ #### Has and Belongs to Many
107
+ For `has_and_belongs_to_many` (HABTM) relationships, you may define relation ids in array format. So if `Post` `has_and_belongs_to_many :tags`, you could write:
108
+ ```yaml
109
+ #posts.yml
110
+
111
+ records:
112
+ - sprig_id: 42
113
+ title: 'All About Brains'
114
+ content: 'Lorem ipsum...'
115
+ tag_ids:
116
+ - '<%= sprig_record(Tag, 1).id %>'
117
+ - '<%= sprig_record(Tag, 2).id %>'
118
+ ```
119
+ ```yaml
120
+ #tags.yml
121
+
122
+ records:
123
+ - sprig_id: 'bio'
124
+ name: 'Biology'
125
+ - sprig_id: 'neuro'
126
+ name: 'Neuroscience'
127
+ ```
88
128
  **Note: For namespaced or STI classes, you'll need to include the namespace with the class name in the seed file name. For example `Users::HeadManager` would need to be `users_head_managers.yml`**
89
129
 
90
130
  ### Special Options
@@ -119,15 +159,17 @@ records:
119
159
  published_at: "<%= 1.week.ago %>"
120
160
  ```
121
161
 
122
- ##Custom Sources and Parsers
162
+ ## Custom Sources and Parsers
123
163
 
124
164
  If all your data is in `.wat` files, fear not. You can tell Sprig where to look for your data, and point it toward a custom parser class for turning your data into records. The example below tells Sprig to read `User` seed data from a Google Spreadsheet, and parse it accordingly.
125
165
 
126
166
  ```ruby
167
+ require 'open-uri'
168
+
127
169
  fanciness = {
128
170
  :class => User,
129
171
  :source => open('https://spreadsheets.google.com/feeds/list/somerandomtoken/1/public/values?alt=json'),
130
- :parser => Sprig::Data::Parser::GoogleSpreadsheetJson
172
+ :parser => Sprig::Parser::GoogleSpreadsheetJson
131
173
  }
132
174
 
133
175
  sprig [
@@ -137,23 +179,32 @@ sprig [
137
179
  ]
138
180
  ```
139
181
 
140
- ##Configuration
182
+ ## Configuration
141
183
 
142
184
  When Sprig conventions don't suit, just add a configuration block to your seed file.
143
185
 
144
186
  ```ruby
145
187
  Sprig.configure do |c|
146
188
  c.directory = 'seed_files'
189
+ c.shared_directory = 'shared'
147
190
  end
148
191
  ```
149
192
 
150
193
  ## Populate Seed Files from Database
151
194
 
152
195
  Want to create Sprig seed files from the records in your database? Well,
153
- [Sprig::Reap](http://www.rubygems.org/sprig-reap) can create them for you! Check out the gem's
196
+ [Sprig::Reap](https://rubygems.org/gems/sprig-reap) can create them for you! Check out the gem's
154
197
  [README](https://github.com/vigetlabs/sprig-reap#sprigreap) for installation instructions and
155
198
  details on usage.
156
199
 
157
200
  ## License
158
201
 
159
202
  This project rocks and uses MIT-LICENSE.
203
+
204
+ ***
205
+
206
+ <a href="http://code.viget.com">
207
+ <img src="http://code.viget.com/github-banner.png" alt="Code At Viget">
208
+ </a>
209
+
210
+ Visit [code.viget.com](http://code.viget.com) to see more projects from [Viget.](https://viget.com)
@@ -9,12 +9,16 @@ module Sprig
9
9
 
10
10
  def create_enviroment_directories
11
11
  empty_directory 'db/seeds'
12
-
12
+ create_shared_directory
13
13
  envs.each { |env| empty_directory "db/seeds/#{env}" }
14
14
  end
15
15
 
16
16
  private
17
17
 
18
+ def create_shared_directory
19
+ empty_directory 'db/seeds/shared'
20
+ end
21
+
18
22
  def envs
19
23
  arg_envs ? arg_envs : default_envs
20
24
  end
data/lib/sprig.rb CHANGED
@@ -19,6 +19,27 @@ module Sprig
19
19
  autoload :Seed, 'sprig/seed'
20
20
 
21
21
  class << self
22
+ attr_writer :adapter, :shared_seeding
23
+
24
+ def adapter
25
+ @adapter ||= :active_record
26
+ end
27
+
28
+ def adapter_model_class
29
+ @adapter_model_class ||= case adapter
30
+ when :active_record
31
+ ActiveRecord::Base
32
+ when :mongoid
33
+ Mongoid::Document
34
+ else
35
+ raise "Unknown model class for adapter #{adapter}"
36
+ end
37
+ end
38
+
39
+ def shared_seeding
40
+ @shared_seeding ||= false
41
+ end
42
+
22
43
  def configuration
23
44
  @@configuration ||= Sprig::Configuration.new
24
45
  end
@@ -1,10 +1,10 @@
1
1
  module Sprig
2
2
  class Configuration
3
3
 
4
- attr_writer :directory, :logger
4
+ attr_writer :directory, :shared_directory, :logger
5
5
 
6
6
  def directory
7
- Rails.root.join(@directory || default_directory, Rails.env)
7
+ Rails.root.join(@directory || default_directory, seeds_directory)
8
8
  end
9
9
 
10
10
  def logger
@@ -16,5 +16,22 @@ module Sprig
16
16
  def default_directory
17
17
  'db/seeds'
18
18
  end
19
+
20
+ def seeds_directory
21
+ return shared_seeds_directory if Sprig.shared_seeding
22
+ env_seeds_directory
23
+ end
24
+
25
+ def env_seeds_directory
26
+ Rails.env
27
+ end
28
+
29
+ def shared_seeds_directory
30
+ @shared_directory || default_shared_directory
31
+ end
32
+
33
+ def default_shared_directory
34
+ 'shared'
35
+ end
19
36
  end
20
37
  end
@@ -7,7 +7,7 @@ module Sprig
7
7
  case
8
8
  when args.is_a?(Hash)
9
9
  args
10
- when args.is_a?(Class) && args < ActiveRecord::Base
10
+ when args.is_a?(Class) && args < Sprig.adapter_model_class
11
11
  { :class => args }
12
12
  else
13
13
  raise ArgumentError, argument_error_message
@@ -30,8 +30,8 @@ module Sprig
30
30
  private
31
31
 
32
32
  def argument_error_message
33
- 'Sprig::Directive must be instantiated with an '\
34
- 'ActiveRecord subclass or a Hash with :class defined'
33
+ 'Sprig::Directive must be instantiated with a(n) '\
34
+ "#{Sprig.adapter_model_class} class or a Hash with :class defined"
35
35
  end
36
36
  end
37
37
  end
data/lib/sprig/helpers.rb CHANGED
@@ -5,9 +5,13 @@ module Sprig
5
5
  end
6
6
 
7
7
  def sprig(directive_definitions)
8
- hopper = []
9
- DirectiveList.new(directive_definitions).add_seeds_to_hopper(hopper)
10
- Planter.new(hopper).sprig
8
+ Sprig.shared_seeding = false
9
+ plant_records(directive_definitions)
10
+ end
11
+
12
+ def sprig_shared(directive_definitions)
13
+ Sprig.shared_seeding = true
14
+ plant_records(directive_definitions)
11
15
  end
12
16
 
13
17
  def sprig_record(klass, seed_id)
@@ -19,5 +23,13 @@ module Sprig
19
23
  def sprig_file(relative_path)
20
24
  File.new(seed_directory.join('files', relative_path))
21
25
  end
26
+
27
+ private
28
+
29
+ def plant_records(directive_definitions)
30
+ hopper = []
31
+ DirectiveList.new(directive_definitions).add_seeds_to_hopper(hopper)
32
+ Planter.new(hopper).sprig
33
+ end
22
34
  end
23
35
  end
data/lib/sprig/planter.rb CHANGED
@@ -25,7 +25,7 @@ module Sprig
25
25
  end
26
26
 
27
27
  def plant(seed)
28
- notifier.in_progress
28
+ notifier.in_progress(seed)
29
29
  seed.before_save
30
30
 
31
31
  if seed.save_record
@@ -10,6 +10,10 @@ module Sprig
10
10
  @errors = []
11
11
  end
12
12
 
13
+ def in_progress(seed)
14
+ log_debug seed.in_progress_text
15
+ end
16
+
13
17
  def success(seed)
14
18
  log_info seed.success_log_text
15
19
  @success_count += 1
@@ -42,10 +46,6 @@ module Sprig
42
46
  end
43
47
  end
44
48
 
45
- def in_progress
46
- log_debug "Planting those seeds...\r"
47
- end
48
-
49
49
  private
50
50
 
51
51
  def success_summary
@@ -54,7 +54,7 @@ module Sprig
54
54
  end
55
55
 
56
56
  def computed_value_regex
57
- /<%[=]?(.*)%>/
57
+ /(<%=?(.*?)%>)/
58
58
  end
59
59
 
60
60
  def compute_value(value)
@@ -73,9 +73,33 @@ module Sprig
73
73
  end
74
74
  end
75
75
 
76
+ def completely_dynamic_value?(string, matches)
77
+ return false if matches.count > 1
78
+
79
+ test_string = string.clone
80
+
81
+ matches.each do |match|
82
+ test_string = test_string.sub(match[0], "")
83
+ end
84
+
85
+ test_string.strip.length == 0
86
+ end
87
+
76
88
  def compute_string_value(string)
77
- matches = computed_value_regex.match(string)
78
- eval(matches[1])
89
+ matches = string.scan(computed_value_regex)
90
+
91
+ if completely_dynamic_value?(string, matches)
92
+ # If the dynamic portion is the entire value, return the result of the eval
93
+ # (This allows for the return of non-string types.)
94
+ eval(matches.first[1])
95
+ else
96
+ # Otherwise return the dynamic portion within the larger string.
97
+ string.clone.tap do |return_string|
98
+ matches.each do |match|
99
+ return_string.sub!(match[0], eval(match[1]).to_s)
100
+ end
101
+ end
102
+ end
79
103
  end
80
104
 
81
105
  end
@@ -34,12 +34,16 @@ module Sprig
34
34
  SprigRecordStore.instance.save(record.orm_record, sprig_id)
35
35
  end
36
36
 
37
- def success_log_text
38
- "#{klass.name} with sprig_id #{sprig_id} successfully #{success_log_status_text}."
37
+ def in_progress_text
38
+ "Planting #{klass.name} with sprig_id #{sprig_id}"
39
39
  end
40
40
 
41
- def success_log_status_text
42
- record.existing? ? "updated" : "saved"
41
+ def success_log_text
42
+ if record.existing?
43
+ "Updated"
44
+ else
45
+ "Saved"
46
+ end
43
47
  end
44
48
 
45
49
  def error_log_text
@@ -30,7 +30,7 @@ module Sprig
30
30
  def klass=(klass)
31
31
  raise ArgumentError, 'Must provide a Class as first argument' unless klass.is_a? Class
32
32
 
33
- klass.reset_column_information
33
+ klass.reset_column_information if defined?(ActiveRecord) && klass < ActiveRecord::Base
34
34
  @klass = klass
35
35
  end
36
36
 
data/lib/sprig/source.rb CHANGED
@@ -67,7 +67,7 @@ module Sprig
67
67
  end
68
68
 
69
69
  def file
70
- File.new(seed_directory.join(filename))
70
+ File.new(filepath)
71
71
  end
72
72
 
73
73
  private
@@ -78,6 +78,15 @@ module Sprig
78
78
  available_files.detect {|name| name =~ /^#{table_name}\./ } || file_not_found
79
79
  end
80
80
 
81
+ def filepath
82
+ path = seed_directory.join(filename)
83
+ if File.symlink?(path)
84
+ File.readlink(path)
85
+ else
86
+ path
87
+ end
88
+ end
89
+
81
90
  def available_files
82
91
  Dir.entries(seed_directory)
83
92
  end
data/lib/sprig/version.rb CHANGED
@@ -1,3 +1,10 @@
1
1
  module Sprig
2
- VERSION = "0.1.6"
2
+
3
+ #:nocov:
4
+ VERSION = [
5
+ 0, # major
6
+ 3, # minor
7
+ 1 # patch
8
+ ].join('.')
9
+ #:nocov:
3
10
  end