ardb 0.28.3 → 0.29.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.
Files changed (53) hide show
  1. checksums.yaml +7 -7
  2. data/Gemfile +4 -9
  3. data/README.md +252 -3
  4. data/ardb.gemspec +8 -7
  5. data/bin/ardb +1 -1
  6. data/lib/ardb.rb +35 -34
  7. data/lib/ardb/adapter/base.rb +34 -30
  8. data/lib/ardb/adapter/mysql.rb +2 -17
  9. data/lib/ardb/adapter/postgresql.rb +24 -30
  10. data/lib/ardb/adapter/sqlite.rb +4 -8
  11. data/lib/ardb/adapter_spy.rb +2 -16
  12. data/lib/ardb/cli.rb +15 -15
  13. data/lib/ardb/cli/clirb.rb +14 -17
  14. data/lib/ardb/cli/commands.rb +204 -114
  15. data/lib/ardb/db_tests.rb +2 -4
  16. data/lib/ardb/default_order_by.rb +3 -13
  17. data/lib/ardb/migration.rb +9 -13
  18. data/lib/ardb/record_spy.rb +7 -26
  19. data/lib/ardb/relation_spy.rb +0 -6
  20. data/lib/ardb/require_autoloaded_active_record_files.rb +103 -58
  21. data/lib/ardb/test_helpers.rb +2 -5
  22. data/lib/ardb/use_db_default.rb +4 -15
  23. data/lib/ardb/version.rb +1 -1
  24. data/script/determine_autoloaded_active_record_files.rb +11 -8
  25. data/test/helper.rb +4 -13
  26. data/test/support/factory.rb +2 -2
  27. data/test/support/postgresql/migrations/{.gitkeep → .keep} +0 -0
  28. data/test/support/postgresql/schema.rb +0 -1
  29. data/test/support/postgresql/setup_test_db.rb +14 -15
  30. data/test/system/.keep +0 -0
  31. data/test/unit/adapter/base_tests.rb +73 -53
  32. data/test/unit/adapter/mysql_tests.rb +2 -19
  33. data/test/unit/adapter/postgresql_tests.rb +14 -23
  34. data/test/unit/adapter/sqlite_tests.rb +3 -11
  35. data/test/unit/adapter_spy_tests.rb +2 -16
  36. data/test/unit/ardb_tests.rb +43 -43
  37. data/test/unit/cli_tests.rb +220 -158
  38. data/test/unit/db_tests_tests.rb +3 -6
  39. data/test/unit/default_order_by_tests.rb +4 -8
  40. data/test/unit/migration_tests.rb +11 -15
  41. data/test/unit/record_spy_tests.rb +17 -22
  42. data/test/unit/relation_spy_tests.rb +17 -46
  43. data/test/unit/test_helpers_tests.rb +3 -14
  44. data/test/unit/use_db_default_tests.rb +7 -11
  45. metadata +100 -84
  46. data/lib/ardb/has_slug.rb +0 -107
  47. data/lib/ardb/migration_helpers.rb +0 -77
  48. data/lib/ardb/pg_json.rb +0 -90
  49. data/test/support/postgresql/pg_json_migrations/20160519133432_create_pg_json_migrate_test.rb +0 -13
  50. data/test/system/pg_json_tests.rb +0 -85
  51. data/test/unit/has_slug_tests.rb +0 -341
  52. data/test/unit/migration_helpers_tests.rb +0 -65
  53. data/test/unit/pg_json_tests.rb +0 -39
@@ -1,3 +1,3 @@
1
1
  module Ardb
2
- VERSION = "0.28.3"
2
+ VERSION = "0.29.0"
3
3
  end
@@ -1,8 +1,8 @@
1
- require 'active_record'
1
+ require "active_record"
2
2
 
3
- # this can be slow, this is one of the reasons this shouldn't be done during
3
+ # this can be slow, this is one of the reasons this shouldn"t be done during
4
4
  # the startup of our apps
5
- gemspec = Gem.loaded_specs['activerecord']
5
+ gemspec = Gem.loaded_specs["activerecord"]
6
6
 
7
7
  puts "Looking at files in: "
8
8
  puts " #{gemspec.lib_dirs_glob.inspect}"
@@ -11,15 +11,18 @@ paths = Dir["#{gemspec.lib_dirs_glob}/**/*.rb"]
11
11
 
