Class: ConstructorPages::Page

Inherits:
ActiveRecord::Base
  • Object
show all
Includes:
ActiveSupport::Inflector
Defined in:
app/models/constructor_pages/page.rb

Overview

Page model. Pages are core for company websites, blogs etc.

Class Method Summary collapse

Instance Method Summary collapse

Dynamic Method Handling

This class handles dynamic methods through the method_missing method

#method_missing(name, *args, &block) ⇒ Object

When method missing it get/set field value or get page in branch

Examples:

page.content = 'Hello world'
puts page.price
page.brand.models.each do...


197
198
199
200
201
# File 'app/models/constructor_pages/page.rb', line 197

def method_missing(name, *args, &block)
  super && return if new_record?
  name = name.to_s
  name[-1] == '=' ? set_field_value(name[0..-2], args[0]) : get_field_value(name) || find_pages_in_branch(name)
end

Class Method Details

.by(params = nil) ⇒ Object



69
# File 'app/models/constructor_pages/page.rb', line 69

def by(params = nil); tap {@params = params} end

.check_code_name(code_name) ⇒ Object

Check code_name for field and template. When missing method Page find field or page in branch with plural and singular code_name so field and template code_name should be uniqueness for page methods



43
44
45
46
47
# File 'app/models/constructor_pages/page.rb', line 43

def check_code_name(code_name)
  [code_name, code_name.pluralize, code_name.singularize].each {|name|
    return false if Page.instance_methods.include?(name.to_sym)}
  true
end

.find_by_request_or_first(request = nil) ⇒ Object

Used for find page by request. It return first page if no request given or request is home page

Parameters:

  • request (defaults to: nil)

    for example '/conditioners/split-systems/zanussi'



29
30
31
# File 'app/models/constructor_pages/page.rb', line 29

def find_by_request_or_first(request = nil)
  (request.nil? || request == '/') ? Page.first : Page.find_by(full_url: request)
end

.full_url_generate(parent_id, url = '') ⇒ Object

Generate full_url from parent id and url

Parameters:

  • parent_id

    integer

  • url (defaults to: '')

    should looks like 'hello-world-page' without leading slash



36
37
38
# File 'app/models/constructor_pages/page.rb', line 36

def full_url_generate(parent_id, url = '')
  '/' + Page.find(parent_id).self_and_ancestors.map{|p| p.url if p.in_url}.append(url).compact.join('/')
end

.ids_by_params(params) ⇒ Object

Return ids of pages founded by params



75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
# File 'app/models/constructor_pages/page.rb', line 75

def ids_by_params(params)
  _hash = {}

  params.each_pair do |key, value|
    next if key == 'utf8'

    key = key.to_s
    _key, _value = key.gsub(/>|</, ''), value

    if _value.is_a?(String)
      next if _value.strip.empty?
      _value = _value.gsub(/>|</, '')
      _value = _value.numeric? ? _value.to_f : (_value.to_boolean if _value.boolean?)
    end

    sign = '='

    if key =~ />$/ || value =~ /^>/
      sign = '>'
    elsif key =~ /<$/ || value =~ /^</
      sign = '<'
    end

    _fields = ConstructorPages::Field.where(code_name: _key)

    _ids = []

    _fields.each do |_field|
      _hash[:field_id] = _field.id
      _ids << _field.type_class.where("value #{sign} ?", _value).where(_hash).map(&:page_id)
    end

    _hash[:page_id] = _ids.flatten.uniq
  end

  return _hash[:page_id] || []
end

.in(where = nil) ⇒ Object



68
# File 'app/models/constructor_pages/page.rb', line 68

def in(where  = nil); tap {@where  = where}  end

.search(what = nil) ⇒ Object

Search pages

Example:

Page.in('/conditioners').search_by(area: 25)
Page.by('price<' => 5000).search_in('/zanussi')
Page.in('/midea').by('price>' => 10000).search(:models)


55
56
57
58
59
60
61
62
63
64
65
66
# File 'app/models/constructor_pages/page.rb', line 55

def search(what = nil)
  _hash, _array = {}, []
  @where = Page.find_by(full_url: @where) if @where.is_a?(String)
  _array = ['lft > ? and rgt < ?', @where.lft, @where.rgt] if @where
  if what
    what = what.to_s.singularize.downcase
    _hash[:template_id] = ConstructorPages::Template.find_by(code_name: what).try(:id)
  end
  _hash[:id] = ids_by_params(@params) if @params
  @where = @params = nil
  _hash.empty? && _array.empty? ? [] : Page.where(_hash).where(_array).to_a
end

.search_by(params = nil) ⇒ Object



