Two fixes in record/1 (#5412)

* Document use of `record/1` with atom argument.

* In `record/1` used with record argument, raise ArgumentError on record size mismatch.
This commit is contained in:
Waldemar Rachwał
2016-11-08 15:27:46 +01:00
committed by José Valim
parent 539b59fe2b
commit e3d2dacff0
2 changed files with 30 additions and 2 deletions
+16 -2
View File
@@ -174,7 +174,8 @@ defmodule Record do
The following macros are generated:
* `name/0` to create a new record with default values for all fields
* `name/1` to create a new record with the given fields and values or to
* `name/1` to create a new record with the given fields and values,
to get the zero-based index of the given field in a record or to
convert the given record to a keyword list
* `name/2` to update an existing record with the given fields and values
or to access a given field in a given record
@@ -206,6 +207,10 @@ defmodule Record do
# To update the record
user(record, age: 26) #=> {:user, "meg", 26}
# To get the zero-based index of the field in record tuple
# (index 0 is occupied by the record "tag")
user(:name) #=> 1
# Convert a record to a keyword list
user(record) #=> [name: "meg", age: 26]
@@ -413,17 +418,26 @@ defmodule Record do
def __keyword__(atom, fields, record) do
if is_record(record, atom) do
[_tag | values] = Tuple.to_list(record)
join_keyword(fields, values, [])
case join_keyword(fields, values, []) do
kv when is_list(kv) ->
kv
expected_fields ->
msg = "expected argument to be a #{inspect atom} record with #{expected_fields} fields, got: #{inspect record}"
raise ArgumentError, msg
end
else
msg = "expected argument to be a literal atom, literal keyword or a #{inspect atom} record, got runtime: #{inspect record}"
raise ArgumentError, msg
end
end
# Returns a keyword list, or expected number of fields on size mismatch
defp join_keyword([{field, _default} | fields], [value | values], acc),
do: join_keyword(fields, values, [{field, value} | acc])
defp join_keyword([], [], acc),
do: :lists.reverse(acc)
defp join_keyword(rest_fields, _rest_values, acc),
do: length(acc) + length(rest_fields) # expected fields
defp apply_underscore(fields, keyword) do
case Keyword.fetch(keyword, :_) do
+14
View File
@@ -176,6 +176,20 @@ defmodule RecordTest do
assert_raise ArgumentError, msg, fn ->
file_info(record)
end
pretender = {RecordTest, "john"}
msg = "expected argument to be a RecordTest record with 2 fields, " <>
"got: {RecordTest, \"john\"}"
assert_raise ArgumentError, msg, fn ->
user(pretender)
end
pretender = {RecordTest, "john", 25, []}
msg = "expected argument to be a RecordTest record with 2 fields, " <>
"got: {RecordTest, \"john\", 25, []}"
assert_raise ArgumentError, msg, fn ->
user(pretender)
end
end
test "records visibility" do