12
12
  # these are regexs for files we want to ignore requiring. for example,
13
13
  # generators fail when we try to require them. the others are pieces of active
14
- # record we don't use in a production environment
14
+ # record we don"t use in a production environment
15
15
  ignored_regexes = [
16
16
  /rails\/generators/,
17
17
  /active_record\/railtie/,
18
18
  /active_record\/migration/,
19
19
  /active_record\/fixtures/,
20
+ /active_record\/fixture_set/,
20
21
  /active_record\/schema/,
21
22
  /active_record\/connection_adapters/,
22
23
  /active_record\/test_case/,
24
+ /active_record\/test_databases/,
25
+ /active_record\/test_fixtures/,
23
26
  /active_record\/coders\/yaml_column/
24
27
  ]
25
28
 
@@ -31,12 +34,12 @@ ignored = []
31
34
  errored = []
32
35
 
33
36
  paths.sort.each do |full_path|
34
- relative_path_with_rb = full_path.gsub("#{gemspec.lib_dirs_glob}/", '')
35
- relative_path = relative_path_with_rb.gsub(/\.rb\z/, '')
37
+ relative_path_with_rb = full_path.gsub("#{gemspec.lib_dirs_glob}/", "")
38
+ relative_path = relative_path_with_rb.gsub(/\.rb\z/, "")
36
39
 
37
40
  result = Result.new(relative_path)
38
41
 
39
- # see if it's ignored
42
+ # see if it"s ignored
40
43
  ignored_regexes.each do |regex|
41
44
  if relative_path =~ regex
42
45
  result.state = :ignored
@@ -87,5 +90,5 @@ puts "\n"
87
90
 
88
91
  puts "Needs To Be Required:\n"
89
92
  needs_to_be_required.each do |result|
90
- puts "require '#{result.file}'"
93
+ puts "require \"#{result.file}\""
91
94
  end
@@ -7,19 +7,10 @@ $LOAD_PATH.unshift(File.expand_path("../..", __FILE__))
7
7
  TEST_SUPPORT_PATH = File.expand_path("../support", __FILE__)
8
8
  TMP_PATH = File.expand_path("../../tmp", __FILE__)
9
9
 
10
- require 'logger'
10
+ require "logger"
11
11
  log_path = File.expand_path("../../log/test.log", __FILE__)
12
- TEST_LOGGER = Logger.new(File.open(log_path, 'w'))
12
+ TEST_LOGGER = Logger.new(File.open(log_path, "w"))
13
13
 
14
14
  # require pry for debugging (`binding.pry`)
15
- require 'pry'
16
- require 'test/support/factory'
17
-
18
- # 1.8.7 backfills
19
-
20
- # Array#sample
21
- if !(a = Array.new).respond_to?(:sample) && a.respond_to?(:choice)
22
- class Array
23
- alias_method :sample, :choice
24
- end
25
- end
15
+ require "pry"
16
+ require "test/support/factory"
@@ -1,10 +1,10 @@
1
- require 'assert/factory'
1
+ require "assert/factory"
2
2
 
3
3
  module Factory
4
4
  extend Assert::Factory
5
5
 
6
6
  def self.migration_id
7
- # identifiers need to be plural b/c af activesupport's pluralize
7
+ # identifiers need to be plural b/c af activesupport"s pluralize
8
8
  "#{Factory.string}_things"
9
9
  end
10
10
 
@@ -1,3 +1,2 @@
1
1
  ActiveRecord::Schema.define(:version => 0) do
2
-
3
2
  end
@@ -1,24 +1,24 @@
1
- require 'assert'
2
- require 'ardb'
1
+ require "assert"
2
+ require "ardb"
3
3
 
4
4
  class PostgresqlDbTests < Assert::Context
5
5
  setup do
6
- @orig_env_ardb_db_file = ENV['ARDB_DB_FILE']
6
+ @orig_env_ardb_db_file = ENV["ARDB_DB_FILE"]
7
7
  ActiveRecord::Base.logger = @orig_ar_loggerF
8
8
 
