OSDN Git Service

d5b45afe72a353fa94a90781075e5c09fade3de6
[elecoma/elecoma.git] / app / models / search_form.rb
1 # 検索条件を格納する
2 # 例: @search = SearchForm.new(params[:search])
3
4 class SearchForm < ActiveForm
5   VALID_NAME = /^[a-zA-Z_][a-zA-Z0-9_]*$/
6   include ActiveRecord::Validations
7   def validate
8     super
9     # from <= to etc...
10     attributes.each do | name, value |
11       value.blank? and next
12       if (m = name.match(/_from$/))
13         prefix = m.pre_match
14         name_to = prefix+'_to'
15         from = value
16         to = send(name_to)
17         next if to.blank?
18         # 数字だけの場合数値として比較
19         unless [from, to].any?{|v| v =~ /\D/} # 数字以外が含まれていない
20           from = from.strftime("%Y%m%d%H%M%S").to_i
21           to = to.strftime("%Y%m%d%H%M%S").to_i
22         end
23         unless from <= to
24           errors.add name, 'の範囲指定が不正です。'
25           errors.add name_to, 'の範囲指定が不正です。'
26         end
27       end
28     end
29   end
30
31   # ActiveForm からコピペして改造
32   def attributes
33     attributes = instance_variables
34     attributes.delete("@errors")
35     attributes.inject({}) do |hash, attribute|
36       hash[attribute[1..-1]] = instance_variable_get(attribute)
37       hash
38     end
39   end
40
41   def attributes=(hash)
42     hash.each do | key, value |
43       next if value.nil? || value == ''
44       # datetime
45       name = key.to_s
46       if (m = name.match(/\((\d)i\)$/))
47         next if m[1] != '1'
48         name = m.pre_match
49         if (date = parse_date_select(hash, name))
50           send(name+'=', date)
51         end
52       elsif value.is_a?(String) &&
53           value =~ /^\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}/
54         # 日時に見える文字列は Date に
55         send(name+'=', Time.zone.parse(value))
56       else
57         send(name+'=', value)
58       end
59     end if hash
60   end
61
62   def method_missing(key, *args)
63     begin
64       super
65     rescue NoMethodError
66       name = key.to_s
67       if name.size >= 2 && name[-1] == ?= # name =~ /^.+=$/
68         # set
69         name = name[0, name.size-1]
70         value = args.first
71         instance_variable_set('@'+name, value) if name =~ VALID_NAME
72       else
73         # get
74         instance_variable_get('@'+name) if name =~ VALID_NAME
75       end
76     end
77   end
78
79   private
80
81   def parse_date_select(params, name)
82     arr = (1..6).map do |i|
83       params["%s(%di)" % [name, i]]
84     end
85     if arr.join.blank?
86       return
87     end
88     year,month,day,hour,min,sec = arr
89
90     selected_date = false
91     selected_time = false
92
93     if year || month || day
94       selected_date = true
95     end
96
97     if hour || min || sec
98       selected_time = true
99     end
100
101     now = DateTime.now
102     if selected_date
103       if year.blank?
104         year = now.year.to_s
105       end
106       if month.blank?
107         if ! day.blank?
108           month = now.month.to_s
109         elsif year
110           month = "1"
111         else
112           month = now.month.to_s
113         end
114       end
115       if day.blank?
116         if year || month
117           day = "1"
118         else
119           day = now.day.to_s
120         end
121       end
122     end
123
124     if selected_time
125       if hour.blank?
126         hour = "00"
127       end
128       if min.blank?
129         if hour
130           min = "00"
131         else
132           min = now.min.to_s
133         end
134       end
135       if sec.blank?
136         if hour || min
137           sec = "00"
138         else
139           sec = now.sec.to_s
140         end
141       end
142     end
143     if selected_time
144       Time.zone.local(year.to_i,month.to_i,day.to_i,hour.to_i,min.to_i,sec.to_i)
145     else
146       Time.zone.local(year.to_i,month.to_i,day.to_i)
147     end
148   end
149
150   ## from ActiveHeart
151
152   class << self
153     def set_field_names(field_names = {})
154       @field_names = HashWithIndifferentAccess.new unless @field_names
155       @field_names.update(field_names)
156     end
157
158     alias_method :_human_attribute_name, :human_attribute_name
159     def human_attribute_name(attribute_key_name)
160       if @field_names && @field_names[attribute_key_name]
161         @field_names[attribute_key_name]
162       else
163         _human_attribute_name(attribute_key_name)
164       end
165     end
166
167     def field_names
168       @field_names
169     end
170
171     def self_and_descendants_from_active_record
172       [self]
173     end
174
175     def human_name(*args)
176       name.humanize
177     end
178   end
179
180 end