1
0
Fork 0
mirror of https://github.com/rails/rails.git synced 2022-11-09 12:12:34 -05:00

Add support for generate scaffold password:digest

* adds password_digest attribute to the migration
* adds has_secure_password to the model
* adds password and password_confirmation password_fields to _form.html
* omits password entirely from index.html and show.html
* adds password and password_confirmation to the controller
* adds unencrypted password and password_confirmation to the controller test
* adds encrypted password_digest to the fixture
This commit is contained in:
Sam Ruby 2013-03-13 08:08:56 -04:00
parent cd9f7508df
commit 3008994d1e
11 changed files with 90 additions and 14 deletions

View file

@ -2,8 +2,12 @@ class <%= migration_class_name %> < ActiveRecord::Migration
def change def change
create_table :<%= table_name %> do |t| create_table :<%= table_name %> do |t|
<% attributes.each do |attribute| -%> <% attributes.each do |attribute| -%>
<% if attribute.password_digest? -%>
t.string :password_digest<%= attribute.inject_options %>
<% else -%>
t.<%= attribute.type %> :<%= attribute.name %><%= attribute.inject_options %> t.<%= attribute.type %> :<%= attribute.name %><%= attribute.inject_options %>
<% end -%> <% end -%>
<% end -%>
<% if options[:timestamps] %> <% if options[:timestamps] %>
t.timestamps t.timestamps
<% end -%> <% end -%>

View file

@ -1,7 +1,10 @@
<% module_namespacing do -%> <% module_namespacing do -%>
class <%= class_name %> < <%= parent_class_name.classify %> class <%= class_name %> < <%= parent_class_name.classify %>
<% attributes.select {|attr| attr.reference? }.each do |attribute| -%> <% attributes.select(&:reference?).each do |attribute| -%>
belongs_to :<%= attribute.name %><%= ', polymorphic: true' if attribute.polymorphic? %> belongs_to :<%= attribute.name %><%= ', polymorphic: true' if attribute.polymorphic? %>
<% end -%> <% end -%>
<% if attributes.any?(&:password_digest?) -%>
has_secure_password
<% end -%>
end end
<% end -%> <% end -%>

View file

@ -1,5 +1,17 @@
## Rails 4.0.0 (unreleased) ## ## Rails 4.0.0 (unreleased) ##
* Add support for generate scaffold password:digest
* adds password_digest attribute to the migration
* adds has_secure_password to the model
* adds password and password_confirmation password_fields to _form.html
* omits password from index.html and show.html
* adds password and password_confirmation to the controller
* adds unencrypted password and password_confirmation to the controller test
* adds encrypted password_digest to the fixture
*Sam Ruby*
* Rails now generates a `test/test_helper.rb` file with `fixtures :all` commented out by default, * Rails now generates a `test/test_helper.rb` file with `fixtures :all` commented out by default,
since we don't want to force loading all fixtures for user when a single test is run. However, since we don't want to force loading all fixtures for user when a single test is run. However,
fixtures are still going to be loaded automatically for test suites. fixtures are still going to be loaded automatically for test suites.

View file

@ -13,8 +13,17 @@
<% attributes.each do |attribute| -%> <% attributes.each do |attribute| -%>
<div class="field"> <div class="field">
<% if attribute.password_digest? -%>
<%%= f.label :password %><br />
<%%= f.password_field :password %>
</div>
<div>
<%%= f.label :password_confirmation %><br />
<%%= f.password_field :password_confirmation %>
<% else -%>
<%%= f.label :<%= attribute.name %> %><br /> <%%= f.label :<%= attribute.name %> %><br />
<%%= f.<%= attribute.field_type %> :<%= attribute.name %> %> <%%= f.<%= attribute.field_type %> :<%= attribute.name %> %>
<% end -%>
</div> </div>
<% end -%> <% end -%>
<div class="actions"> <div class="actions">

View file

@ -3,7 +3,7 @@
<table> <table>
<thead> <thead>
<tr> <tr>
<% attributes.each do |attribute| -%> <% attributes.reject(&:password_digest?).each do |attribute| -%>
<th><%= attribute.human_name %></th> <th><%= attribute.human_name %></th>
<% end -%> <% end -%>
<th></th> <th></th>
@ -15,7 +15,7 @@
<tbody> <tbody>
<%% @<%= plural_table_name %>.each do |<%= singular_table_name %>| %> <%% @<%= plural_table_name %>.each do |<%= singular_table_name %>| %>
<tr> <tr>
<% attributes.each do |attribute| -%> <% attributes.reject(&:password_digest?).each do |attribute| -%>
<td><%%= <%= singular_table_name %>.<%= attribute.name %> %></td> <td><%%= <%= singular_table_name %>.<%= attribute.name %> %></td>
<% end -%> <% end -%>
<td><%%= link_to 'Show', <%= singular_table_name %> %></td> <td><%%= link_to 'Show', <%= singular_table_name %> %></td>

View file

