1

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]"
christian
  • 64
  • 1
  • 10
  • 2
    Why are you defining a method inside the view??? You're asking for big trouble here. – Tom Lord May 31 '16 at 14:02
  • 1
    I might suggest defining that function elsewhere, like in a helper or computing that value in the controller. HAML, and ERB aren't really well suited for that purpose. – Chase May 31 '16 at 14:03
  • @ChaseGilliam Indeed, HAML makes it hard to define a function in a view _because_ functions shouldn't be defined in views. – Wayne Conrad May 31 '16 at 15:58

2 Answers2

2

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.

Community
  • 1
  • 1
Michael Gaskill
  • 7,913
  • 10
  • 38
  • 43
  • I will be able to give you 5 more later today, when my votes are replenished. :D – Michael Gaskill May 31 '16 at 15:58
  • can you help me with a similar one i will edit my current question because i can't post a new one 2 days – christian Jun 01 '16 at 14:18
  • @christian The error is because the `end` is not needed for the `content_tag` blocks. If you simply remove the `end` lines at lines 13, 17, 21, etc, this should work. When you can post a new question, post this then, and rollback this answer to the original, so that this question and answers are not conflicting. – Michael Gaskill Jun 01 '16 at 18:14
1

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]]
Vasfed
  • 18,013
  • 10
  • 47
  • 53