decidim-assemblies 0.20.1 → 0.21.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 (76) hide show
  1. checksums.yaml +4 -4
  2. data/app/cells/decidim/assemblies/assembly_m_cell.rb +1 -5
  3. data/app/commands/decidim/assemblies/admin/create_assemblies_type.rb +45 -0
  4. data/app/commands/decidim/assemblies/admin/create_assembly.rb +1 -2
  5. data/app/commands/decidim/assemblies/admin/destroy_assemblies_type.rb +45 -0
  6. data/app/commands/decidim/assemblies/admin/update_assemblies_type.rb +46 -0
  7. data/app/commands/decidim/assemblies/admin/update_assembly.rb +1 -2
  8. data/app/controllers/concerns/decidim/assemblies/admin/filterable.rb +30 -0
  9. data/app/controllers/decidim/assemblies/admin/assemblies_controller.rb +8 -23
  10. data/app/controllers/decidim/assemblies/admin/assemblies_types_controller.rb +107 -0
  11. data/app/controllers/decidim/assemblies/assemblies_controller.rb +1 -1
  12. data/app/forms/decidim/assemblies/admin/assemblies_type_form.rb +17 -0
  13. data/app/forms/decidim/assemblies/admin/assembly_form.rb +19 -10
  14. data/app/helpers/decidim/assemblies/admin/assemblies_helper.rb +6 -0
  15. data/app/helpers/decidim/assemblies/filter_assemblies_helper.rb +10 -7
  16. data/app/models/decidim/assemblies_type.rb +24 -0
  17. data/app/models/decidim/assembly.rb +12 -2
  18. data/app/models/decidim/assembly_user_role.rb +1 -1
  19. data/app/permissions/decidim/assemblies/permissions.rb +25 -0
  20. data/app/presenters/decidim/assemblies/admin_log/assemblies_type_presenter.rb +43 -0
  21. data/app/presenters/decidim/assemblies/admin_log/assembly_presenter.rb +1 -2
  22. data/app/presenters/decidim/log/value_types/assembly_type_presenter.rb +29 -0
  23. data/app/queries/decidim/assemblies/filtered_assemblies.rb +2 -2
  24. data/app/queries/decidim/assemblies/parent_assemblies_for_select.rb +23 -0
  25. data/app/services/decidim/assemblies/assembly_search.rb +3 -3
  26. data/app/types/decidim/assemblies/assemblies_type_type.rb +17 -0
  27. data/app/types/decidim/assemblies/assembly_member_type.rb +29 -0
  28. data/app/types/decidim/assemblies/assembly_type.rb +67 -0
  29. data/app/views/decidim/assemblies/_filter_by_type.html.erb +14 -12
  30. data/app/views/decidim/assemblies/admin/assemblies/_form.html.erb +2 -6
  31. data/app/views/decidim/assemblies/admin/assemblies/index.html.erb +5 -2
  32. data/app/views/decidim/assemblies/admin/assemblies_types/_form.html.erb +11 -0
  33. data/app/views/decidim/assemblies/admin/assemblies_types/edit.html.erb +6 -0
  34. data/app/views/decidim/assemblies/admin/assemblies_types/index.html.erb +43 -0
  35. data/app/views/decidim/assemblies/admin/assemblies_types/new.html.erb +7 -0
  36. data/app/views/decidim/assemblies/admin/assembly_members/index.html.erb +30 -30
  37. data/app/views/decidim/assemblies/assemblies/show.html.erb +1 -5
  38. data/app/views/layouts/decidim/admin/assemblies.html.erb +17 -0
  39. data/app/views/layouts/decidim/admin/assembly.html.erb +2 -2
  40. data/config/locales/ar.yml +24 -0
  41. data/config/locales/ca.yml +32 -0
  42. data/config/locales/cs.yml +33 -1
  43. data/config/locales/de.yml +11 -0
  44. data/config/locales/el.yml +1 -0
  45. data/config/locales/en.yml +32 -0
  46. data/config/locales/es-MX.yml +32 -0
  47. data/config/locales/es-PY.yml +32 -0
  48. data/config/locales/es.yml +32 -0
  49. data/config/locales/eu.yml +11 -0
  50. data/config/locales/fi-plain.yml +32 -0
  51. data/config/locales/fi.yml +32 -0
  52. data/config/locales/fr.yml +11 -0
  53. data/config/locales/gl.yml +11 -0
  54. data/config/locales/hu.yml +32 -0
  55. data/config/locales/id-ID.yml +11 -0
  56. data/config/locales/is-IS.yml +11 -0
  57. data/config/locales/it.yml +20 -0
  58. data/config/locales/nl.yml +20 -0
  59. data/config/locales/no.yml +31 -0
  60. data/config/locales/pl.yml +11 -0
  61. data/config/locales/pt-BR.yml +11 -0
  62. data/config/locales/pt.yml +11 -0
  63. data/config/locales/ru.yml +11 -0
  64. data/config/locales/sv.yml +11 -0
  65. data/config/locales/tr-TR.yml +11 -0
  66. data/config/locales/uk.yml +11 -0
  67. data/db/migrate/20200108113855_create_decidim_assembly_types.rb +19 -0
  68. data/db/migrate/20200108123050_migrate_decidim_assembly_types.rb +83 -0
  69. data/lib/decidim/assemblies/admin_engine.rb +2 -0
  70. data/lib/decidim/assemblies/engine.rb +7 -0
  71. data/lib/decidim/assemblies/participatory_space.rb +3 -2
  72. data/lib/decidim/assemblies/query_extensions.rb +40 -0
  73. data/lib/decidim/assemblies/test/factories.rb +24 -2
  74. data/lib/decidim/assemblies/version.rb +1 -1
  75. metadata +29 -9
  76. data/app/views/decidim/assemblies/assembly_widgets/show.html.erb +0 -11
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 4bce95b5a50ca5a51acc8ec5006c31433e1221e6c4261797ceeb55a4440df460
4
- data.tar.gz: 33e3a8271d02f6f50816d6a554212877d50ecccd96835e291b9e24675011d1ad
3
+ metadata.gz: 59b7c6152c1d1c2c96dc32b800435039413c4a9ad9e91150dd5101251af5fdba
4
+ data.tar.gz: 9d4370974c2dacb07d232fee8dcde3aa92a3b74e86b7aaf836860c32a3120ec2
5
5
  SHA512:
6
- metadata.gz: fe93f7eab23f14845eb11443873be2dff139b860c021284197a50b1bbc0dd4e49715cd0a357cd903c0a5123221c74db4c2e832b8993878fba4b611613eaed698
7
- data.tar.gz: f2aa517dd035ff6c746e545f15f54e7c93ddc3778ae90c63f29444554ee1fc8c9d8d60679f69a2864f629ecb7e60721d36e7b7185ce0b9f305fbe1e72412f6d3
6
+ metadata.gz: 84c422de10b4da4aac9d0e3e7ec291bd32664641d8a163ab68072615c5d23816a7c804939b1023b930c9fbfec93cccdcb5a990a1ed62e28ba2ec5ce4c3e283ea
7
+ data.tar.gz: 918d1933d6bc85ff6d3044a4db73a7576b187b5731e00fc2c9789e671466bbe560590410c72a4178280c9c50336195650633a63bdfa28f29332aa382df8a0b33
@@ -64,11 +64,7 @@ module Decidim
64
64
  end
65
65
 
66
66
  def assembly_type
67
- if model.assembly_type == "others"
68
- translated_attribute(model.assembly_type_other)
69
- else
70
- t("assembly_types.#{model.assembly_type}", scope: "decidim.assemblies").to_s
71
- end
67
+ translated_attribute model.assembly_type.title
72
68
  end
73
69
  end
74
70
  end