9
- # no-op, we're manually configuring ardb so we don't need this to do anything
10
- ENV['ARDB_DB_FILE'] = File.join(TEST_SUPPORT_PATH, 'require_test_db_file')
9
+ # no-op, we"re manually configuring ardb so we don"t need this to do anything
10
+ ENV["ARDB_DB_FILE"] = File.join(TEST_SUPPORT_PATH, "require_test_db_file")
11
11
 
12
12
  @ardb_config = Ardb::Config.new.tap do |c|
13
- c.adapter = 'postgresql'
14
- c.database = 'redding_ardb_test'
15
- c.encoding = 'unicode'
16
- c.min_messages = 'WARNING'
13
+ c.adapter = "postgresql"
14
+ c.database = "redding_ardb_test"
15
+ c.encoding = "unicode"
16
+ c.min_messages = "WARNING"
17
17
 
18
18
  c.logger = TEST_LOGGER
19
- c.root_path = File.join(TEST_SUPPORT_PATH, 'postgresql')
20
- c.migrations_path = 'migrations'
21
- c.schema_path = 'schema'
19
+ c.root_path = File.join(TEST_SUPPORT_PATH, "postgresql")
20
+ c.migrations_path = "migrations"
21
+ c.schema_path = "schema"
22
22
  c.schema_format = :ruby
23
23
  end
24
24
  Assert.stub(Ardb, :config){ @ardb_config }
@@ -33,7 +33,7 @@ class PostgresqlDbTests < Assert::Context
33
33
  teardown do
34
34
  Ardb.reset_adapter
35
35
  ActiveRecord::Base.logger = @orig_ar_logger
36
- ENV['ARDB_DB_FILE'] = @orig_env_ardb_db_file
36
+ ENV["ARDB_DB_FILE"] = @orig_env_ardb_db_file
37
37
  end
38
38
 
39
39
  private
@@ -41,12 +41,11 @@ class PostgresqlDbTests < Assert::Context
41
41
  # useful when testing creating/dropping/migrating DBs
42
42
  def silence_stdout
43
43
  current_stdout = $stdout.dup
44
- $stdout = File.new('/dev/null', 'w')
44
+ $stdout = File.new("/dev/null", "w")
45
45
  begin
46
46
  yield
47
47
  ensure
48
48
  $stdout = current_stdout
49
49
  end
50
50
  end
51
-
52
51
  end
File without changes
@@ -1,14 +1,13 @@
1
- require 'assert'
2
- require 'ardb/adapter/base'
1
+ require "assert"
2
+ require "ardb/adapter/base"
3
3
 
4
- require 'ardb'
5
- # This is needed by the schema dumper but it doesn't handle requiring it so we
4
+ require "ardb"
5
+ # This is needed by the schema dumper but it doesn"t handle requiring it so we
6
6
  # have to manually, otherwise this errors when you try to run the adapter base
7
7
  # tests by themselves
8
- require 'active_support/core_ext/class/attribute_accessors'
8
+ require "active_support/core_ext/class/attribute_accessors"
9
9
 
10
10
  class Ardb::Adapter::Base
11
-
12
11
  class UnitTests < Assert::Context
13
12
  desc "Ardb::Adapter::Base"
14
13
  setup do
@@ -21,7 +20,6 @@ class Ardb::Adapter::Base
21
20
  should have_imeths :connect_hash, :database, :migrations_path
22
21
  should have_imeths :schema_format, :ruby_schema_path, :sql_schema_path
23
22
  should have_imeths :escape_like_pattern
24
- should have_imeths :foreign_key_add_sql, :foreign_key_drop_sql
25
23
  should have_imeths :create_db, :drop_db, :drop_tables
26
24
  should have_imeths :connect_db, :migrate_db
27
25
  should have_imeths :load_schema, :load_ruby_schema, :load_sql_schema
@@ -49,7 +47,7 @@ class Ardb::Adapter::Base
49
47
  "#{Factory.string}\\" \
50
48
  "#{Factory.string} " \
51
49
  "#{Factory.string}"
52
- exp = pattern.gsub("\\"){ "\\\\" }.gsub('%', "\\%").gsub('_', "\\_")
50
+ exp = pattern.gsub("\\"){ "\\\\" }.gsub("%", "\\%").gsub("_", "\\_")
53
51
  assert_equal exp, subject.escape_like_pattern(pattern)
54
52
 
55
53
  pattern = Factory.string
@@ -57,7 +55,7 @@ class Ardb::Adapter::Base
57
55
  end
