hydroponics 0.3.2 → 0.3.3

Sign up to get free protection for your applications and to get access to all the features.
data/ChangeLog.markdown CHANGED
@@ -1,3 +1,8 @@
1
+ # hydroponics 0.3.3
2
+
3
+ * Generalized the routes, so new actions can be added without changing them
4
+ * Added an action, Foreign Dupe for duplicating rows in a table while incrementing a foreign key.
5
+
1
6
  # hydroponics 0.3.2
2
7
 
3
8
  * Fixed require statements so other machines can run the gem
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.3.2
1
+ 0.3.3
data/app/actions/dupe.rb CHANGED
@@ -1,14 +1,17 @@
1
1
  module Hydroponics
2
2
  module Actions
3
- def dupe(table, target_count)
3
+ # Dupe
4
+ #
5
+ # Change the total rows of a table to target_count, either by duplicating
6
+ # the first row or deleting rows from the end.
7
+ def dupe(table, data)
4
8
  table = table.to_sym
5
-
6
- first_row = @db[table].first
7
- first_row.delete(:id)
8
-
9
9
  current_count = @db[table].count
10
+ target_count = data['count'] || current_count
10
11
 
11
12
  if target_count > current_count
13
+ first_row = @db[table].first
14
+ first_row.delete(:id)
12
15
  @db[table].multi_insert([first_row] * (target_count - current_count))
13
16
  elsif current_count > target_count
14
17
  cutoff_id = @db[table].map(:id)[target_count-1]