@@ -0,0 +1,45 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Decidim
4
+ module Assemblies
5
+ module Admin
6
+ # A command with all the business logic when creating a new assembly
7
+ # type in the system.
8
+ class CreateAssembliesType < Rectify::Command
9
+ # Public: Initializes the command.
10
+ #
11
+ # form - A form object with the params.
12
+ def initialize(form)
13
+ @form = form
14
+ end
15
+
16
+ # Executes the command. Broadcasts these events:
17
+ #
18
+ # - :ok when everything is valid.
19
+ # - :invalid if the form wasn't valid and we couldn't proceed.
20
+ #
21
+ # Returns nothing.
22
+ def call
23
+ return broadcast(:invalid) if form.invalid?
24
+
25
+ create_assemblies_type!
26
+
27
+ broadcast(:ok)
28
+ end
29
+
30
+ private
31
+
32
+ attr_reader :form
33
+
34
+ def create_assemblies_type!
35
+ Decidim.traceability.create!(
36
+ AssembliesType,
37
+ form.current_user,
38
+ organization: form.current_organization,
39
+ title: form.title
40
+ )
41
+ end
42
+ end
43
+ end
44
+ end
45
+ end
@@ -67,7 +67,6 @@ module Decidim
67
67
  purpose_of_action: form.purpose_of_action,
68
68
  composition: form.composition,
69
69
  assembly_type: form.assembly_type,
70
- assembly_type_other: form.assembly_type_other,
71
70
  creation_date: form.creation_date,
72
71
  created_by: form.created_by,
73
72
  created_by_other: form.created_by_other,
@@ -104,7 +103,7 @@ module Decidim
104
103
  end
105
104
 
106
105
  def link_participatory_processes(assembly)
107
- assembly.link_participatory_spaces_resources(participatory_processes(assembly), "included_participatory_processes")
106
+ assembly.link_participatory_space_resources(participatory_processes(assembly), "included_participatory_processes")
108
107
  end
109
108
  end
110
109
  end
@@ -0,0 +1,45 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Decidim
4
+ module Assemblies
5
+ module Admin
6
+ # A command with all the business logic when destroying an assembly
7
+ # type in the system.
8
+ class DestroyAssembliesType < Rectify::Command
9
+ # Public: Initializes the command.
10
+ #
11
+ # assemblies_type - the AssemblyMember to destroy
12
+ # current_user - the user performing the action
13
+ def initialize(assemblies_type, current_user)
14
+ @assemblies_type = assemblies_type
15
+ @current_user = current_user
16
+ end
17
+
18
+ # Executes the command. Broadcasts these events:
19
+ #
20
+ # - :ok when everything is valid.
21
+ # - :invalid if the form wasn't valid and we couldn't proceed.
22
+ #
23
+ # Returns nothing.
24
+ def call
25
+ destroy_assembly_type!
26
+ broadcast(:ok)
27
+ end
28
+
29
+ private
30
+
31
+ attr_reader :current_user
32
+
33
+ def destroy_assembly_type!
34
+ Decidim.traceability.perform_action!(
35
+ "delete",
36
+ @assemblies_type,
37
+ current_user
38
+ ) do
39
+ @assemblies_type.destroy!
40
+ end
41
+ end
42
+ end
43
+ end
44
+ end
45
+ end
@@ -0,0 +1,46 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Decidim
4
+ module Assemblies
5
+ module Admin
6
+ # A command with all the business logic when updating a new assembly
7
+ # type in the system.
8
+ class UpdateAssembliesType < Rectify::Command
9
+ # Public: Initializes the command.
10
+ #
11
+ # assemblies_type - A assemblies_type object to update.
12
+ # form - A form object with the params.
13
+ def initialize(assemblies_type, form)
14
+ @assemblies_type = assemblies_type
15
+ @form = form
16
+ end
17
+
18
+ # Executes the command. Broadcasts these events:
19
+ #
20
+ # - :ok when everything is valid.
21
+ # - :invalid if the form wasn't valid and we couldn't proceed.
22
+ #
23
+ # Returns nothing.
24
+ def call
25
+ return broadcast(:invalid) if form.invalid?
26
+
27
+ update_assemblies_type!
28
+
29
+ broadcast(:ok)
30
+ end
31
+
32
+ private
33
+
34
+ attr_reader :form
35
+
36
+ def update_assemblies_type!
37
+ Decidim.traceability.update!(
38
+ @assemblies_type,
39
+ form.current_user,
40
+ title: form.title
41
+ )
42
+ end
43
+ end
44
+ end
45
+ end
46
+ end
@@ -84,7 +84,6 @@ module Decidim
84
84
  purpose_of_action: form.purpose_of_action,
85
85
  composition: form.composition,
86
86
  assembly_type: form.assembly_type,
