Guest User

Untitled

a guest
Mar 12th, 2018
122
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 21.04 KB | None | 0 0
  1. class Classified < ActiveRecord::Base
  2. DataFieldsFilePath = "test/fixtures/staticdata/type_of_goods_datafields.yml"
  3.  
  4. acts_as_mappable
  5.  
  6. acts_as_simply_searchable :fields_mapping => {
  7. "administrative_area_code" => "address.administrative_area_code",
  8. "area" => "address.area",
  9. "area_size_from" => "area_size_from",
  10. "area_size_to" => "area_size_to",
  11. "bedrooms" => "number_of_bedrooms",
  12. "bedrooms_from" => "number_of_bedrooms_from",
  13. "city" => "address.city",
  14. "description" => "description",
  15. "is_published" => "is_published",
  16. "is_sold" => "is_sold",
  17. "office_id" => "office_id",
  18. "postal_code" => "address.postal_code",
  19. "postal_code_in" => "address.postal_code_in",
  20. "price_from" => "price_from",
  21. "price_to" => "price_to",
  22. "ref" => "ref",
  23. "rooms" => "number_of_rooms",
  24. "rooms_from" => "number_of_rooms_from",
  25. "sort_by" => "sort_by",
  26. "sort_order" => "sort_order",
  27. "tags" => "tags.name",
  28. "title" => "title",
  29. "type" => "type",
  30. "transaction" => "type_of_transaction",
  31. "user_id" => "user_id"
  32. },
  33. :find_method => 'paginate',
  34. :pagination_options => {:per_page => 10}
  35.  
  36. #internationalization
  37. self.keep_translations_in_model = true
  38. translates :title, :description, :base_as_default => true, :multiple_base_language => true
  39.  
  40. #relationships
  41. belongs_to :user
  42. belongs_to :office
  43. belongs_to :program
  44. #belongs_to :type, :class_name => "TypeOfGood", :foreign_key => "name"
  45. #belongs_to :type_of_transaction, :class_name => "TypeOfTransaction", :foreign_key => "name"
  46. has_one :address, :as => :addressable, :dependent => :destroy
  47. has_many :attachments, :as => :assetable, :order => "position ASC"
  48. has_many :leads, :as => :leadable
  49. has_and_belongs_to_many :tags, :after_add => :increment_counter_cache, :after_remove => :decrement_counter_cache
  50. has_and_belongs_to_many :email_notifications
  51. before_create :generate_password
  52.  
  53. #hooks
  54. def before_validation
  55. super
  56. if program
  57. self.availability_date = self.program.delivery_date
  58. self.address = self.program.address.clone
  59. self.office_id = self.program.office_id
  60. self.address.save!
  61. end
  62. end
  63.  
  64.  
  65. def after_destroy
  66. if program
  67. if program.classifieds.size == 0 and program.is_published == true
  68. program.is_published = false
  69. program.save!
  70. end
  71. end
  72. end
  73.  
  74. after_save :update_tags
  75.  
  76. #global validation
  77. validates_presence_of :type_of_transaction
  78.  
  79. validates_presence_of :user
  80. validates_associated :user
  81. validates_presence_of :office
  82. validates_associated :office
  83.  
  84. #specific validation
  85. validates_presence_of :address
  86. validates_associated :address
  87.  
  88. validates_presence_of :program, :if => Proc.new { |classified| classified.type_of_transaction == 'newly built' }
  89. validates_associated :program, :if => Proc.new { |classified| classified.type_of_transaction == 'newly built' }
  90.  
  91. #behaviour
  92. strip_tags_attribute :title
  93. white_list_attribute :description
  94. define_price_display_attribute :price
  95. define_price_display_attribute :expenses
  96. define_price_display_attribute :fees
  97.  
  98. def to_param
  99. "#{id}-#{PermalinkFu.escape(title)}"
  100. end
  101.  
  102. def type_of_good
  103. self.class.to_s
  104. end
  105.  
  106. def viewable_by?(viewer)
  107. viewer.organization.classifieds.include?(self)
  108. end
  109.  
  110. def destroyable_by?(deleter)
  111. (deleter.organization.classifieds.include?(self) && deleter.has_role?("OrganizationAdministratorRole")) ||
  112. (deleter.has_role?("ClassifiedManagerRole") && deleter.classifieds.include?(self))
  113. end
  114.  
  115. def updatable_by?(updater)
  116. (updater.organization.classifieds.include?(self) && updater.has_role?("OrganizationAdministratorRole")) ||
  117. (updater.has_role?("ClassifiedManagerRole") && updater.classifieds.include?(self))
  118. end
  119.  
  120. def localization
  121. if address
  122. "#{address.city} (#{address.postal_code})"
  123. end
  124. end
  125.  
  126. protected
  127.  
  128. def generate_password
  129. self.password = Digest::SHA1.hexdigest("--#{Time.now.to_s}--")
  130. end
  131.  
  132. def validate
  133. raise "Classified cannot be call directly, use TypeOfGoods classes instead" if self.class.name == 'Classified'
  134. type_of_good = TypeOfGood.find_by_name(self.class.name)
  135. raise "class: #{self.class.name} does not inherit of Classified" if type_of_good == nil
  136. errors.add("type_of_transaction", "'#{type_of_transaction}' is not valid") unless type_of_good.type_of_transactions.map{|t| t.name}.include?(type_of_transaction)
  137. end
  138. # return array of keep_translations_in_model db fields for a specific field_name
  139. def self.keep_translations_in_model_attribute_names(field_name)
  140. attribute_names = []
  141. attribute_names = self.column_names.delete_if{|column_name| Language.pick(column_name.match(field_name+"_([a-z][a-z])")[1])==nil rescue true } if self.globalize_facets.include?(field_name.to_sym)
  142. end
  143. # construct dynamic validation methods from type_of_good fixtures.yml
  144. def self.validate_classified()
  145. type_of_good = TypeOfGood.find_by_name( self.name)
  146. type_of_good.datafields.each{ |field_name,validators|
  147. validators.each { |validator_name,validator_args|
  148. next if (validator_name =~ /^validates_/)!=0
  149.  
  150. attr_names = validator_args==nil ? nil : eval(validator_args)
  151.  
  152. #default_values hack
  153.  
  154. if (validators["default_values"]!=nil and validator_name=="validates_inclusion_of" and (attr_names ==nil or attr_names[:in]==nil))
  155. default_values_key = "default_values"
  156. default_values = eval(validators[default_values_key])
  157. type_of_good.type_of_transactions.each{|t|
  158. # type_of_transaction-dependent default values hack
  159. default_values.concat(eval(validators[default_values_key+"_"+t.name])) if validators[default_values_key+"_"+t.name]
  160. }
  161. in_hash={:in => default_values.map{|x| x[1]}}
  162. attr_names = attr_names ==nil ? in_hash : attr_names.merge(in_hash)
  163. end
  164. #type_of_transaction hack
  165. if validators["exclude_for_type_of_transactions"]!=nil
  166. in_hash={:if => Proc.new { |classified| validators["exclude_for_type_of_transactions"].include?(classified.type_of_transaction) ==false }}
  167. attr_names = attr_names ==nil ? in_hash : attr_names.merge(in_hash)
  168. end
  169. if self.globalize_facets.include?(field_name.to_sym)
  170. #for translated attributes (globalize keep_translations_in_model)
  171. self.keep_translations_in_model_attribute_names(field_name).each{|internationalize_field_name|
  172. language = internationalize_field_name.slice(field_name.length+1,internationalize_field_name.length)
  173. internationalize_attr_names = attr_names
  174.  
  175. begin
  176. Locale.base_language
  177. rescue Globalize::NoBaseLanguageError
  178. #for doc:diagrams
  179. Locale.set_base_language("fr-FR")
  180. Locale.set('fr-FR')
  181. end
  182. if (language != Locale.base_language.code)
  183. #other language than base_language are not mandatory
  184. if (validator_name == 'validates_presence_of')
  185. next #skip presence_of (cannot set it to :allow_ni)
  186. else
  187. in_hash={:allow_nil => true}
  188. internationalize_attr_names = internationalize_attr_names ==nil ? in_hash : internationalize_attr_names.merge(in_hash)
  189. end
  190. end
  191.  
  192. if internationalize_attr_names==nil
  193. send(validator_name.to_sym,internationalize_field_name.to_sym)
  194. else
  195. send(validator_name.to_sym,internationalize_field_name.to_sym,internationalize_attr_names)
  196. end
  197. }
  198. else
  199. # classic field
  200. if attr_names==nil
  201. send(validator_name.to_sym,field_name.to_sym)
  202. else
  203. send(validator_name.to_sym,field_name.to_sym,attr_names)
  204. end
  205.  
  206. end
  207. } unless validators == nil
  208. }
  209. end
  210.  
  211.  
  212. def update_tags
  213. if @new_tag_list
  214. Tag.transaction do
  215. tags.clear
  216. Tag.parse(@new_tag_list).each do |name|
  217. tag = Tag.find_or_create_by_name(name)
  218. tags << tag
  219. end
  220. tags.reset
  221. @new_tag_list = nil
  222. end
  223. end
  224. end
  225.  
  226. def increment_counter_cache(tag)
  227. organization_tag = OrganizationTag.find_or_create_by_organization_id_and_tag_id(office.organization.id, tag.id)
  228. OrganizationTag.increment_counter('organization_count', organization_tag.id)
  229. end
  230.  
  231. def decrement_counter_cache(tag)
  232. organization_tag = OrganizationTag.find_or_create_by_organization_id_and_tag_id(office.organization.id, tag.id)
  233. OrganizationTag.decrement_counter('organization_count', organization_tag.id)
  234. end
  235.  
  236. public
  237.  
  238. def tag_list
  239. tags.collect{|tag| tag.name.include?(" ") ? %("#{tag.name}") : tag.name }.join(" ")
  240. end
  241.  
  242. def tag_list=(new_tag_list)
  243. unless tag_list == new_tag_list
  244. @new_tag_list = new_tag_list
  245. end
  246. end
  247.  
  248. # factory to instanciate House Apartement, and all TypeOfGood Classified classes through 'type' attribute
  249. def self.create(attributes)
  250. my_class = nil
  251. unless attributes[:type] == nil
  252. class_name = attributes[:type]
  253. attributes.delete(:type)
  254. my_class = class_name.constantize.new(attributes)
  255. end
  256. my_class
  257. end
  258.  
  259. def initialize(attributes = nil)
  260. if self.class.name != 'Classified' and attributes !=nil
  261. # allow_nil hack (to set to nil not mandatory blank attribute in order to pass validators)
  262. self.class.non_mandatory_fields(attributes[:type_of_transaction]).each{ |non_mandatory_field|
  263. if self.class.globalize_facets.include?(non_mandatory_field.to_sym)
  264. # for translated attributes (globalize keep_translations_in_model)
  265.  
  266. self.class.keep_translations_in_model_attribute_names(non_mandatory_field).each { |internationalized_attribute_name|
  267. attributes[internationalized_attribute_name.to_sym] = nil if attributes.has_key?(internationalized_attribute_name.to_sym) and attributes[internationalized_attribute_name.to_sym].blank?
  268. }
  269. else
  270. # for classic attributes
  271. attributes[non_mandatory_field.to_sym] = nil if attributes.has_key?(non_mandatory_field.to_sym) and attributes[non_mandatory_field.to_sym].blank?
  272. end
  273. }
  274. end
  275. super(attributes)
  276. end
  277.  
  278. def self.field_type(field_name,class_name=self.name)
  279. type_of_good = TypeOfGood.find_by_name(class_name)
  280. type_of_good.datafields[field_name]["field_type"] unless type_of_good == nil or type_of_good.datafields[field_name] ==nil
  281. end
  282.  
  283. def self.default_values?(field_name,class_name=self.name,type_of_default_values=nil)
  284. default_values_key = "default_values"
  285. default_values_key += "_"+type_of_default_values if type_of_default_values
  286. type_of_good = TypeOfGood.find_by_name(class_name)
  287. type_of_good != nil and type_of_good.datafields[field_name.to_s] !=nil and type_of_good.datafields[field_name.to_s][default_values_key].blank? ==false
  288. end
  289.  
  290. # return field_name default value depending on return_type:
  291. # return_type = nil (default) - an ordered array of [[default_label , default_value],...]
  292. # return_type = 'keys' - an ordered array of [default_label, default_label2,...]
  293. # return_type = 'values' - an ordered array of [default_value, default_value2,...]
  294. # return_type = 'Hash' - an non-ordered Hash of {default_label => default_value,...}
  295. # return_type = 'Hash' - an non-ordered Hash of {default_label => default_value,...}
  296. # class_name = "Apartment", "House", ... all child class name of Classified
  297. # type_of_default_values - instead of using global 'default_values' use a specific default_values_<type_of_default_values> list entry (see type_of_goods.yml)
  298. # options
  299. # - :override_allow_nil_label allow to replace label of ["Sélectionnez une valeur", nil] by ["<override_allow_nil_label value>", nil]
  300. #
  301. # Examples:
  302. # >> Classified.default_values("number_of_bedrooms",nil,"Apartment")
  303. # => [["Sélectionnez une valeur", nil], ["1", 1], ["2", 2], ["3", 3], ["4", 4], ["5+", 5]]
  304. #
  305. # >> Classified.default_values("number_of_bedrooms",Hash,"Apartment")
  306. # => {"5+"=>5, "Sélectionnez une valeur"=>nil, "1"=>1, "2"=>2, "3"=>3, "4"=>4}
  307. #
  308. # >> Classified.default_values("price_frequency",Hash,"Field","rental")
  309. # >> Classified.default_values("price_frequency",Hash,"*","*")
  310. # =>
  311. # find all type type of default values for field "price_frequency" for each TypeOfGood and TypeOfTransaction
  312.  
  313. def self.default_values(field_name,return_type=nil,class_name=self.name,type_of_default_value=nil,options={})
  314. return_values =[]
  315.  
  316. if class_name=='*'
  317. class_names= TypeOfGood.find(:all).map{|t| t.name}
  318. else
  319. class_names=[class_name]
  320. end
  321.  
  322. if type_of_default_value=='*'
  323. type_of_default_values=TypeOfTransaction.find(:all).map{|t| t.name}
  324. type_of_default_values.unshift(nil)
  325. else
  326. type_of_default_values=[type_of_default_value]
  327. end
  328.  
  329. class_names.each{|class_name|
  330. default_values = {}
  331. type_of_good = TypeOfGood.find_by_name(class_name)
  332.  
  333.  
  334.  
  335.  
  336. type_of_default_values.each{|type_of_default_value|
  337. default_values_key = "default_values"
  338. default_values_key += "_"+type_of_default_value if type_of_default_value
  339.  
  340. value = type_of_good.datafields[field_name.to_s][default_values_key] unless type_of_good == nil or type_of_good.datafields[field_name.to_s] ==nil
  341.  
  342. unless value ==nil
  343. default_values = eval(value)
  344. default_values = default_values.map{|item| item[1]==nil ? [options[:override_allow_nil_label],nil] : [item[0],item[1]]} if options[:override_allow_nil_label]
  345. end
  346.  
  347. if default_values.size>0
  348. case return_type.to_s
  349. when "" #nil.to_s
  350. return_values << default_values if return_type==nil
  351. when Hash.name
  352. return_values << Hash[*default_values.flatten]
  353. when "keys"
  354. return_values << default_values.map{|x| x[0]}
  355. when "values"
  356. return_values << default_values.map{|x| x[1]}
  357. else
  358. raise "bad return_type (#{return_type}) for Classified.default_value"
  359. end
  360. end
  361. }
  362. }
  363.  
  364. return_values = return_values[0] if return_values.size==1
  365. return_values = {} if return_values.size == 0 and return_type.to_s == Hash.name
  366. return return_values
  367. end
  368.  
  369. # return field_name default_values (based on classified type_of_transaction)
  370. # see self.default_values
  371. def default_values(field_name,return_type=nil)
  372. if self.class.default_values?(field_name,self.class.name,type_of_transaction)
  373. type_of_default_values = type_of_transaction
  374. else
  375. type_of_default_values = nil
  376. end
  377. self.class.default_values(field_name,return_type,self.class.name,type_of_default_values)
  378. end
  379. # when field_name has default_values? map value to default value 'label', otherwise display value
  380. def display_value_map(field_name)
  381. if respond_to?(field_name)
  382. value = send(field_name)
  383. hash = default_values(field_name,Hash).invert
  384. value = hash[value] if hash[value]
  385. end
  386. value
  387. end
  388.  
  389. # return a hash of [data_fields_name => is_field_mandatory (true or false)], if type_of_transaction = nil or not found it return complete datafield list
  390. def self.datafields(type_of_transaction=nil)
  391. fields_info = {}
  392. type_of_good = TypeOfGood.find_by_name( self.name)
  393. type_of_good.datafields.each{ |field_name,validators|
  394. unless (validators != nil and validators["exclude_for_type_of_transactions"] != nil and validators["exclude_for_type_of_transactions"].include?(type_of_transaction))
  395. mandatory = false
  396. if (validators !=nil)
  397. mandatory = true
  398. count_allow_nil = 0
  399. validators.each { |validator_name,validator_args|
  400. if (validator_name =~ /^validates_/)!=0
  401. count_allow_nil = count_allow_nil+1
  402. next
  403. end
  404. attr_names = validator_args==nil ? nil : eval(validator_args)
  405. count_allow_nil = count_allow_nil+1 if attr_names != nil and attr_names[:allow_nil] == true
  406. }
  407. mandatory = false if validators.size == count_allow_nil
  408. end
  409. fields_info[field_name] = mandatory
  410. end
  411. }
  412. fields_info
  413. end
  414. # see self.datafields
  415. def datafields
  416. self.class.datafields(type_of_transaction)
  417. end
  418. # return a array of non_mandatory fields
  419. def self.non_mandatory_fields(type_of_transaction=nil)
  420. self.datafields(type_of_transaction).delete_if {|field_name,mandatory| mandatory==true }.keys
  421. end
  422. # see self.non_mandatory_fields
  423. def non_mandatory_fields
  424. self.class.non_mandatory_fields(type_of_transaction)
  425. end
  426. # return a array of mandatory fields
  427. def self.mandatory_fields(type_of_transaction=nil)
  428. self.datafields(type_of_transaction).delete_if {|field_name,mandatory| mandatory==false }.keys
  429. end
  430. # see self.mandatory_fields
  431. def mandatory_fields
  432. self.class.mandatory_fields(type_of_transaction)
  433. end
  434. # return a array of displayed fields
  435. def self.displayed_fields(type_of_transaction=nil)
  436. self.datafields(type_of_transaction).keys
  437. end
  438. # see self.displayed_fields
  439. def displayed_fields
  440. self.class.displayed_fields(type_of_transaction)
  441. end
  442. # check if field_name is displayable depending of type_of_transaction
  443. def self.displayable_field(type_of_transaction,field_name)
  444. self.datafields(type_of_transaction).keys.include?(field_name.to_s)
  445. end
  446. # see self.displayable_field
  447. def displayable_field(field_name,false_if_empty=false)
  448. return false if false_if_empty and send(field_name)==nil
  449. self.class.displayable_field(type_of_transaction,field_name)
  450. end
  451. # check if field_name is mandatory depending of type_of_transaction
  452. def self.mandatory_field(type_of_transaction,field_name)
  453. self.mandatory_fields(type_of_transaction).include?(field_name.to_s)
  454. end
  455. # see self.mandatory_field
  456. def mandatory_field(field_name)
  457. self.class.mandatory_field(type_of_transaction,field_name)
  458. end
  459.  
  460. # provide an array of all TypeOfGood datafields
  461. def self.all_datafields
  462. fixtures_data = YAML::load_file(self::DataFieldsFilePath)
  463. end
  464. # see self.all_datafields
  465. def all_datafields
  466. self.class.all_datafields
  467. end
  468.  
  469. # tell for all_adatafields if [fieldname => is displayable]
  470. def fields_displayability
  471. fields_displayability = {}
  472. displayed_fields = displayed_fields()
  473. all_datafields.each{ |field| fields_displayability[field] = displayed_fields.include?(field)}
  474. fields_displayability
  475. end
  476.  
  477. def user_id=(value)
  478. super(value)
  479. self.user = User.find(value) if !value.blank?
  480. self[:user_id]=value
  481. end
  482.  
  483. def office_id=(value)
  484. super(value)
  485. self.office = Office.find(self[:office_id]) if !value.blank?
  486. end
  487.  
  488. def program_id=(value)
  489. super(value)
  490. self.program = Program.find(self[:program_id]) if !value.blank?
  491. end
  492.  
  493. #always convert to square meters
  494. def area_size=(value)
  495. begin
  496. Kernel.Float(value) # test numeric value
  497. self[:area_size] = value.to_i.send(Locale.active.country.area_size_unit).to_square_meters.value
  498. rescue ArgumentError, TypeError
  499. self[:area_size] = value #pass raw value to validator
  500. end
  501. end
  502. #always convert to square meters
  503. def lot_size=(value)
  504. begin
  505. Kernel.Float(value) # test numeric value
  506. self[:lot_size] = value.to_i.send(Locale.active.country.lot_size_unit).to_square_meters.value
  507. rescue ArgumentError, TypeError
  508. self[:lot_size] = value #pass raw value to validator
  509. end
  510. end
  511.  
  512. def area_size_localized
  513. begin
  514. self[:area_size].square_meters.send(Locale.active.country.area_size_unit).value.to_i
  515. rescue
  516. self[:area_size]
  517. end
  518. end
  519.  
  520. def lot_size_localized
  521. begin
  522. self[:lot_size].square_meters.send(Locale.active.country.lot_size_unit).value.to_i
  523. rescue
  524. self[:lot_size]
  525. end
  526. end
  527. end
  528.  
  529. # {attr_name}_display magic method
  530. Classified.class_eval do
  531. self.all_datafields.each {|attr_name|
  532. next if self.method_defined?("#{attr_name}_display".to_sym)
  533. define_method("#{attr_name}_display".to_sym) {
  534. display_value_map(attr_name)
  535. }
  536. }
  537. end
Add Comment
Please, Sign In to add comment