@@ -0,0 +1,37 @@
1
+ require 'active_support/inflector'
2
+ require 'active_support/core_ext'
3
+
4
+ module Hydroponics
5
+ module Actions
6
+ # Foreign Dupe
7
+ #
8
+ # Just like Dupe, except it pulls valid foreign keys from table foreign_table.
9
+ #
10
+ # It starts from the beginning and increments as it goes.
11
+ def foreign_dupe(table, data)
12
+ table = table.to_sym
13
+ data.stringify_keys!
14
+ foreign_table = data['foreign_table'].to_sym
15
+ foreign_key_col = data['foreign_key'] || (foreign_table.to_s.singularize + "_id")
16
+ foreign_key_col = foreign_key_col.to_sym
17
+
18
+ current_count = @db[table].count
19
+ target_count = data['count'] || current_count
20
+
21
+ if target_count > current_count
22
+ foreign_ids = @db[foreign_table].map(:id)
23
+ first_row = @db[table].first
24
+ first_row.delete(:id)
25
+ n = target_count - current_count
26
+ @db[table].multi_insert( (1..n).collect { |i|
27
+ first_row.merge( Hash[foreign_key_col, foreign_ids[i % foreign_ids.size]] )
28
+ } )
29
+ elsif current_count > target_count
30
+ cutoff_id = @db[table].map(:id)[target_count-1]
31
+ @db[table].filter("id > #{cutoff_id}").delete
32
+ end
33
+
34
+ @db[table].count.to_s
35
+ end
36
+ end
37
+ end
@@ -0,0 +1,111 @@
1
+ <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
2
+ "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
3
+ <html xmlns="http://www.w3.org/1999/xhtml" lang="en" xml:lang="en">
4
+
5
+ <head>
6
+ <link href="../vendor/jquery-ui-1.8.5.custom/css/smoothness/jquery-ui-1.8.5.custom.css" media="screen" rel="stylesheet" type="text/css" />
7
+ <script type="text/javascript" src="../vendor/jquery-ui-1.8.5.custom/js/jquery-1.4.2.min.js"></script>
8
+ <script type="text/javascript" src="../vendor/jquery-ui-1.8.5.custom/js/jquery-ui-1.8.5.custom.min.js"></script>
9
+ <script type="text/javascript">
10
+ $(function(){
11
+ $("#slider div").slider({
12
+ slide: function(event, ui) {
13
+ $("#sliderct").html("<i>" + ui.value + "</i>");
14
+ $("button").button("enable");
15
+ },
16
+ max: 25000,
17
+ value: <%= db[@table].count %>
18
+ });
19
+
20
+ $("button").button();
21
+ $("button").button("enable");
22
+ $("button").click(function(){
23
+ $("#slider div").slider("disable");
24
+ $("button").button("disable");
25
+ $(".loader").show();
26
+
27
+ var postData = {
28
+ count: $("#slider div").slider("value"),
29
+ foreign_table: "<%= params[:foreign_table] %>"
30
+ };
31
+ if($("#foreign_key").val() != "") {
32
+ postData.foreign_key = $("#foreign_key").val()
33
+ }
34
+
35
+ $.ajax({
36
+ type: "POST",
37
+ url: "/foreign_dupe/<%= @table %>",
38
+ data: JSON.stringify(postData),
39
+ success: function(data, status, xhr) {
40
+ $("#sliderct").html("<b>" + data + "</b>");
41
+ $("#slider div").slider("enable");
42
+ $(".loader").hide();
43
+ },
44
+ processData: false
45
+ });
46
+ });
47
+ });
48
+ </script>
49
+ <style type="text/css">
50
+ .container {width:950px;margin:0 auto;}
51
+ .dupe h3 {
52
+ margin: 10px 5px 10px 18px;
53
+ color: #444;
54
+ float: left;
55
+ }
56
+ .dupe #slider {
57
+ float: left;
58
+ width: 252px;
59
+ margin: 16px 12px;
60
+ }
61
+ .dupecontainer {
62
+ height: 130px;
63
+ width: 501px;
64
+ }
65
+ .dupe {
66
+ height: 106px;
67
+ width: 500px;
68
+ border: 1px #ddd solid;
69
+ }
70
+ .dupe #button {
71
+ float: right;
72
+ margin: 2px 12px;
73
+ }
74
+ .dupe p {
75
+ padding: 50px 18px;
76
+ font-size: 12px;
77
+ }
78
+ h1, h3, p {
79
+ font-family: Verdana,Arial,sans-serif
80
+ }
81
+ .loader {
82
+ background-image: url('../ajax-loader.gif');
83
+ width: 32px;
84
+ height: 16px;
85
+ margin-top:16px;
86
+ float: left;
87
+ }
88
+ .dupe input {
89
+ float: right;
90
+ margin-top: 12px;
91
+ }
92
+ </style>
93
+ <title>Hydroponics <%= settings.version %></title>
94
+ </head>
95
+
96
+ <body class="container">
97
+ <div class="header">
98
+ <h1>Hydroponics</h1>
99
+ </div>
100
+ <div class="dupecontainer">
101
+ <div class="dupe">
102
+ <h3>Foreign Dupe</h3>
103
+ <div id='slider'><div></div></div>
104
+ <div class="loader" style="display:none;"></div>
105
+ <div id='button'><button>Update</button></div>
106
+ <input id='foreign_key'></input>
107
+ <p><%= @table.to_s.gsub("_"," ") %>: <span id='sliderct'><%= db[@table].count %></span></p>
108
+ </div>
109
+ </div>
110
+ </body>
111
+ </html>
data/config/hydro_app.rb CHANGED
@@ -19,13 +19,17 @@ class HydroApp < Sinatra::Base
19
19
  set :public, File.join(File.dirname(__FILE__), "../static")
20
20
  set :version, File.read(File.join(File.dirname(__FILE__), "../VERSION")).chomp
21
21
 
22
- post '/dupe/:table' do |table|
22
+ # new actions can be used without any changes to the routes, as long as they follow
23
+ # the existing format.
24
+ # => ex: GET /dupe/users; POST /dupe/users {count: 10}
25
+ # => ex: GET /foreign_dupe/portfolios?foreign_table=users; POST /foreign_dupe/users {count: 100, foreign_table: 'users'}
26
+ post '/:action/:table' do |action, table|
23
27
  data = JSON.parse(request.body.read)
24
- dupe(table, data['count'])
28
+ send(action.to_sym, table, data)
25
29
  end
26
30
 
27
- get '/dupe/:table' do |table|
31
+ get '/:action/:table' do |action, table|
28
32
  @table = table.to_sym
29
- erb :"dupe/index"
33
+ erb :"#{action}/index"
30
34
  end
31
35
  end
data/hydroponics.gemspec CHANGED
@@ -5,11 +5,11 @@
5
5
 
