christian
christian

Reputation: 64

Error after migration from ERB to HAML

I used http://htmltohaml.com/ this to convert my ERB and there is some kind of problem.

The working ERB before the convert

<h3><%= t("admin.labels.employee") %> <%= content_tag(:span, employee_counter) %></h3>
<%
   def create_validation_rules(field_rules)
     Hash[field_rules.map do |rule|
            next ["rule-#{rule[:name]}", rule[:value]] if rule[:value]
            next ["msg-#{rule[:name]}", rule[:msg]] if rule[:msg]
          end] if field_rules
   end
%>
<div class="control-group form-controls">
    <%= f.label :first_name, t("labels.name") %>
    <%= f.text_field :first_name, placeholder: t("labels.first_name"), class: 'js-employeeName', id: "merchant_employees_attributes_#{index}_first_name", name: "merchant[employees_attributes][#{index}][first_name]", autocomplete: "off", maxlength: 50, size: nil, data: create_validation_rules(validations[:first_name]) %>
    <%= f.text_field :middle_name, placeholder: t("labels.middle_name"), id: "merchant_employees_attributes_#{index}_middle_name", name: "merchant[employees_attributes][#{index}][middle_name]", autocomplete: "off", maxlength: 100, size: nil %>
    <%= f.text_field :last_name, placeholder: t("labels.last_name"), class: 'js-employeeName', id: "merchant_employees_attributes_#{index}_last_name", name: "merchant[employees_attributes][#{index}][last_name]", autocomplete: "off", maxlength: 50, size: nil, data: create_validation_rules(validations[:last_name]) %>
</div>
<div class="control-group">
  <%= f.label :email, t("labels.email_address") %>
  <%= f.text_field :email, id: "merchant_employees_attributes_#{index}_email", name: "merchant[employees_attributes][#{index}][email]", autocomplete: "off", maxlength: 250, size: nil, data: create_validation_rules(validations[:email]) %>
</div>
<div class="control-group">
  <% if force_superuser_role %>
      <%= f.hidden_field :superuser, value: "1" %>
  <% else %>
      <%= f.label :superuser, t("admin.labels.superuser") %>
      <%= f.check_box :superuser, class: "superuser_checkbox", id: "merchant_employees_attributes_#{index}_superuser", name: "merchant[employees_attributes][#{index}][superuser]"%>
  <% end %>
</div>

Not working HAML after the convert:

This is my error: Showing /Users/project/app/views/shared/_employee.html.haml where line #9 raised:

%h3
  = t("admin.labels.employee")
  = content_tag(:span, employee_counter)
- def create_validation_rules(field_rules)
- Hash[field_rules.map do |rule|
- next ["rule-#{rule[:name]}", rule[:value]] if rule[:value]
- next ["msg-#{rule[:name]}", rule[:msg]] if rule[:msg]
- end] if field_rules
- end
.control-group.form-controls
  = f.label :first_name, t("labels.name")
  = f.text_field :first_name, placeholder: t("labels.first_name"), class: 'js-employeeName', id: "merchant_employees_attributes_#{index}_first_name", name: "merchant[employees_attributes][#{index}][first_name]", autocomplete: "off", maxlength: 50, size: nil, data: create_validation_rules(validations[:first_name])
  = f.text_field :middle_name, placeholder: t("labels.middle_name"), id: "merchant_employees_attributes_#{index}_middle_name", name: "merchant[employees_attributes][#{index}][middle_name]", autocomplete: "off", maxlength: 100, size: nil
  = f.text_field :last_name, placeholder: t("labels.last_name"), class: 'js-employeeName', id: "merchant_employees_attributes_#{index}_last_name", name: "merchant[employees_attributes][#{index}][last_name]", autocomplete: "off", maxlength: 50, size: nil, data: create_validation_rules(validations[:last_name])
.control-group
  = f.label :email, t("labels.email_address")
  = f.text_field :email, id: "merchant_employees_attributes_#{index}_email", name: "merchant[employees_attributes][#{index}][email]", autocomplete: "off", maxlength: 250, size: nil, data: create_validation_rules(validations[:email])
