| 
									
										
										
										
											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. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   Add this module as an extension when establishing your Postgrex connection: | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-07-17 09:14:41 +00:00
										 |  |  |       Postgrex.start_link( | 
					
						
							| 
									
										
										
										
											2015-05-27 17:33:15 +00:00
										 |  |  |         database: "isn_test", | 
					
						
							| 
									
										
										
										
											2016-01-10 11:12:38 +00:00
										 |  |  |         extensions: [{ISN, {}}]) | 
					
						
							| 
									
										
										
										
											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 | 
					
						
							| 
									
										
										
										
											2016-01-10 11:12:38 +00:00
										 |  |  |           field :isbn, ISN.ISBN13 | 
					
						
							| 
									
										
										
										
											2015-05-27 17:33:15 +00:00
										 |  |  |           # other fields | 
					
						
							|  |  |  |         end | 
					
						
							|  |  |  |       end | 
					
						
							|  |  |  |   """
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-01-22 21:19:23 +00:00
										 |  |  |   def init(opts) when opts in [:copy, :reference], do: opts | 
					
						
							| 
									
										
										
										
											2015-05-27 16:15:09 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-10-03 19:45:47 +00:00
										 |  |  |   def matching(_), | 
					
						
							| 
									
										
										
										
											2015-06-02 06:03:17 +00:00
										 |  |  |     do: Enum.zip(Stream.cycle([:type]), @isn) | 
					
						
							| 
									
										
										
										
											2015-05-27 16:15:09 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |   def format(_), | 
					
						
							|  |  |  |     do: :text | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-01-22 21:23:06 +00:00
										 |  |  |   def encode(_opts) do | 
					
						
							| 
									
										
										
										
											2017-01-22 21:19:23 +00:00
										 |  |  |     quote do | 
					
						
							|  |  |  |       thing -> | 
					
						
							|  |  |  |         [<<IO.iodata_length(thing) :: int32>> | thing] | 
					
						
							|  |  |  |     end | 
					
						
							|  |  |  |   end | 
					
						
							| 
									
										
										
										
											2015-05-27 16:15:09 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-01-22 21:19:23 +00:00
										 |  |  |   def decode(:copy) do | 
					
						
							|  |  |  |     quote do | 
					
						
							|  |  |  |       <<len :: int32, thing::binary-size(len)>> -> | 
					
						
							|  |  |  |         :binary.copy(thing) | 
					
						
							|  |  |  |     end | 
					
						
							|  |  |  |   end | 
					
						
							|  |  |  |   def decode(:reference) do | 
					
						
							|  |  |  |     quote do | 
					
						
							|  |  |  |       <<len :: int32, thing::binary-size(len)>> -> | 
					
						
							|  |  |  |         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]) | 
					
						
							| 
									
										
										
										
											2015-10-02 18:24:50 +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 | 
					
						
							|  |  |  |     @behaviour Ecto.Type | 
					
						
							| 
									
										
										
										
											2015-06-02 06:03:17 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-10-02 18:24:50 +00:00
										 |  |  |     @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
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											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 |