58
56
 
59
57
  should "allow using a custom escape char when escaping like patterns" do
60
- escape_char = '#'
58
+ escape_char = "#"
61
59
  pattern = "#{Factory.string}%" \
62
60
  "#{Factory.string}_" \
63
61
  "#{Factory.string}\\" \
@@ -65,15 +63,10 @@ class Ardb::Adapter::Base
65
63
  "#{Factory.string} " \
66
64
  "#{Factory.string}"
67
65
  exp = pattern.gsub(escape_char, "#{escape_char}#{escape_char}")
68
- exp = exp.gsub('%', "#{escape_char}%").gsub('_', "#{escape_char}_")
66
+ exp = exp.gsub("%", "#{escape_char}%").gsub("_", "#{escape_char}_")
69
67
  assert_equal exp, subject.escape_like_pattern(pattern, escape_char)
70
68
  end
71
69
 
72
- should "not implement the foreign key sql meths" do
73
- assert_raises(NotImplementedError){ subject.foreign_key_add_sql }
74
- assert_raises(NotImplementedError){ subject.foreign_key_drop_sql }
75
- end
76
-
77
70
  should "not implement the create and drop db methods" do
78
71
  assert_raises(NotImplementedError){ subject.create_db }
79
72
  assert_raises(NotImplementedError){ subject.drop_db }
@@ -95,7 +88,6 @@ class Ardb::Adapter::Base
95
88
  non_matching_adapter = Ardb::Adapter::Base.new(Factory.ardb_config)
96
89
  assert_not_equal non_matching_adapter, subject
97
90
  end
98
-
99
91
  end
100
92
 
101
93
  class ConnectDbTests < UnitTests
@@ -114,58 +106,64 @@ class Ardb::Adapter::Base
114
106
  @ar_with_connection_called = true
115
107
  end
116
108
 
117
- @adapter.connect_db
109
+ subject.connect_db
118
110
  end
119
111
 
120
112
  should "use activerecord to establish and then checkout a connection" do
121
113
  assert_equal subject.connect_hash, @ar_establish_connection_called_with
122
114
  assert_true @ar_with_connection_called
123
115
  end
124
-
125
116
  end
126
117
 
127
- class MigrateDbTests < UnitTests
128
- desc "`migrate_db`"
118
+ class MigrateTests < UnitTests
129
119
  setup do
130
- @orig_migrate_version_env_var = ENV['MIGRATE_VERSION']
131
- @orig_migrate_query_env_var = ENV['MIGRATE_QUIET']
132
-
133
- ENV["MIGRATE_VERSION"] = Factory.integer.to_s if Factory.boolean
134
- ENV["MIGRATE_QUIET"] = Factory.boolean.to_s if Factory.boolean
135
-
136
- @migrator_called_with = []
137
- Assert.stub(ActiveRecord::Migrator, :migrate) do |*args|
138
- @migrator_called_with = args
120
+ Assert.stub(ActiveRecord::MigrationContext, :new) do |*args, &block|
121
+ @fake_migration_context ||= FakeMigrationContext.new(*args)
139
122
  end
140
-
141
- @adapter.migrate_db
142
- end
143
- teardown do
144
- ENV['MIGRATE_VERSION'] = @orig_migrate_version_env_var
145
- ENV['MIGRATE_QUIET'] = @orig_migrate_query_env_var
146
123
  end
147
124
 
148
- should "add the ardb migration helper recorder to activerecord's command recorder" do
149
- exp = Ardb::MigrationHelpers::RecorderMixin
150
- assert_includes exp, ActiveRecord::Migration::CommandRecorder
125
+ should "migrate the db with `migrate_db`" do
126
+ subject.migrate_db
127
+
128
+ assert_equal [subject.migrations_path], @fake_migration_context.init_with
129
+ assert_equal [nil], @fake_migration_context.up_called_with
151
130
  end
152
131
 
153
- should "set the activerecord migrator's migrations path" do
154
- exp = subject.migrations_path
155
- assert_equal exp, ActiveRecord::Migrator.migrations_path
132
+ should "migrate the db with `migrate_db_up`" do
133
+ subject.migrate_db_up
134
+ assert_equal [nil], @fake_migration_context.up_called_with
135
+
136
+ target = Factory.string
137
+ subject.migrate_db_up(target)
138
+ assert_equal [target], @fake_migration_context.up_called_with
156
139
  end
