solidus_backend 2.10.0.beta1 → 2.10.5

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of solidus_backend might be problematic. Click here for more details.

Files changed (65) hide show
  1. checksums.yaml +4 -4
  2. data/app/assets/javascripts/spree/backend.js +1 -0
  3. data/app/assets/javascripts/spree/backend/components/admin_nav.js +24 -0
  4. data/app/assets/javascripts/spree/backend/components/tabs.js +1 -1
  5. data/app/assets/javascripts/spree/backend/views/order/address.js +7 -5
  6. data/app/assets/stylesheets/spree/backend/_bootstrap_custom.scss +2 -0
  7. data/app/assets/stylesheets/spree/backend/components/_breadcrumb.scss +3 -3
  8. data/app/assets/stylesheets/spree/backend/components/_messages.scss +4 -0
  9. data/app/assets/stylesheets/spree/backend/components/_navigation.scss +182 -49
  10. data/app/assets/stylesheets/spree/backend/globals/_variables.scss +2 -0
  11. data/app/assets/stylesheets/spree/backend/shared/_header.scss +5 -1
  12. data/app/assets/stylesheets/spree/backend/shared/_layout.scss +0 -9
  13. data/app/controllers/spree/admin/orders_controller.rb +2 -2
  14. data/app/controllers/spree/admin/payment_methods_controller.rb +3 -3
  15. data/app/controllers/spree/admin/payments_controller.rb +2 -2
  16. data/app/controllers/spree/admin/product_properties_controller.rb +1 -1
  17. data/app/controllers/spree/admin/products_controller.rb +1 -1
  18. data/app/controllers/spree/admin/resource_controller.rb +12 -3
  19. data/app/controllers/spree/admin/taxons/attachment_controller.rb +20 -0
  20. data/app/controllers/spree/admin/users_controller.rb +4 -0
  21. data/app/helpers/spree/admin/orders_helper.rb +1 -1
  22. data/app/views/spree/admin/customer_returns/new.html.erb +1 -1
  23. data/app/views/spree/admin/option_types/edit.html.erb +1 -1
  24. data/app/views/spree/admin/orders/edit.html.erb +1 -1
  25. data/app/views/spree/admin/payment_methods/new.html.erb +1 -1
  26. data/app/views/spree/admin/prices/_master_variant_table.html.erb +41 -41
  27. data/app/views/spree/admin/promotion_code_batches/new.html.erb +1 -1
  28. data/app/views/spree/admin/promotion_codes/new.html.erb +1 -1
  29. data/app/views/spree/admin/promotions/_actions.html.erb +1 -0
  30. data/app/views/spree/admin/return_authorizations/new.html.erb +1 -1
  31. data/app/views/spree/admin/shared/_calculator_fields.html.erb +5 -0
  32. data/app/views/spree/admin/shared/_navigation.html.erb +3 -0
  33. data/app/views/spree/admin/shared/_new_resource_links.html.erb +1 -1
  34. data/app/views/spree/admin/shared/_settings_sub_menu.html.erb +1 -1
  35. data/app/views/spree/admin/shipping_methods/_form.html.erb +1 -1
  36. data/app/views/spree/admin/tax_rates/_form.html.erb +1 -1
  37. data/app/views/spree/admin/taxonomies/new.html.erb +1 -1
  38. data/app/views/spree/admin/taxons/_form.html.erb +1 -5
  39. data/app/views/spree/admin/taxons/attachment_forms/_paperclip.html.erb +16 -0
  40. data/app/views/spree/admin/users/_form.html.erb +12 -10
  41. data/app/views/spree/admin/users/edit.html.erb +1 -2
  42. data/app/views/spree/layouts/admin.html.erb +1 -2
  43. data/config/routes.rb +4 -6
  44. data/lib/spree/backend_configuration.rb +2 -1
  45. data/solidus_backend.gemspec +1 -1
  46. data/spec/controllers/spree/admin/resource_controller_spec.rb +12 -1
  47. data/spec/controllers/spree/admin/users_controller_spec.rb +23 -0
  48. data/spec/features/admin/configuration/payment_methods_spec.rb +11 -2
  49. data/spec/features/admin/configuration/shipping_methods_spec.rb +13 -1
  50. data/spec/features/admin/configuration/taxonomies_spec.rb +7 -0
  51. data/spec/features/admin/orders/customer_returns_spec.rb +20 -7
  52. data/spec/features/admin/orders/new_order_spec.rb +48 -0
  53. data/spec/features/admin/orders/return_authorizations_spec.rb +38 -9
  54. data/spec/features/admin/products/edit/images_spec.rb +1 -1
  55. data/spec/features/admin/products/products_spec.rb +12 -0
  56. data/spec/features/admin/promotion_adjustments_spec.rb +9 -0
  57. data/spec/features/admin/promotions/promotion_code_batches_spec.rb +37 -0
  58. data/spec/features/admin/promotions/promotion_code_spec.rb +31 -0
  59. data/spec/features/admin/taxons_spec.rb +12 -0
  60. data/spec/features/admin/users_spec.rb +18 -8
  61. data/spec/{support → fixtures/files}/ror_ringer.jpeg +0 -0
  62. data/spec/spec_helper.rb +1 -0
  63. data/spec/support/feature/base_feature_helper.rb +6 -1
  64. data/vendor/assets/stylesheets/solidus_admin/bootstrap/_variables.scss +1 -1
  65. metadata +17 -12
