|
1 | 1 | module Flex |
2 | 2 | module Attributes |
3 | 3 | extend ActiveSupport::Concern |
4 | | - |
5 | | - # A custom ActiveRecord type that allows storing a date. It behaviors the same |
6 | | - # as the default Date type, but it allows setting the attribute using a hash |
7 | | - # with keys :year, :month, and :day. This is meant to be used in conjunction |
8 | | - # with the memorable_date method in the Flex form builder |
9 | | - class MemorableDate < ActiveRecord::Type::Date |
10 | | - # Override cast to allow setting the date via a Hash with keys :year, :month, :day. |
11 | | - def cast(value) |
12 | | - return super(value) unless value.is_a?(Hash) |
13 | | - |
14 | | - begin |
15 | | - # Use strptime since Date.new is too lenient, allowing things like negative months and years |
16 | | - value = Date.strptime("#{value[:year]}-#{value[:month]}-#{value[:day]}", "%Y-%m-%d") |
17 | | - rescue ArgumentError |
18 | | - nil |
19 | | - end |
20 | | - end |
21 | | - |
22 | | - def type |
23 | | - :date_from_hash |
24 | | - end |
25 | | - end |
| 4 | + include Flex::Attributes::MemorableDateAttribute |
26 | 5 |
|
27 | 6 | class_methods do |
28 | 7 | def flex_attribute(name, type, options = {}) |
29 | | - if type == :memorable_date |
| 8 | + case type |
| 9 | + when :memorable_date |
30 | 10 | memorable_date_attribute name, options |
31 | 11 | else |
32 | 12 | raise ArgumentError, "Unsupported attribute type: #{type}" |
33 | 13 | end |
34 | 14 | end |
35 | | - |
36 | | - private |
37 | | - |
38 | | - def memorable_date_attribute(name, options) |
39 | | - attribute name, MemorableDate.new |
40 | | - |
41 | | - validate :"validate_#{name}" |
42 | | - |
43 | | - if options[:presence] |
44 | | - validates name, presence: true |
45 | | - end |
46 | | - |
47 | | - # Create a validation method that checks if the value is a valid date |
48 | | - define_method "validate_#{name}" do |
49 | | - value = send(name) |
50 | | - raw_value = read_attribute_before_type_cast(name) |
51 | | - |
52 | | - # If model.<attribute> is nil, but model.<attribute>_before_type_cast is not nil, |
53 | | - # that means the application failed to cast the value to the appropriate type in |
54 | | - # order to complete the attribute assignment. This means the original value |
55 | | - # is invalid. |
56 | | - did_type_cast_fail = value.nil? && raw_value.present? |
57 | | - if did_type_cast_fail |
58 | | - errors.add(name, :invalid_date) |
59 | | - end |
60 | | - end |
61 | | - end |
62 | 15 | end |
63 | 16 | end |
64 | 17 | end |
0 commit comments