72
# File 'app/models/constructor_pages/page.rb', line 72

def search_by(params = nil); self.by(params).search end

.search_in(where = nil) ⇒ Object



71
# File 'app/models/constructor_pages/page.rb', line 71

def search_in(where  = nil); self.in(where).search  end

Instance Method Details

#as_json(options = {}) ⇒ Object

Returns page hash attributes with fields.

Default attributes are name and title. Options param allows to add more.

Parameters:

  • options (defaults to: {})

    default merge name and title page attributes



177
178
179
180
181
# File 'app/models/constructor_pages/page.rb', line 177

def as_json(options = {})
  {name: self.name, title: self.title}.merge(options).tap do |options|
    fields.each {|f| options.merge!({f.code_name.to_sym => f.get_value_for(self)})}
  end
end

#by(params = nil) ⇒ Object



115
# File 'app/models/constructor_pages/page.rb', line 115

def by(params = nil); Page.by(params); self end

#create_fields_valuesObject

Create fields values



142
# File 'app/models/constructor_pages/page.rb', line 142

def create_fields_values; fields.each {|f| f.create_type_object self} end

#field(code_name) ⇒ Object

Get field by code_name



119
120
121
# File 'app/models/constructor_pages/page.rb', line 119

def field(code_name)
  Field.find_by code_name: code_name, template_id: template_id
end

#find_page_in_branch(cname) ⇒ Object Also known as: find_pages_in_branch

Search page by template code_name in same branch of pages and templates. It allows to call page.category.brand.series.model etc.

Return one page if founded in ancestors, and return array of pages if founded in descendants

It determines if code_name is singular or nor

Parameters:

  • cname

    template code name



155
156
157
158
159
# File 'app/models/constructor_pages/page.rb', line 155

def find_page_in_branch(cname)
  Template.find_by(code_name: cname.singularize).tap {|t| t || return
    (descendants.where(template_id: t.id) if cname == cname.pluralize).tap {|r| r ||= []
      return r.empty? ? ancestors.find_by(template_id: t.id) : r}}
end

#get_field_value(code_name) ⇒ Object

Get value of field by code_name



124
# File 'app/models/constructor_pages/page.rb', line 124

def get_field_value(code_name); field(code_name).try(:get_value_for, self) end

#in_breadcrumbsObject



163
# File 'app/models/constructor_pages/page.rb', line 163

def in_breadcrumbs; in_nav end

#multipart?Boolean

Return true if there is a file upload field in page

Returns:

  • (Boolean)


168
169
170
171
# File 'app/models/constructor_pages/page.rb', line 168

def multipart?
  fields.each {|f| return true if f.type_value == 'image'}
  false
end

#published?Boolean

Returns:

  • (Boolean)


165
# File 'app/models/constructor_pages/page.rb', line 165

def published?; active? end

#redirect?Boolean

Check if link specified

Returns:

  • (Boolean)


184
# File 'app/models/constructor_pages/page.rb', line 184

def redirect?; url != redirect && !redirect.empty? end

#remove_fields_valuesObject

Remove all fields values



145
# File 'app/models/constructor_pages/page.rb', line 145

def remove_fields_values; fields.each {|f| f.remove_type_object self} end

#search(what = nil) ⇒ Object



114
# File 'app/models/constructor_pages/page.rb', line 114

def search(what = nil); Page.in(self).search(what) end

#search_by(params = nil) ⇒ Object



116
# File 'app/models/constructor_pages/page.rb', line 116

def search_by(params = nil); Page.by(params).in(self).search end

#set_field_value(code_name, value) ⇒ Object

Set value of field by code_name and value



127
# File 'app/models/constructor_pages/page.rb', line 127

def set_field_value(code_name, value); field(code_name).try(:set_value_for, self, value) end

#touch_branchObject

Touch all pages in same branch



187
188
189
# File 'app/models/constructor_pages/page.rb', line 187

def touch_branch
  [ancestors, descendants].each {|p| p.map(&:touch)}
end

#update_fields_values(params, reset_booleans = true) ⇒ Object

Update all fields values with given params.

Parameters:

  • params

    should looks like {price: 500, content: 'Hello'}

  • reset_booleans (defaults to: true)

    reset all boolean fields to false before assign params



132
133
134
135
136
137
138
139
# File 'app/models/constructor_pages/page.rb', line 132

def update_fields_values(params, reset_booleans = true)
  params || return

  fields.each {|f| f.find_or_create_type_object(self).tap {|t| t || next
    t.value = 0 if f.type_value == 'boolean' && reset_booleans
    params[f.code_name.to_sym].tap {|v| v && t.value = v}
    t.save }}
end