| 
									
										
										
										
											2016-01-10 11:12:38 +00:00
										 |  |  | defmodule ISN do | 
					
						
							| 
									
										
										
										
											2015-05-27 16:15:09 +00:00
										 |  |  |   @behaviour Postgrex.Extension | 
					
						
							|  |  |  |   @isn ~w(ean13 isbn13 ismn13 issn13 isbn ismn issn upc) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-05-27 17:33:15 +00:00
										 |  |  |   @moduledoc """
 | 
					
						
							|  |  |  |   A Postgrex.Extension enabling the use of postgresql data types from the isn | 
					
						
							|  |  |  |   extension. | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-04-21 10:17:10 +00:00
										 |  |  |   In lib/ directory create a file with the following content: | 
					
						
							| 
									
										
										
										
											2015-05-27 17:33:15 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-05-10 19:08:50 +00:00
										 |  |  |     Postgrex.Types.define(MyApp.PostgrexTypes, [ISN], []) | 
					
						
							| 
									
										
										
										
											2017-04-21 10:00:31 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |   Add the following lines in conig.exs: | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     config :my_app, MyApp.Repo, | 
					
						
							|  |  |  |       types: MyApp.PostgrexTypes | 
					
						
							| 
									
										
										
										
											2015-05-27 17:33:15 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |   Then you can do Ecto.Migrations like this: | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       defmodule MyApp.Repo.Migrations.CreateBook do | 
					
						
							|  |  |  |         use Ecto.Migration | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         def change do | 
					
						
							|  |  |  |           create table(:books) do | 
					
						
							|  |  |  |             add :isbn, :isbn13 | 
					
						
							|  |  |  |             # other fields | 
					
						
							|  |  |  |           end | 
					
						
							|  |  |  |         end | 
					
						
							|  |  |  |       end | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   You can also define Ecto.Models using the matching custom Ecto.Types: | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       defmodule MyApp.Book do | 
					
						
							|  |  |  |         use MyApp.Web, :model | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         schema "books" do | 
					
						
							| 
									
										
										
										
											2017-04-21 10:00:31 +00:00
										 |  |  |           field :isbn, ISN.ISBN13, read_after_writes: true | 
					
						
							| 
									
										
										
										
											2015-05-27 17:33:15 +00:00
										 |  |  |           # other fields | 
					
						
							|  |  |  |         end | 
					
						
							|  |  |  |       end | 
					
						
							|  |  |  |   """
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-04-21 10:00:31 +00:00
										 |  |  |   def init(opts), do: Keyword.get(opts, :decode_copy, :reference) | 
					
						
							| 
									
										
										
										
											2015-05-27 16:15:09 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-01-26 16:55:15 +00:00
										 |  |  |   def matching(_), do: Enum.zip(Stream.cycle([:type]), @isn) | 
					
						
							| 
									
										
										
										
											2015-05-27 16:15:09 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-01-26 16:55:15 +00:00
										 |  |  |   def format(_), do: :text | 
					
						
							| 
									
										
										
										
											2015-05-27 16:15:09 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-01-22 21:23:06 +00:00
										 |  |  |   def encode(_opts) do | 
					
						
							| 
									
										
										
										
											2017-01-22 21:19:23 +00:00
										 |  |  |     quote do | 
					
						
							|  |  |  |       thing -> | 
					
						
							| 
									
										
										
										
											2023-07-14 12:35:14 +00:00
										 |  |  |         [<<IO.iodata_length(thing)::int32()>> | thing] | 
					
						
							| 
									
										
										
										
											2017-01-22 21:19:23 +00:00
										 |  |  |     end | 
					
						
							|  |  |  |   end | 
					
						
							| 
									
										
										
										
											2015-05-27 16:15:09 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-01-22 21:19:23 +00:00
										 |  |  |   def decode(:copy) do | 
					
						
							|  |  |  |     quote do | 
					
						
							| 
									
										
										
										
											2023-07-14 12:35:14 +00:00
										 |  |  |       <<len::int32(), thing::binary-size(len)>> -> | 
					
						
							| 
									
										
										
										
											2017-01-22 21:19:23 +00:00
										 |  |  |         :binary.copy(thing) | 
					
						
							|  |  |  |     end | 
					
						
							|  |  |  |   end | 
					
						
							| 
									
										
										
										
											2018-01-26 16:55:15 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-01-22 21:19:23 +00:00
										 |  |  |   def decode(:reference) do | 
					
						
							|  |  |  |     quote do | 
					
						
							| 
									
										
										
										
											2023-07-14 12:35:14 +00:00
										 |  |  |       <<len::int32(), thing::binary-size(len)>> -> | 
					
						
							| 
									
										
										
										
											2017-01-22 21:19:23 +00:00
										 |  |  |         thing | 
					
						
							|  |  |  |     end | 
					
						
							|  |  |  |   end | 
					
						
							| 
									
										
										
										
											2015-05-27 16:15:09 +00:00
										 |  |  | end | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-10-02 18:45:53 +00:00
										 |  |  | # Generate Ecto.Type modules for all supported data types in the `isn` | 
					
						
							|  |  |  | # postgresql module. | 
					
						
							| 
									
										
										
										
											2015-10-02 18:24:50 +00:00
										 |  |  | for module <- ~w(ISBN ISMN ISSN ISBN13 ISMN13 ISSN13 UPC EAN13) do | 
					
						
							| 
									
										
										
										
											2016-01-10 11:12:38 +00:00
										 |  |  |   module_name = Module.concat([ISN, module]) | 
					
						
							| 
									
										
										
										
											2018-01-26 16:55:15 +00:00
										 |  |  |   ecto_type = module |> String.downcase() |> String.to_atom() | 
					
						
							| 
									
										
										
										
											2015-10-02 18:45:53 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-10-02 18:24:50 +00:00
										 |  |  |   defmodule module_name do | 
					
						
							|  |  |  |     @moduledoc """
 | 
					
						
							| 
									
										
										
										
											2016-01-10 11:12:38 +00:00
										 |  |  |     Definition for the ISN.#{module} module. | 
					
						
							| 
									
										
										
										
											2015-05-27 17:33:15 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-10-02 18:24:50 +00:00
										 |  |  |     How to use this in an Ecto.Model | 
					
						
							| 
									
										
										
										
											2015-05-27 17:33:15 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-10-02 18:43:59 +00:00
										 |  |  |         defmodule MyApp.Book do | 
					
						
							|  |  |  |           use MyApp.Web, :model | 
					
						
							| 
									
										
										
										
											2015-05-27 17:33:15 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-10-02 18:43:59 +00:00
										 |  |  |           schema "books" do | 
					
						
							| 
									
										
										
										
											2016-01-10 11:12:38 +00:00
										 |  |  |             field :#{ecto_type}, ISN.#{module} | 
					
						
							| 
									
										
										
										
											2015-10-02 18:43:59 +00:00
										 |  |  |             # other fields | 
					
						
							|  |  |  |           end | 
					
						
							|  |  |  |         end | 
					
						
							| 
									
										
										
										
											2015-10-02 18:24:50 +00:00
										 |  |  |     """
 | 
					
						
							| 
									
										
										
										
											2015-05-27 16:15:09 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-05-10 18:34:13 +00:00
										 |  |  |     use Ecto.Type | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-10-02 18:24:50 +00:00
										 |  |  |     def type, do: unquote(ecto_type) | 
					
						
							| 
									
										
										
										
											2015-05-27 16:15:09 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-10-02 18:24:50 +00:00
										 |  |  |     def cast(nil), do: :error | 
					
						
							|  |  |  |     def cast(isn), do: {:ok, to_string(isn)} | 
					
						
							| 
									
										
										
										
											2015-05-27 16:15:09 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-10-02 18:24:50 +00:00
										 |  |  |     def load(isn), do: {:ok, to_string(isn)} | 
					
						
							| 
									
										
										
										
											2015-05-27 16:15:09 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-10-02 18:24:50 +00:00
										 |  |  |     def dump(isn), do: {:ok, to_string(isn)} | 
					
						
							| 
									
										
										
										
											2015-05-27 16:15:09 +00:00
										 |  |  |   end | 
					
						
							|  |  |  | end |