根据列/值列表为结构赋值

时间:2015-12-06 05:34:06

标签: elixir

我想按顺序获取包含列和值的列表,并将其转换为struct。我目前在值上进行模式匹配,但随着列表的不断增长,我的代码变得越来越大。这是一些代码。

@find_account_query ~s{
  SELECT
    username, -- 1
    name, -- 2
    surname, -- 3
    account.active, -- 4
    CASE WHEN person_id IS NOT NULL
      THEN TRUE
    ELSE FALSE END AS isPerson -- 5
  FROM account
    LEFT JOIN person ON person.id = account.person_id
  WHERE username = $1
}


def get(username), do:
  conn 
  |> Connection.query(@find_account_query, [username])
  |> parse_acct

defp parse_acct({:ok, %{ :num_rows => 0 }}), do: nil
defp parse_acct({:ok, %{ :columns => columns, :rows => [account]}}), do: 
  account |> parse_acct

##### The following function clause will get really long
defp parse_acct([username, name, surname, active, is_person]), do:
  %Topaz.Account{
    username: username,
    name: name,
    surname: surname,
    active: active,
    is_person: is_person
  }

defp parse_acct(_), do: nil

如何简化从Liststruct的过程?

2 个答案:

答案 0 :(得分:0)

假设列列表和值列表对齐,您可以递归遍历列列表,并根据索引为结构赋值。

def get(username), do:
  conn
  |> Connection.query(@find_account_query, [username])
  |> getp

defp parse_acct({:ok, %{ :num_rows => 0 }}), do: nil
defp parse_acct({:ok, %{ :columns => columns,  :rows => [values]}}), do:
  parse_acct(columns, values, %Topaz.Account{}, 0)

defp parse_acct([head|tail], values, account, index) do
  # Get the corresponding atom in the model
  atom = head |> String.to_atom
  # Add the value to the account
  account = account |> Map.put(atom, values |> Enum.at(index))
  # Continue iterating
  parse_acct(tail, values, account, index + 1)
end

# When iteration is done, return account
defp parse_acct([], values, account, index), do: account

答案 1 :(得分:0)

您可以使用结构只是一个带有defp parse_acct(values), do: keys = [:username, :name, :surname, :active, :is_person] keys |> Enum.zip(values) |> Enum.into(%{}) |> Map.merge(%Topaz.Account{}) end 键的地图来构建地图,然后添加相应的%Topaz.Account{} |> Map.keys |> Enum.filter(&(&1 != :__struct__)) 键。像这样:

 <script type="text/javascript">

            $(document).ready(function () {
                $.validator.setDefaults({
                    submitHandler: function (form) {
                        $.ajax({
                            type: "POST",
                            url: "contact_form.php",

                            data: $("#contactform").serialize()
                        }).done(function (data) {
                                alert(data);
                            swal("Mail Send!", "We will back to you soon", 'success');
                            $('#contactform').trigger("reset");

                        });
                    }
                });
 $("#contactform").validate({
                    rules:
                            {
                                name: {required: true, minlength: 3, maxlength: 50},
                                email: {required: true, email: true},
                                suburb: {required: true, minlength: 4},
                                phonenumber: {required: true, number: true, minlength: 4},
                                message: {required: false, maxlength: 300}
                            },
                    errorClass: "error",
                    highlight: function (label) {
                        $(label).closest('.form-group').removeClass('has-success').addClass('has-error');
                    },
                    success: function (label) {
                        label
                                // .text('Seems Perfect!').addClass('valid')
                                .closest('.form-group').addClass('has-success');

                    }
                }

                );

            });



        </script>

你可以进一步使用类似这样的东西从结构中提取键列表

<?php
  print_r($_POST);

但是,这需要您的值始终按照Map枚举键的顺序传递(可能按字母顺序排列)

相关问题