@ -1,6 +1,6 @@
<p id="notice"><%%= notice %></p> <p id="notice"><%%= notice %></p>
<% attributes.each do |attribute| -%> <% attributes.reject(&:password_digest?).each do |attribute| -%>
<p> <p>
<strong><%= attribute.human_name %>:</strong> <strong><%= attribute.human_name %>:</strong>
<%%= @<%= singular_table_name %>.<%= attribute.name %> %> <%%= @<%= singular_table_name %>.<%= attribute.name %> %>

View file

@ -130,6 +130,10 @@ module Rails
@has_uniq_index @has_uniq_index
end end
def password_digest?
name == 'password' && type == :digest
end
def inject_options def inject_options
"".tap { |s| @attr_options.each { |k,v| s << ", #{k}: #{v.inspect}" } } "".tap { |s| @attr_options.each { |k,v| s << ", #{k}: #{v.inspect}" } }
end end

View file

@ -163,6 +163,7 @@ module Rails
def attributes_names def attributes_names
@attributes_names ||= attributes.each_with_object([]) do |a, names| @attributes_names ||= attributes.each_with_object([]) do |a, names|
names << a.column_name names << a.column_name
names << 'password_confirmation' if a.password_digest?
names << "#{a.name}_type" if a.polymorphic? names << "#{a.name}_type" if a.polymorphic?
end end
end end

View file

@ -1,22 +1,20 @@
# Read about fixtures at http://api.rubyonrails.org/classes/ActiveRecord/Fixtures.html # Read about fixtures at http://api.rubyonrails.org/classes/ActiveRecord/Fixtures.html
<% unless attributes.empty? -%> <% unless attributes.empty? -%>
one: <% %w(one two).each do |name| %>
<%= name %>:
<% attributes.each do |attribute| -%> <% attributes.each do |attribute| -%>
<%- if attribute.password_digest? -%>
password_digest: <%%= BCrypt::Password.create('secret') %>
<%- else -%>
<%= yaml_key_value(attribute.column_name, attribute.default) %> <%= yaml_key_value(attribute.column_name, attribute.default) %>
<%- end -%>
<%- if attribute.polymorphic? -%> <%- if attribute.polymorphic? -%>
<%= yaml_key_value("#{attribute.name}_type", attribute.human_name) %> <%= yaml_key_value("#{attribute.name}_type", attribute.human_name) %>
<%- end -%> <%- end -%>
<% end -%> <% end -%>
two:
<% attributes.each do |attribute| -%>
<%= yaml_key_value(attribute.column_name, attribute.default) %>
<%- if attribute.polymorphic? -%>
<%= yaml_key_value("#{attribute.name}_type", attribute.human_name) %>
<%- end -%>
<% end -%> <% end -%>
<% else -%> <% else -%>
# This model initially had no columns defined. If you add columns to the # This model initially had no columns defined. If you add columns to the
# model remove the '{}' from the fixture names and add the columns immediately # model remove the '{}' from the fixture names and add the columns immediately
# below each fixture, per the syntax in the comments below # below each fixture, per the syntax in the comments below

View file

@ -21,7 +21,11 @@ module TestUnit # :nodoc:
return if attributes_names.empty? return if attributes_names.empty?
attributes_names.map do |name| attributes_names.map do |name|
"#{name}: @#{singular_table_name}.#{name}" if %w(password password_confirmation).include?(name) && attributes.any?(&:password_digest?)
"#{name}: 'secret'"
else
"#{name}: @#{singular_table_name}.#{name}"
end
end.sort.join(', ') end.sort.join(', ')
end end
end end

View file

@ -271,4 +271,45 @@ class ScaffoldGeneratorTest < Rails::Generators::TestCase
end end
end end
end end
def test_scaffold_generator_password_digest
run_generator ["user", "name", "password:digest"]
assert_file "app/models/user.rb", /has_secure_password/
assert_migration "db/migrate/create_users.rb" do |m|
assert_method :change, m do |up|
assert_match(/t\.string :name/, up)
assert_match(/t\.string :password_digest/, up)
end
end
assert_file "app/controllers/users_controller.rb" do |content|
assert_instance_method :user_params, content do |m|
assert_match(/permit\(:name, :password, :password_confirmation\)/, m)
end
end
assert_file "app/views/users/_form.html.erb" do |content|
assert_match(/<%= f\.password_field :password %>/, content)
assert_match(/<%= f\.password_field :password_confirmation %>/, content)
end
assert_file "app/views/users/index.html.erb" do |content|
assert_no_match(/password/, content)
end
assert_file "app/views/users/show.html.erb" do |content|
assert_no_match(/password/, content)
end
assert_file "test/controllers/users_controller_test.rb" do |content|
assert_match(/password: 'secret'/, content)
assert_match(/password_confirmation: 'secret'/, content)
end
assert_file "test/fixtures/users.yml" do |content|
assert_match(/password_digest: <%= BCrypt::Password.create\('secret'\) %>/, content)
end
end
end end