157
140
 
158
- should "set the activerecord migration's verbose attr" do
159
- exp = ENV["MIGRATE_QUIET"].nil?
160
- assert_equal exp, ActiveRecord::Migration.verbose
141
+ should "migrate the db with `migrate_db_down`" do
142
+ subject.migrate_db_down
143
+ assert_equal [nil], @fake_migration_context.down_called_with
144
+
145
+ target = Factory.string
146
+ subject.migrate_db_down(target)
147
+ assert_equal [target], @fake_migration_context.down_called_with
161
148
  end
162
149
 
163
- should "call the activerecord migrator's migrate method" do
164
- version = ENV.key?("MIGRATE_VERSION") ? ENV["MIGRATE_VERSION"].to_i : nil
165
- exp = [subject.migrations_path, version]
166
- assert_equal exp, @migrator_called_with
150
+ should "migrate the db with `migrate_db_forward`" do
151
+ subject.migrate_db_forward
152
+ assert_equal [1], @fake_migration_context.forward_called_with
153
+
154
+ steps = Factory.integer(3)
155
+ subject.migrate_db_forward(steps)
156
+ assert_equal [steps], @fake_migration_context.forward_called_with
167
157
  end
168
158
 
159
+ should "migrate the db with `migrate_db_backward`" do
160
+ subject.migrate_db_backward
161
+ assert_equal [1], @fake_migration_context.rollback_called_with
162
+
163
+ steps = Factory.integer(3)
164
+ subject.migrate_db_backward(steps)
165
+ assert_equal [steps], @fake_migration_context.rollback_called_with
166
+ end
169
167
  end
170
168
 
171
169
  class LoadAndDumpSchemaTests < UnitTests
@@ -238,12 +236,11 @@ class Ardb::Adapter::Base
238
236
  subject.load_schema
239
237
  assert_empty @captured_stdout
240
238
  end
241
-
242
239
  end
243
240
 
244
241
  class LoadRubySchemaTests < UnitTests
245
242
  setup do
246
- @config.schema_path = File.join(TEST_SUPPORT_PATH, 'fake_schema')
243
+ @config.schema_path = File.join(TEST_SUPPORT_PATH, "fake_schema")
247
244
  @adapter = Ardb::Adapter::Base.new(@config)
248
245
  end
249
246
 
@@ -255,12 +252,11 @@ class Ardb::Adapter::Base
255
252
  subject.load_ruby_schema
256
253
  assert_equal 2, FAKE_SCHEMA.load_count
257
254
  end
258
-
259
255
  end
260
256
 
261
257
  class DumpRubySchemaTests < UnitTests
262
258
  setup do
263
- @config.schema_path = File.join(TMP_PATH, 'testdb', 'test_dump_ruby_schema')
259
+ @config.schema_path = File.join(TMP_PATH, "testdb", "test_dump_ruby_schema")
264
260
  FileUtils.rm_rf(File.dirname(@config.schema_path))
265
261
 
266
262
  @schema_dumper_connection, @schema_dumper_file = [nil, nil]
@@ -286,7 +282,6 @@ class Ardb::Adapter::Base
286
282
  assert_instance_of File, @schema_dumper_file
287
283
  assert_equal subject.ruby_schema_path, @schema_dumper_file.path
288
284
  end
289
-
290
285
  end
291
286
 
292
287
  class FakeConnection; end
@@ -328,4 +323,29 @@ class Ardb::Adapter::Base
328
323
  def with_connection(&block); end
329
324
  end
330
325
 
326
+ class FakeMigrationContext
327
+ attr_reader :init_with
328
+ attr_reader :up_called_with, :down_called_with
329
+ attr_reader :forward_called_with, :rollback_called_with
330
+
331
+ def initialize(*args)
332
+ @init_with = args
333
+ end
334
+
335
+ def up(*args)
336
+ @up_called_with = args
337
+ end
338
+
339
+ def down(*args)
340
+ @down_called_with = args
341
+ end
342
+
343
+ def forward(*args)
344
+ @forward_called_with = args
345
+ end
346
+
347
+ def rollback(*args)
348
+ @rollback_called_with = args
349
+ end
350
+ end
331
351
  end