6
6
  Gem::Specification.new do |s|
7
7
  s.name = %q{hydroponics}
8
- s.version = "0.3.2"
8
+ s.version = "0.3.3"
9
9
 
10
10
  s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
11
  s.authors = ["Tyler Boyd"]
12
- s.date = %q{2010-10-29}
12
+ s.date = %q{2010-11-03}
13
13
  s.default_executable = %q{hydro}
14
14
  s.description = %q{A user interface to seed or destroy large quantities of data in a Rails app.}
15
15
  s.email = %q{tboyd47@gmail.com}
@@ -28,7 +28,9 @@ Gem::Specification.new do |s|
28
28
  "Rakefile",
29
29
  "VERSION",
30
30
  "app/actions/dupe.rb",
31
+ "app/actions/foreigndupe.rb",
31
32
  "app/views/dupe/index.erb",
33
+ "app/views/foreign_dupe/index.erb",
32
34
  "bin/hydro",
33
35
  "config/hydro_app.rb",
34
36
  "hydroponics.gemspec",
@@ -31,7 +31,7 @@ describe "HydroApp" do
31
31
 
32
32
  it "should show the table's count" do
33
33
  get '/dupe/users'
34
- last_response.body.include?("Count: " + @db[:users].count.to_s).should be_true
34
+ last_response.body.include?("<span id='sliderct'>" + @db[:users].count.to_s).should be_true
35
35
  end
36
36
  end
37
37
 
@@ -42,9 +42,25 @@ describe "HydroApp" do
42
42
  @db[:users].count.should == 10
43
43
  end
44
44
 
45
- it "should return the time elapsed on success" do
45
+ it "should return the final count on success" do
46
46
  post '/dupe/users', {:count => 10}.to_json
47
- last_response.body.match(/s$/).should be_true
47
+ last_response.body.match("10").should be_true
48
+ end
49
+ end
50
+
51
+ describe "/foreigndupe/*" do
52
+ it "should open foreigndupe/index.erb" do
53
+ get '/foreign_dupe/portfolios'
54
+ last_response.should be_ok
55
+ end
56
+ end
57
+
58
+ describe "/foreign_dupe/*/*" do
59
+ it "should copy the first row n times" do
60
+ @db[:users].multi_insert([{:name => "ABC", :email => "123@example.com"}] * 10)
61
+ post '/foreign_dupe/portfolios', {:count => 10, :foreign_table => 'users'}.to_json
62
+ last_response.should be_ok
63
+ @db[:portfolios].count.should == 10
48
64
  end
49
65
  end
50
66
  end
@@ -61,27 +61,67 @@ describe "Hydroponics::Actions" do
61
61
 
62
62
  describe "#dupe" do
63
63
  it "should duplicate the first user until the desired count is reached" do
64
- dupe(:users, 10)
64
+ dupe(:users, {'count' => 10})
65
65
  @db[:users].count.should == 10
66
66
  end
67
67
 
68
68
  it "should delete users from the end until the desired count is reached" do
69
69
  @db[:users].multi_insert([{:name => "ABC", :email => "123@example.com"}] * 10)
70
70
  @db[:users].count.should == 11
71
- dupe(:users, 2)
71
+ dupe(:users, {'count' => 2})
72
72
  @db[:users].count.should == 2
73
73
  end
74
74
 
75
75
  it "should handle non-consecutive id numbers" do
76
76
  @db[:users].multi_insert([{:id => 6789, :name => "ABC", :email => "123@example.com"}, {:id => 6790, :name => "ABC", :email => "123@example.com"}])
77
- dupe(:users, 2)
77
+ dupe(:users, {'count' => 2})
78
78
  @db[:users].count.should == 2
79
79
  end
80
80
 
81
81
  it "should require the table name and count" do
82
82
  lambda { dupe }.should raise_error
83
83
  lambda { dupe(:users) }.should raise_error