@@ -12,15 +12,6 @@ body {
12
12
  background-color: $admin-body-bg;
13
13
  }
14
14
 
15
- .admin-nav {
16
- position: absolute;
17
- top: 0;
18
- bottom: 0;
19
- left: 0;
20
- width: $width-sidebar;
21
- @media print { display: none }
22
- }
23
-
24
15
  .content-wrapper {
25
16
  background-color: $content-wrapper-bg;
26
17
  padding-top: 1rem;
@@ -105,8 +105,8 @@ module Spree
105
105
  @order.complete!
106
106
  flash[:success] = t('spree.order_completed')
107
107
  redirect_to edit_admin_order_url(@order)
108
- rescue StateMachines::InvalidTransition => e
109
- flash[:error] = e.message
108
+ rescue StateMachines::InvalidTransition => error
109
+ flash[:error] = error.message
110
110
  redirect_to confirm_admin_order_url(@order)
111
111
  end
112
112
 
@@ -28,9 +28,9 @@ module Spree
28
28
  invoke_callbacks(:update, :before)
29
29
 
30
30
  attributes = payment_method_params
31
- attributes.each do |k, _v|
32
- if k.include?("password") && attributes[k].blank?
33
- attributes.delete(k)
31
+ attributes.each do |key, _value|
32
+ if key.include?("password") && attributes[key].blank?
33
+ attributes.delete(key)
34
34
  end
35
35
  end
36
36
 
@@ -46,8 +46,8 @@ module Spree
46
46
  flash[:error] = t('spree.payment_could_not_be_created')
47
47
  render :new
48
48
  end
49
- rescue Spree::Core::GatewayError => e
50
- flash[:error] = e.message.to_s
49
+ rescue Spree::Core::GatewayError => error
50
+ flash[:error] = error.message.to_s
51
51
  redirect_to new_admin_order_payment_path(@order)
52
52
  end
53
53
  end
@@ -3,7 +3,7 @@
3
3
  module Spree
4
4
  module Admin
5
5
  class ProductPropertiesController < ResourceController
6
- belongs_to 'spree/product', find_by: :slug
6
+ belongs_to 'spree/product', find_by: :slug, includes: { product_properties: :property }
7
7
  before_action :find_properties
8
8
  before_action :setup_property, only: :index, if: -> { can?(:create, model_class) }
9
9
  before_action :setup_variant_property_rules, only: :index
@@ -120,7 +120,7 @@ module Spree
120
120
  end
121
121
 
122
122
  def product_includes
123
- [{ variants: [:images], master: [:images, :default_price] }]
123
+ [:variant_images, { variants: [:images], master: [:images, :default_price] }]
124
124
  end
125
125
 
126
126
  def clone_object_url(resource)
@@ -107,8 +107,14 @@ class Spree::Admin::ResourceController < Spree::Admin::BaseController
107
107
  else
108
108
  invoke_callbacks(:destroy, :fails)
109
109
  respond_with(@object) do |format|
110
- format.html { redirect_to location_after_destroy }
111
- format.js { render status: :unprocessable_entity, plain: @object.errors.full_messages.join(', ') }
110
+ message = @object.errors.full_messages.to_sentence
111
+ format.html do
112
+ flash[:error] = message
113
+ redirect_to location_after_destroy
114
+ end
115
+ format.js do
116
+ render status: :unprocessable_entity, plain: message
117
+ end
112
118
  end
113
119
  end
114
120
  end
@@ -123,6 +129,7 @@ class Spree::Admin::ResourceController < Spree::Admin::BaseController
123
129
  @parent_data[:model_name] = model_name
124
130
  @parent_data[:model_class] = (options[:model_class] || model_name.to_s.classify.constantize)
125
131
  @parent_data[:find_by] = options[:find_by] || :id
132
+ @parent_data[:includes] = options[:includes]
126
133
  end
127
134
  end
128
135
 
@@ -183,7 +190,9 @@ class Spree::Admin::ResourceController < Spree::Admin::BaseController
183
190
 
184
191
  def parent
185
192
  if parent?
186
- @parent ||= self.class.parent_data[:model_class].find_by(self.class.parent_data[:find_by] => params["#{parent_model_name}_id"])
193
+ @parent ||= self.class.parent_data[:model_class]
194
+ .includes(self.class.parent_data[:includes])
195
+ .find_by(self.class.parent_data[:find_by] => params["#{parent_model_name}_id"])
187
196
  instance_variable_set("@#{parent_model_name}", @parent)
188
197
  else
189
198
  Spree::Deprecation.warn "Calling #parent is deprecated on a ResourceController which has not defined a belongs_to"
@@ -0,0 +1,20 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Spree
4
+ module Admin
5
+ module Taxons
6
+ class AttachmentController < Spree::Admin::BaseController
7
+ def destroy
8
+ taxonomy = Spree::Taxonomy.find(params[:taxonomy_id])
9
+ taxon = taxonomy.taxons.find(params[:taxon_id])
10
+ if taxon.destroy_attachment(params[:attachment_definition])
11
+ flash[:success] = t('spree.successfully_removed', resource: params[:attachment_definition].titleize)
12
+ else
13
+ flash[:error] = t('spree.taxon_attachment_removal_error')
14
+ end
15
+ redirect_to edit_admin_taxonomy_taxon_path(taxonomy, taxon.id)
16
+ end
17
+ end
18
+ end
19
+ end
20
+ end
@@ -131,6 +131,10 @@ module Spree
131
131
  attributes += [{ spree_role_ids: [] }]
132
132
  end
133
133
 
134
+ unless can? :update_password, @user
135
+ attributes -= [:password, :password_confirmation]
136
+ end
137
+
134
138
  params.require(:user).permit(attributes)
135
139
  end
136
140
 
@@ -8,7 +8,7 @@ module Spree
8
8
  links = []
9
9
  @order_events.sort.each do |event|
10
10
  next unless @order.send("can_#{event}?")
11
- links << button_to(t(event, scope: 'spree'), [event, :admin, @order],
11
+ links << button_to(t(event, scope: 'spree'), [event.to_sym, :admin, @order],
12
12
  method: :put,
13
13
  data: { confirm: t('spree.order_sure_want_to', event: t(event, scope: 'spree')) })
14
14
  end
@@ -40,7 +40,7 @@
40
40
  </div>
41
41
 
42
42
  <div class="form-buttons filter-actions actions" data-hook="buttons">
43
- <%= button_tag t('spree.actions.create'), class: 'btn btn-primary' %>
43
+ <%= f.submit t('spree.actions.create'), class: 'btn btn-primary' %>
44
44
  <%= link_to t('spree.actions.cancel'), admin_order_customer_returns_url(@order), class: 'btn btn-primary' %>
45
45
  </div>
46
46
  </fieldset>
@@ -9,7 +9,7 @@
9
9
  <%= link_to_add_fields t('spree.add_option_value'), "tbody#option_values", class: 'btn btn-primary' %>
10
10
  </span>
11
11
  </li>
12
- <% end %>
12
+ <% end %>
13
13
 
14
14
  <%= render partial: 'spree/shared/error_messages', locals: { target: @option_type } %>
15
15
 
@@ -18,7 +18,7 @@
18
18
  <%= render 'spree/admin/orders/risk_analysis', latest_payment: @order.payments.reorder("created_at DESC").first %>
19
19
  <% end %>
20
20
 
21
- <div data-hook="admin_order_edit_sub_header" />
21
+ <div data-hook="admin_order_edit_sub_header"></div>
22
22
 
23
23
  <% if @order.line_items.empty? %>
24
24
  <div class="no-objects-found">
@@ -15,7 +15,7 @@
15
15
  <fieldset class="no-border-top">
16
16
  <%= render partial: 'form', locals: { f: f } %>
17
17
  <div data-hook="buttons" class="filter-actions actions">
18
- <%= button_tag t('spree.actions.create'), class: 'btn btn-primary' %>
18
+ <%= f.submit t('spree.actions.create'), class: 'btn btn-primary' %>
19
19
  </div>
20
20
  </fieldset>
21
21
  <% end %>
@@ -1,41 +1,41 @@
1
- <div class="row">
2
- <div class="col-12">
3
- <fieldset class="no-border-bottom <%= "no-border-top" if !variants %>">
4
- <% if variants %>
5
- <legend align="center"><%= I18n.t(:master_variant, scope: :spree) %> <%= admin_hint I18n.t(:master_variant, scope: :spree), I18n.t(:master_variant, scope: [:spree, :hints, "spree/price"]) %></legend>
6
- <% end %>
7
- <table class="index master_prices">
8
- <colgroup>
9
- <col style="width: 30%">
10
- <col style="width: 30%">
11
- <col style="width: 20%">
12
- <col style="width: 20%">
13
- </colgroup>
14
- <thead data-hook="master_prices_header">
15
- <tr>
16
- <th><%= Spree::Price.human_attribute_name(:country) %></th>
17
- <th><%= Spree::Price.human_attribute_name(:currency) %></th>
18
- <th><%= Spree::Price.human_attribute_name(:amount) %></th>
19
- <th class="actions"></th>
20
- </tr>
21
- </thead>
22
- <% master_prices.each do |price| %>
23
- <tr id="<%= spree_dom_id price %>" data-hook="prices_row" class="<%= "deleted" if price.deleted? %>">
24
- <td><%= price.display_country %></td>
25
- <td><%= price.currency %></td>
26
- <td><%= price.money.to_html %></td>
27
- <td class="actions">
28
- <% if can?(:update, price) %>
29
- <%= link_to_edit(price, no_text: true) unless price.deleted? %>
30
- <% end %>
31
- <% if can?(:destroy, price) %>
32
- &nbsp;
33
- <%= link_to_delete(price, no_text: true) unless price.deleted? %>
34
- <% end %>
35
- </td>
36
- </tr>
37
- <% end %>
38
- </table>
39
- </fieldset>
40
- </div>
41
- </div>
1
+ <%= paginate master_prices, theme: "solidus_admin" %>
2
+
3
+ <fieldset class="no-border-bottom <%= "no-border-top" if !variants %>">
4
+ <% if variants %>
5
+ <legend align="center"><%= I18n.t(:master_variant, scope: :spree) %> <%= admin_hint I18n.t(:master_variant, scope: :spree), I18n.t(:master_variant, scope: [:spree, :hints, "spree/price"]) %></legend>
6
+ <% end %>
7
+ <table class="index master_prices">
8
+ <colgroup>
9
+ <col style="width: 30%">
10
+ <col style="width: 30%">
11
+ <col style="width: 20%">
12
+ <col style="width: 20%">
13
+ </colgroup>
14
+ <thead data-hook="master_prices_header">
15
+ <tr>
16
+ <th><%= Spree::Price.human_attribute_name(:country) %></th>
17
+ <th><%= Spree::Price.human_attribute_name(:currency) %></th>
18
+ <th><%= Spree::Price.human_attribute_name(:amount) %></th>
19
+ <th class="actions"></th>
20
+ </tr>
21
+ </thead>
22
+ <% master_prices.each do |price| %>
23
+ <tr id="<%= spree_dom_id price %>" data-hook="prices_row" class="<%= "deleted" if price.deleted? %>">
24
+ <td><%= price.display_country %></td>
25
+ <td><%= price.currency %></td>
26
+ <td><%= price.money.to_html %></td>
27
+ <td class="actions">
28
+ <% if can?(:update, price) %>
29
+ <%= link_to_edit(price, no_text: true) unless price.deleted? %>
30
+ <% end %>
31
+ <% if can?(:destroy, price) %>
32
+ &nbsp;
33
+ <%= link_to_delete(price, no_text: true) unless price.deleted? %>
34
+ <% end %>
35
+ </td>
36
+ </tr>
37
+ <% end %>
38
+ </table>
39
+ </fieldset>
40
+
41
+ <%= paginate master_prices, theme: "solidus_admin" %>
@@ -24,5 +24,5 @@
24
24
  <%= f.label :email %>
25
25
  <%= f.text_field :email, class: "fullwidth", value: spree_current_user.email %>
26
26
  <% end %>
27
- <%= button_tag t('spree.actions.create'), class: 'btn btn-primary' %>
27
+ <%= f.submit t('spree.actions.create'), class: 'btn btn-primary' %>
28
28
  <% end %>
@@ -24,7 +24,7 @@
24
24
  </div>
25
25
 
26
26
  <div class="form-buttons filter-actions actions" data-hook="buttons">
27
- <%= button_tag t('spree.actions.create'), class: 'btn btn-primary' %>
27
+ <%= f.submit t('spree.actions.create'), class: 'btn btn-primary' %>
28
28
  <%= link_to t('spree.actions.cancel'), admin_promotion_promotion_codes_url(@promotion), class: 'button' %>
29
29
  </div>
30
30
  </fieldset>
@@ -7,6 +7,7 @@
7
7
  <% if can?(:update, @promotion) %>
8
8
  <div class="field">
9
9
  <%= label_tag :action_type, t('spree.adjustment_type')%>
10
+ <%= admin_hint t('spree.adjustment_type'), t(:promotions, scope: [:spree, :hints, "spree/calculator"]) %>
10
11
  <%= select_tag 'action_type', options, include_blank: t(:choose_promotion_action, scope: 'spree'), class: 'custom-select fullwidth' %>
11
12
  </div>
12
13
  <div class="filter-actions actions">
@@ -13,7 +13,7 @@
13
13
  <%= render partial: 'form', locals: { f: f } %>
14
14
 
15
15
  <div class="form-buttons filter-actions actions" data-hook="buttons">
16
- <%= button_tag t('spree.actions.create'), class: 'btn btn-primary' %>
16
+ <%= f.submit t('spree.actions.create'), class: 'btn btn-primary' %>
17
17
  <%= link_to t('spree.actions.cancel'), admin_order_return_authorizations_url(@order), class: 'btn btn-primary' %>
18
18
  </div>
19
19
  </fieldset>
@@ -4,6 +4,11 @@
4
4
  <div id="preference-settings">
5
5
  <div class="field">
6
6
  <%= f.label(:calculator_type, Spree::Calculator.model_name.human) %>
7
+
8
+ <% if local_assigns.has_key? :hint %>
9
+ <%= admin_hint t("spree.#{hint}"), t(hint, scope: [:spree, :hints, "spree/calculator"]) %>
10
+ <% end %>
11
+
7
12
  <%= f.select(:calculator_type, @calculators.map { |c| [c.description, c.name] }, {}, {class: 'custom-select fullwidth js-calculator-type'}) %>
8
13
  </div>
9
14
 
@@ -3,6 +3,9 @@
3
3
  <div class="admin-nav-sticky">
4
4
  <%= render partial: 'spree/admin/shared/menu' %>
5
5
  <div class="admin-nav-footer">
6
+ <%= button_tag class: 'btn fa fa-chevron-circle-left', id: 'admin-nav-toggle', type: :button do %>
7
+ <span class="text"><%= t('spree.minimize_menu') %></span>
8
+ <% end %>
6
9
  <%= render partial: 'spree/admin/shared/locale_selection' %>
7
10
  <%= render partial: 'spree/admin/shared/navigation_footer' %>
8
11
  </div>
@@ -1,4 +1,4 @@
1
1
  <div class="form-buttons filter-actions actions" data-hook="buttons">
2
- <%= button_tag t('spree.actions.create'), class: 'btn btn-primary' %>
2
+ <%= submit_tag t('spree.actions.create'), class: 'btn btn-primary' %>
3
3
  <%= link_to t('spree.actions.cancel'), collection_url, class: 'button' %>
4
4
  </div>
@@ -13,7 +13,7 @@
13
13
 
14
14
  <% if can?(:display, Spree::RefundReason) || can?(:display, Spree::ReimbursementType) ||
15
15
  can?(:display, Spree::ReturnReason) || can?(:display, Spree::AdjustmentReason) %>
16
- <%= tab :checkout, url: spree.admin_refund_reasons_path, match_path: %r(refund_reasons|reimbursement_types|return_reasons|adjustment_reasons) %>
16
+ <%= tab :checkout, url: spree.admin_refund_reasons_path, match_path: %r(refund_reasons|reimbursement_types|return_reasons|adjustment_reasons|store_credit_reasons) %>
17
17
  <% end %>
18
18
 
19
19
  <% if can?(:display, Spree::ShippingMethod) || can?(:display, Spree::ShippingCategory) || can?(:display, Spree::StockLocation) %>
@@ -100,7 +100,7 @@
100
100
  </div>
101
101
  <div class="col-5">
102
102
  <div data-hook="admin_shipping_method_form_calculator_fields">
103
- <%= render partial: 'spree/admin/shared/calculator_fields', locals: { f: f } %>
103
+ <%= render partial: 'spree/admin/shared/calculator_fields', locals: { f: f, hint: :shipping_methods } %>
104
104
  </div>
105
105
  <div>
106
106
  <fieldset class="tax_categories no-border-bottom">
@@ -58,5 +58,5 @@
58
58
 
59
59
  <div class="clear"></div>
60
60
 
61
- <%= render 'spree/admin/shared/calculator_fields', f: f %>
61
+ <%= render partial: 'spree/admin/shared/calculator_fields', locals: { f: f, hint: :tax_rates } %>
62
62
  </div>
@@ -12,7 +12,7 @@
12
12
  <fieldset class="no-border-top">
13
13
  <br>
14
14
  <div class="filter-actions actions" data-hook="buttons">
15
- <%= button_tag t('spree.actions.create'), class: 'btn btn-primary' %>
15
+ <%= f.submit t('spree.actions.create'), class: 'btn btn-primary' %>
16
16
  </div>
17
17
  </fieldset>
18
18
  <% end %>
@@ -20,11 +20,7 @@
20
20
  </div>
21
21
  <% end %>
22
22
 
23
- <%= f.field_container :icon do %>
24
- <%= f.label :icon %><br />
25
- <%= f.file_field :icon %>
26
- <%= image_tag f.object.icon(:mini) if f.object.icon_present? %>
27
- <% end %>
23
+ <%= render "spree/admin/taxons/attachment_forms/#{f.object.attachment_partial_name}", f: f %>
28
24
  </div>
29
25
 
30
26
  <div class="col-5">
@@ -0,0 +1,16 @@
1
+ <% f.object.class.attachment_definitions.each do |attachment, definition| %>
2
+ <%= f.field_container attachment do %>
3
+ <%= f.label attachment %><br>
4
+ <%= f.file_field attachment %>
5
+ <% if f.object.send(attachment).exists? %>
6
+ <%= image_tag f.object.send(attachment, definition[:default_style]) %>
7
+ <%= link_to t('spree.actions.remove'),
8
+ admin_taxonomy_taxon_attachment_path(@taxonomy,
9
+ @taxon.id,
10
+ attachment_definition: attachment,
11
+ authenticity_token: form_authenticity_token),
12
+ method: :delete,
13
+ class: 'btn btn-sm btn-danger' %>
14
+ <% end %>
15
+ <% end %>
16
+ <% end %>
@@ -60,18 +60,20 @@
60
60
  </div>
61
61
 
62
62
  <div data-hook="admin_user_form_password_fields" class="col-6">
63
- <%= f.field_container :password do %>
64
- <%= f.label :password %>
65
- <%= f.password_field :password, class: 'fullwidth' %>
66
- <%= f.error_message_on :password %>
67
- <% end %>
63
+ <% if can? :update_password, @user %>
64
+ <%= f.field_container :password do %>
65
+ <%= f.label :password %>
66
+ <%= f.password_field :password, class: 'fullwidth' %>
67
+ <%= f.error_message_on :password %>
68
+ <% end %>
68
69
 
69
70
 
70
- <% if f.object.respond_to?(:password_confirmation) %>
71
- <%= f.field_container :password do %>
72
- <%= f.label :password_confirmation %>
73
- <%= f.password_field :password_confirmation, class: 'fullwidth' %>
74
- <%= f.error_message_on :password_confirmation %>
71
+ <% if f.object.respond_to?(:password_confirmation) %>
72
+ <%= f.field_container :password do %>
73
+ <%= f.label :password_confirmation %>
74
+ <%= f.password_field :password_confirmation, class: 'fullwidth' %>
75
+ <%= f.error_message_on :password_confirmation %>
76
+ <% end %>
75
77
  <% end %>
76
78
  <% end %>
77
79
  </div>