87
- assembly_type_other: form.assembly_type_other,
88
87
  creation_date: form.creation_date,
89
88
  created_by: form.created_by,
90
89
  created_by_other: form.created_by_other,
@@ -108,7 +107,7 @@ module Decidim
108
107
  end
109
108
 
110
109
  def link_participatory_processes(assembly)
111
- assembly.link_participatory_spaces_resources(participatory_processes(assembly), "included_participatory_processes")
110
+ assembly.link_participatory_space_resources(participatory_processes(assembly), "included_participatory_processes")
112
111
  end
113
112
 
114
113
  # Resets the children counter cache to its correct value using an SQL count query.
@@ -0,0 +1,30 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "active_support/concern"
4
+
5
+ module Decidim
6
+ module Assemblies
7
+ module Admin
8
+ module Filterable
9
+ extend ActiveSupport::Concern
10
+
11
+ included do
12
+ include Decidim::Admin::Filterable
13
+
14
+ private
15
+
16
+ # Unless we are explicitly looking for child assemblies, we filter them out.
17
+ def base_query
18
+ return collection if ransack_params[:parent_id_eq]
19
+
20
+ collection.parent_assemblies
21
+ end
22
+
23
+ def extra_filters
24
+ [:parent_id_eq]
25
+ end
26
+ end
27
+ end
28
+ end
29
+ end
30
+ end
@@ -6,13 +6,13 @@ module Decidim
6
6
  # Controller that allows managing assemblies.
7
7
  #
8
8
  class AssembliesController < Decidim::Assemblies::Admin::ApplicationController
9
- include Decidim::Paginable
10
- helper_method :current_assembly, :parent_assembly, :parent_assemblies, :current_participatory_space, :query
9
+ include Decidim::Assemblies::Admin::Filterable
10
+ helper_method :current_assembly, :parent_assembly, :current_participatory_space
11
11
  layout "decidim/admin/assemblies"
12
12
 
13
13
  def index
14
14
  enforce_permission_to :read, :assembly_list
15
- @assemblies = collection
15
+ @assemblies = filtered_collection
16
16
  end
17
17
 
18
18
  def new
@@ -28,7 +28,7 @@ module Decidim
28
28
  CreateAssembly.call(@form) do
29
29
  on(:ok) do |assembly|
30
30
  flash[:notice] = I18n.t("assemblies.create.success", scope: "decidim.admin")
31
- redirect_to assemblies_path(parent_id: assembly.parent_id)
31
+ redirect_to assemblies_path(q: { parent_id_eq: assembly.parent_id })
32
32
  end
33
33
 
34
34
  on(:invalid) do
@@ -70,35 +70,20 @@ module Decidim
70
70
 
71
71
  private
72
72
 
73
- def organization_assemblies
74
- @organization_assemblies ||= OrganizationAssemblies.new(current_user.organization).query
75
- end
76
-
77
- def query
78
- organization_assemblies
79
- .where(parent_id: params[:parent_id])
80
- .ransack(params[:q])
81
- end
82
-
83
73
  def collection
84
- @collection ||= paginate(query.result)
74
+ @collection ||= OrganizationAssemblies.new(current_user.organization).query
85
75
  end
86
76
 
87
77
  def current_assembly