.control-group
  - if force_superuser_role
    = f.hidden_field :superuser, value: "1"
  - else
    = f.label :superuser, t("admin.labels.superuser")
    = f.check_box :superuser, class: "superuser_checkbox", id: "merchant_employees_attributes_#{index}_superuser", name: "merchant[employees_attributes][#{index}][superuser]"

Upvotes: 1

Views: 90

Answers (2)

Michael Gaskill
Michael Gaskill

Reputation: 8042

The correct way to handle this is to define the method as a helper in your controller:

class MyController
  helper_method :create_validation_rules

private
  def create_validation_rules(field_rules)
    Hash[field_rules.map do |rule|
      next ["rule-#{rule[:name]}", rule[:value]] if rule[:value]
      next ["msg-#{rule[:name]}", rule[:msg]] if rule[:msg]
    end] if field_rules
  end
end

This will allow you to call create_validation_rules from within the view, without having to define the method there. See In Rails, what exactly do helper and helper_method do? to understand exactly what a helper method is and how it works.


However, if you simply must use an embedded method in the View code, there is a solution: you can simply eliminate the last end in the inline function, and properly indent the body of the function and the loop.

In this case, the error message would have explained everything:

You don't need to use "- end" in Haml. Un-indent to close a block

Updating your HAML code, this works:

%h3
  = t("admin.labels.employee")
  = content_tag(:span, employee_counter)
- def create_validation_rules(field_rules)
  - Hash[field_rules.map do |rule|
    - next ["rule-#{rule[:name]}", rule[:value]] if rule[:value]
    - next ["msg-#{rule[:name]}", rule[:msg]] if rule[:msg]
  - end] if field_rules
.control-group.form-controls
  = f.label :first_name, t("labels.name")
  = f.text_field :first_name, placeholder: t("labels.first_name"), class: 'js-employeeName', id: "merchant_employees_attributes_#{index}_first_name", name: "merchant[employees_attributes][#{index}][first_name]", autocomplete: "off", maxlength: 50, size: nil, data: create_validation_rules(validations[:first_name])
  = f.text_field :middle_name, placeholder: t("labels.middle_name"), id: "merchant_employees_attributes_#{index}_middle_name", name: "merchant[employees_attributes][#{index}][middle_name]", autocomplete: "off", maxlength: 100, size: nil
  = f.text_field :last_name, placeholder: t("labels.last_name"), class: 'js-employeeName', id: "merchant_employees_attributes_#{index}_last_name", name: "merchant[employees_attributes][#{index}][last_name]", autocomplete: "off", maxlength: 50, size: nil, data: create_validation_rules(validations[:last_name])
.control-group
  = f.label :email, t("labels.email_address")
  = f.text_field :email, id: "merchant_employees_attributes_#{index}_email", name: "merchant[employees_attributes][#{index}][email]", autocomplete: "off", maxlength: 250, size: nil, data: create_validation_rules(validations[:email])
.control-group
  - if force_superuser_role
    = f.hidden_field :superuser, value: "1"
  - else
    = f.label :superuser, t("admin.labels.superuser")
    = f.check_box :superuser, class: "superuser_checkbox", id: "merchant_employees_attributes_#{index}_superuser", name: "merchant[employees_attributes][#{index}][superuser]"

As a function definition embedded in ERB view code is abnormal, http://htmltohaml.com didn't handle it well, and simply regurgitated the entire method into the HAML output. While this is clearly incorrect, it's a simple matter to correct.


If you're being a good net citizen (and as you're already using the tool), you'll report this issue to the developer of http://htmltohaml.com so that he can account for this class of HAML generation issue.

Upvotes: 2

Vasfed
Vasfed

Reputation: 18504

Best option is to move create_validation_rules into a helper or at least make it a helper_method in controller.

To keep it in haml - you have to use haml syntax for blocks:

- def create_validation_rules(field_rules)
  - if field_rules
    - Hash.[] field_rules.map do |rule|
      - if rule[:value]
        - next ["rule-#{rule[:name]}", rule[:value]]
      - if rule[:msg]
        - next ["msg-#{rule[:name]}", rule[:msg]]

Upvotes: 1

Related Questions