@@ -1,8 +1,7 @@
1
- require 'assert'
2
- require 'ardb/adapter/mysql'
1
+ require "assert"
2
+ require "ardb/adapter/mysql"
3
3
 
4
4
  class Ardb::Adapter::Mysql
5
-
6
5
  class UnitTests < Assert::Context
7
6
  desc "Ardb::Adapter::Mysql"
8
7
  setup do
@@ -11,20 +10,6 @@ class Ardb::Adapter::Mysql
11
10
  end
12
11
  subject{ @adapter }
13
12
 
14
- should "know its foreign key add sql" do
15
- exp_add_sql = "ALTER TABLE :from_table"\
16
- " ADD CONSTRAINT :name"\
17
- " FOREIGN KEY (:from_column)"\
18
- " REFERENCES :to_table (:to_column)"
19
- assert_equal exp_add_sql, subject.foreign_key_add_sql
20
- end
21
-
22
- should "know its foreign key drop sql" do
23
- exp_drop_sql = "ALTER TABLE :from_table"\
24
- " DROP FOREIGN KEY :name"
25
- assert_equal exp_drop_sql, subject.foreign_key_drop_sql
26
- end
27
-
28
13
  # not currently implemented, see: https://github.com/redding/ardb/issues/13
29
14
  should "not implement the create and drop db methods" do
30
15
  assert_raises(NotImplementedError){ subject.create_db }
@@ -35,7 +20,5 @@ class Ardb::Adapter::Mysql
35
20
  should "not implement the drop tables method" do
36
21
  assert_raises(NotImplementedError){ subject.drop_tables }
37
22
  end
38
-
39
23
  end
40
-
41
24
  end
@@ -1,10 +1,9 @@
1
- require 'assert'
2
- require 'ardb/adapter/postgresql'
1
+ require "assert"
2
+ require "ardb/adapter/postgresql"
3
3
 
4
- require 'scmd'
4
+ require "scmd"
5
5
 
6
6
  class Ardb::Adapter::Postgresql
7
-
8
7
  class UnitTests < Assert::Context
9
8
  desc "Ardb::Adapter::Postgresql"
10
9
  setup do
@@ -17,35 +16,27 @@ class Ardb::Adapter::Postgresql
17
16
 
18
17
  should "know its public connect hash" do
19
18
  exp = subject.connect_hash.merge({
20
- 'database' => 'postgres',
21
- 'schema_search_path' => 'public'
19
+ "database" => "postgres",
20
+ "schema_search_path" => "public"
22
21
  })
23
22
  assert_equal exp, subject.public_connect_hash
24
23
  end
25
24
 
26
- should "know its foreign key add sql" do
27
- exp_add_sql = "ALTER TABLE :from_table"\
28
- " ADD CONSTRAINT :name"\
29
- " FOREIGN KEY (:from_column)"\
30
- " REFERENCES :to_table (:to_column)"
31
- assert_equal exp_add_sql, subject.foreign_key_add_sql
32
- end
33
-
34
- should "know its foreign key drop sql" do
35
- exp_drop_sql = "ALTER TABLE :from_table"\
36
- " DROP CONSTRAINT :name"
37
- assert_equal exp_drop_sql, subject.foreign_key_drop_sql
25
+ should "complain if given a database name with non-word characters" do
26
+ @config.database = "#{Factory.string}-#{Factory.string}"
27
+ assert_raises(Ardb::ConfigurationError){
28
+ Ardb::Adapter::Postgresql.new(@config)
29
+ }
38
30
  end
39
-
40
31
  end
41
32
 
42
33
  class SQLSchemaTests < UnitTests
43
34
  setup do
44
35
  @env = {
45
- 'PGHOST' => @adapter.connect_hash['host'],
46
- 'PGPORT' => @adapter.connect_hash['port'],
47
- 'PGUSER' => @adapter.connect_hash['username'],
48
- 'PGPASSWORD' => @adapter.connect_hash['password']
36
+ "PGHOST" => @adapter.connect_hash["host"],
37
+ "PGPORT" => @adapter.connect_hash["port"],
38
+ "PGUSER" => @adapter.connect_hash["username"],
39
+ "PGPASSWORD" => @adapter.connect_hash["password"]
49
40
  }
50
41
  end
51
42