88
- scope = organization_assemblies
89
- @current_assembly ||= scope.where(slug: params[:slug]).or(
90
- scope.where(id: params[:slug])
78
+ @current_assembly ||= collection.where(slug: params[:slug]).or(
79
+ collection.where(id: params[:slug])
91
80
  ).first
92
81
  end
93
82
 
94
83
  alias current_participatory_space current_assembly
95
84
 
96
85
  def parent_assembly
97
- @parent_assembly ||= organization_assemblies.find_by(id: params[:parent_id])
98
- end
99
-
100
- def parent_assemblies
101
- @parent_assemblies ||= organization_assemblies.where.not(id: current_assembly)
86
+ @parent_assembly ||= collection.find_by(id: ransack_params[:parent_id_eq])
102
87
  end
103
88
 
104
89
  def assembly_params
@@ -0,0 +1,107 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Decidim
4
+ module Assemblies
5
+ module Admin
6
+ # Controller used to manage the available assemblies types for the current
7
+ # organization.
8
+ # As this substitues former i18n simple hash we need to keep these i18n keys for migrations
9
+ # and rollbakcs. So let i18n-tasks know about:
10
+ # i18n-tasks-use t('decidim.assemblies.assembly_types.government')
11
+ # i18n-tasks-use t('decidim.assemblies.assembly_types.commission')
12
+ # i18n-tasks-use t('decidim.assemblies.assembly_types.consultative_advisory')
13
+ # i18n-tasks-use t('decidim.assemblies.assembly_types.executive')
14
+ # i18n-tasks-use t('decidim.assemblies.assembly_types.others')
15
+ # i18n-tasks-use t('decidim.assemblies.assembly_types.participatory')
16
+ # i18n-tasks-use t('decidim.assemblies.assembly_types.working_group')
17
+ # This comment (and the i18n keys) may be removed in future versions
18
+ class AssembliesTypesController < Decidim::Assemblies::Admin::ApplicationController
19
+ helper_method :available_assemblies_types, :current_assembly_type
20
+ layout "decidim/admin/assemblies"
21
+
22
+ # GET /admin/assemblies_types
23
+ def index
24
+ enforce_permission_to :index, :assembly_type
25
+ end
26
+
27
+ # GET /admin/assemblies_types/new
28
+ def new
29
+ enforce_permission_to :create, :assembly_type
30
+ @form = assembly_type_form.instance
31
+ end
32
+
33
+ # POST /admin/assemblies_types
34
+ def create
35
+ enforce_permission_to :create, :assembly_type
36
+ @form = assembly_type_form.from_params(params)
37
+
38
+ CreateAssembliesType.call(@form) do
39
+ on(:ok) do |_assembly_type|
40
+ flash[:notice] = I18n.t("assemblies_types.create.success", scope: "decidim.admin")
41
+ redirect_to assemblies_types_path
42
+ end
43
+
44
+ on(:invalid) do
45
+ flash.now[:alert] = I18n.t("assemblies_types.create.error", scope: "decidim.admin")
46
+ render :new
47
+ end
48
+ end
49
+ end
50
+
51
+ # GET /admin/assemblies_types/:id/edit
52
+ def edit
53
+ enforce_permission_to :edit, :assembly_type, assembly_type: current_assembly_type
54
+ @form = assembly_type_form
55
+ .from_model(current_assembly_type,
56
+ assembly_type: current_assembly_type)
57
+ end
58
+
59
+ # PUT /admin/assemblies_types/:id
60
+ def update
61
+ enforce_permission_to :update, :assembly_type, assembly_type: current_assembly_type
62
+
63
+ @form = assembly_type_form
64
+ .from_params(params, assembly_type: current_assembly_type)
65
+
66
+ UpdateAssembliesType.call(current_assembly_type, @form) do
67
+ on(:ok) do
68
+ flash[:notice] = I18n.t("assemblies_types.update.success", scope: "decidim.admin")
69
+ redirect_to assemblies_types_path
70
+ end
71
+
72
+ on(:invalid) do
73
+ flash.now[:alert] = I18n.t("assemblies_types.update.error", scope: "decidim.admin")
74
+ render :edit
75
+ end
76
+ end
77
+ end
78
+
79
+ # DELETE /admin/assemblies_types/:id
80
+ def destroy
81
+ enforce_permission_to :destroy, :assembly_type, assembly_type: current_assembly_type
82
+
83
+ DestroyAssembliesType.call(current_assembly_type, current_user) do
84
+ on(:ok) do
85
+ flash[:notice] = I18n.t("assemblies_types.destroy.success", scope: "decidim.admin")
86
+ redirect_to assemblies_types_path
87
+ end
88
+ end
89
+ end
90
+
91
+ private
92
+
93
+ def available_assemblies_types
94
+ @available_assemblies_types ||= AssembliesType.where(organization: current_organization)
95
+ end
96
+
97
+ def current_assembly_type
98
+ @current_assembly_type ||= AssembliesType.find(params[:id])
99
+ end
100
+
101
+ def assembly_type_form
102
+ form(Decidim::Assemblies::Admin::AssembliesTypeForm)
103
+ end
104
+ end
105
+ end
106
+ end
107
+ end
@@ -56,7 +56,7 @@ module Decidim
56
56
  {
57
57
  scope_id: nil,
58
58
  area_id: nil,
59
- assembly_type: "all"
59
+ type_id: nil
60
60
  }
61
61
  end
62
62
 
@@ -0,0 +1,17 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Decidim
4
+ module Assemblies
5
+ module Admin
6
+ # A form object used to create assembly type from the admin dashboard.
7
+ class AssembliesTypeForm < Form
8
+ include TranslatableAttributes
9
+
10
+ mimic :assemblies_type
11
+
12
+ translatable_attribute :title, String
13
+ validates :title, translatable_presence: true
14
+ end
15
+ end
16
+ end
17
+ end
@@ -9,12 +9,10 @@ module Decidim
9
9
  class AssemblyForm < Form
10
10
  include TranslatableAttributes
11
11
 
12
- ASSEMBLY_TYPES = %w(government executive consultative_advisory participatory working_group commission others).freeze
13
12
  CREATED_BY = %w(city_council public others).freeze
14
13
 
15
14
  mimic :assembly
16
15
 
17
- translatable_attribute :assembly_type_other, String
18
16
  translatable_attribute :composition, String
19
17
  translatable_attribute :closing_date_reason, String
20
18
  translatable_attribute :created_by_other, String
@@ -32,7 +30,6 @@ module Decidim
32
30
  translatable_attribute :target, String
33
31
  translatable_attribute :title, String
34
32
 
35
- attribute :assembly_type, String
36
33
  attribute :created_by, String
37
34
  attribute :facebook_handler, String
38
35
  attribute :github_handler, String
@@ -42,6 +39,7 @@ module Decidim
42
39
  attribute :twitter_handler, String
43
40
  attribute :youtube_handler, String
44
41
 
42
+ attribute :decidim_assemblies_type_id, Integer
45
43
  attribute :area_id, Integer
46
44
  attribute :parent_id, Integer
47
45
  attribute :participatory_processes_ids, Array[Integer]
@@ -69,8 +67,8 @@ module Decidim
69
67
  validates :slug, presence: true, format: { with: Decidim::Assembly.slug_format }
70
68
 
71
69
  validate :slug_uniqueness
70
+ validate :same_type_organization, if: ->(form) { form.decidim_assemblies_type_id }
72
71
 
73
- validates :assembly_type_other, translatable_presence: true, if: ->(form) { form.assembly_type == "others" }
74
72
  validates :created_by_other, translatable_presence: true, if: ->(form) { form.created_by == "others" }
75
73
  validates :title, :subtitle, :description, :short_description, translatable_presence: true
76
74
 
@@ -94,12 +92,8 @@ module Decidim
94
92
  end
95
93
 
96
94
  def assembly_types_for_select
97
- ASSEMBLY_TYPES.map do |type|
98
- [
99
- I18n.t("assembly_types.#{type}", scope: "decidim.assemblies"),
100
- type
101
- ]
102
- end
95
+ @assembly_types_for_select ||= organization_assembly_types
96
+ &.map { |type| [translated_attribute(type.title), type.id] }
103
97
  end
104
98
 
105
99
  def created_by_for_select
@@ -121,8 +115,16 @@ module Decidim
121
115
  &.sort_by { |arr| arr[0] }
122
116
  end
123
117
 
118
+ def assembly_type
119
+ AssembliesType.find_by(id: decidim_assemblies_type_id)
120
+ end
121
+
124
122
  private
125
123
 
124
+ def organization_assembly_types
125
+ AssembliesType.where(organization: current_organization)
126
+ end
127
+
126
128
  def organization_participatory_processes
127
129
  Decidim.find_participatory_space_manifest(:participatory_processes)
128
130
  .participatory_spaces.call(current_organization)
@@ -140,6 +142,13 @@ module Decidim
140
142
 
141
143
  errors.add(:slug, :taken)
142
144
  end
145
+
146
+ def same_type_organization
147
+ return unless assembly_type
148
+ return if assembly_type.organization == current_organization
149
+
150
+ errors.add(:assembly_type, :invalid)
151
+ end
143
152
  end
144
153
  end
145
154
  end