84
- lambda { dupe(16) }.should raise_error
84
+ lambda { dupe({'count' => 16}) }.should raise_error
85
+ end
86
+ end
87
+
88
+ describe "#foreigndupe" do
89
+ it "should copy the first row n times" do
90
+ @db[:users].multi_insert([{:name => "ABC", :email => "123@example.com"}] * 10)
91
+ foreign_dupe('portfolios', {:count => 10, :foreign_table => 'users'})
92
+ @db[:portfolios].count.should == 10
93
+ end
94
+
95
+ it "should add the foreign key" do
96
+ @db[:users].multi_insert([{:name => "ABC", :email => "123@example.com"}] * 10)
97
+ foreign_dupe('portfolios', {:count => 10, :foreign_table => 'users'})
98
+ @db[:portfolios].map(:user_id)[9].should > 0
99
+ end
100
+
101
+ it "should return the table's count" do
102
+ @db[:users].multi_insert([{:name => "ABC", :email => "123@example.com"}] * 10)
103
+ foreign_dupe('portfolios', {:count => 10, :foreign_table => 'users'}).should == "10"
104
+ end
105
+
106
+ it "should allow a custom foreign key name" do
107
+ @db.drop_table :portfolios if @db.table_exists?(:portfolios)
108
+ @db.create_table :portfolios do
109
+ primary_key :id
110
+ Integer :custom_id
111
+ String :experience
112
+ String :education
113
+ end
114
+ @db[:portfolios].insert(:experience => "None", :education => "None", :custom_id => @db[:users].first[:id])
115
+
116
+ foreign_dupe('portfolios', {:count => 10, :foreign_table => 'users', :foreign_key => "custom_id"}).should == "10"
117
+ @db[:portfolios].map(:custom_id)[9].should > 0
118
+ end
119
+
120
+ it "should start from the beginning of the foreign table if it runs out of foreign keys" do
121
+ @db[:users].multi_insert([{:name => "ABC", :email => "123@example.com"}] * 9) # so there are 10 total.
122
+ foreign_dupe('portfolios', {:count => 11, :foreign_table => 'users'})
123
+ @db[:portfolios].map(:user_id)[1].should == @db[:users].map(:id)[1]
124
+ @db[:portfolios].map(:user_id)[10].should == @db[:users].map(:id)[0]
85
125
  end
86
126
  end
87
127
  end
data/spec/spec_helper.rb CHANGED
@@ -26,10 +26,18 @@ end
26
26
  def populate_test_db
27
27
  db = Hydroponics.db
28
28
  db.drop_table :users if db.table_exists?(:users)
29
+ db.drop_table :portfolios if db.table_exists?(:portfolios)
29
30
  db.create_table :users do
30
31
  primary_key :id
31
32
  String :name
32
33
  String :email
33
34
  end
35
+ db.create_table :portfolios do
36
+ primary_key :id
37
+ Integer :user_id
38
+ String :experience
39
+ String :education
40
+ end
34
41
  db[:users].insert(:name => "Acorn Hrefski", :email => "acorn@example.com")
42
+ db[:portfolios].insert(:experience => "None", :education => "None", :user_id => db[:users].first[:id])
35
43
  end
metadata CHANGED
@@ -1,13 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: hydroponics
3
3
  version: !ruby/object:Gem::Version
4
- hash: 23
4
+ hash: 21
5
5
  prerelease: false
6
6
  segments:
7
7
  - 0
8
8
  - 3
9
- - 2
10
- version: 0.3.2
9
+ - 3
10
+ version: 0.3.3
11
11
  platform: ruby
12
12
  authors:
13
13
  - Tyler Boyd
@@ -15,7 +15,7 @@ autorequire:
15
15
  bindir: bin
16
16
  cert_chain: []
17
17
 
18
- date: 2010-10-29 00:00:00 -04:00
18
+ date: 2010-11-03 00:00:00 -04:00
19
19
  default_executable: hydro
20
20
  dependencies:
21
21
  - !ruby/object:Gem::Dependency
@@ -138,7 +138,9 @@ files:
138
138
  - Rakefile
139
139
  - VERSION
140
140
  - app/actions/dupe.rb
141
+ - app/actions/foreigndupe.rb
141
142
  - app/views/dupe/index.erb
143
+ - app/views/foreign_dupe/index.erb
142
144
  - bin/hydro
143
145
  - config/hydro_app.rb
144
146
  - hydroponics.gemspec