Class: Site

Inherits:
MongoRecord show all
Defined in:
lib/yodel/models/core/site/site.rb

Constant Summary

Constants inherited from AbstractRecord

AbstractRecord::CALLBACKS, AbstractRecord::FIELD_CALLBACKS, AbstractRecord::ORDERS

Instance Attribute Summary collapse

Attributes inherited from AbstractRecord

#changed, #errors, #stash, #typecast, #values

Class Method Summary collapse

Instance Method Summary collapse

Methods inherited from MongoRecord

#collection, #default_values, #fields, #id, #increment!, #inspect_hash, #load_from_mongo, #load_mongo_document, #perform_destroy, #perform_reload, #perform_save, #set_id

Methods included from MongoModel

#collection, #load, #scoped

Methods included from AbstractModel

#embed_many, #embed_one, #field, #fields, #many, #modify_field, #one, #remove_field

Methods inherited from AbstractRecord

#changed!, #changed?, #clear_key, #default_values, #destroy, #destroyed?, #eql?, #errors?, #field, #field?, #field_was, #fields, #from_json, #get, #get_meta, #get_raw, #hash, #id, #increment!, inherited, #inspect, #inspect_hash, #inspect_value, #new?, #prepare_reload_params, #present?, #reload, #save, #save_without_validation, #search_terms, #set, #set_meta, #set_raw, #to_json, #to_str, #trigger_field_callback, #update, #valid?

Constructor Details

#initialize(values = {}, new_record = true) ⇒ Site

Returns a new instance of Site.



17
18
19
20
21
22
23
24
25
26
27
# File 'lib/yodel/models/core/site/site.rb', line 17

def initialize(values={}, new_record=true)
  super
  @cached_records = {}
  @cached_models  = {}
  
  # static models
  @models = Model.scoped_for(self)
  @cached_models['Model']   = @cached_models['models']    = @models
  @cached_models['Trigger'] = @cached_models['triggers']  = Trigger.scoped_for(self)
  @cached_models['Task']    = @cached_models['tasks']     = Task.scoped_for(self)
end

Dynamic Method Handling

This class handles dynamic methods through the method_missing method

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


Model Lookups


Method missing is utilised to allows lookups of models by their plural name directly on a site object. site.models is equivalent to site.model(‘Model’)



176
177
178
179
180
181
182
183
184
185
186
# File 'lib/yodel/models/core/site/site.rb', line 176

def method_missing(name, *args, &block)
  # attempt to find the model in the cached_models hash
  key = name.to_s
  model = @cached_models[key]
  return model unless model.nil?
  
  # otherwise perform a lookup
  model = model_by_plural_name(key)
  return super if model.nil?
  model
end

Instance Attribute Details

#cached_modelsObject (readonly)

Returns the value of attribute cached_models.



2
3
4
# File 'lib/yodel/models/core/site/site.rb', line 2

def cached_models
  @cached_models
end

#cached_recordsObject (readonly)

Returns the value of attribute cached_records.



2
3
4
# File 'lib/yodel/models/core/site/site.rb', line 2

def cached_records
  @cached_records
end

Class Method Details

.load_from_site_yaml(path) ⇒ Object



164
165
166
167
168
# File 'lib/yodel/models/core/site/site.rb', line 164

def self.load_from_site_yaml(path)
  Site.new(YAML.load_file(path)).tap do |site|
    site.root_directory = File.dirname(path)
  end
end

Instance Method Details

#attachments_directoryObject



80
81
82
# File 'lib/yodel/models/core/site/site.rb', line 80

def attachments_directory
  @attachments_dir ||= File.join(root_directory, Yodel::ATTACHMENTS_DIRECTORY_NAME)
end

#destroy_directoriesObject



134
135
136
137
138
139
140
141
142
143
144
145
# File 'lib/yodel/models/core/site/site.rb', line 134

def destroy_directories
  # root directory
  FileUtils.remove_entry_secure(root_directory) if File.directory?(root_directory)
  
  # domain symlinks in production
  if Yodel.env.production?
    domains.each do |domain|
      path = File.join(Yodel.config.public_directory, domain)
      FileUtils.remove_file(path, true) if File.symlink?(path)
    end
  end
end

#destroy_recordsObject



125
126
127
128
129
130
131
# File 'lib/yodel/models/core/site/site.rb', line 125

def destroy_records
  Trigger.collection.remove(_site_id: id)
  LogEntry.collection.remove(_site_id: id)
  Record.collection.remove(_site_id: id)
  Model.collection.remove(_site_id: id)
  Task.collection.remove(_site_id: id)
end

#latest_revisionObject



108
109
110
111
112
# File 'lib/yodel/models/core/site/site.rb', line 108

def latest_revision
  Dir.chdir(root_directory) do
    `git log -n1 --pretty=format:"%H"`
  end
end

#latest_revision_dateObject



114
115
116
117
118
# File 'lib/yodel/models/core/site/site.rb', line 114

def latest_revision_date
  Dir.chdir(root_directory) do
    `git log -n1 --pretty=format:"%ai"`
  end
end

#layout_directoriesObject



68
69
70
# File 'lib/yodel/models/core/site/site.rb', line 68

def layout_directories
  @layout_dirs ||= Yodel.config.layout_directories + [layouts_directory]
end

#layouts_directoryObject



64
65
66
# File 'lib/yodel/models/core/site/site.rb', line 64

def layouts_directory
  @layouts_dir ||= File.join(root_directory, Yodel::LAYOUTS_DIRECTORY_NAME)
end

#local_domainObject



88
89
90
# File 'lib/yodel/models/core/site/site.rb', line 88

def local_domain
  domains.find {|domain| domain.end_with?('.yodel')}
end

#logObject



39
40
41
# File 'lib/yodel/models/core/site/site.rb', line 39

def log
  @log ||= Log.new(self)
end

#migrations_directoryObject



76
77
78
# File 'lib/yodel/models/core/site/site.rb', line 76

def migrations_directory
  @migrations_dir ||= File.join(root_directory, Yodel::MIGRATIONS_DIRECTORY_NAME)
end

#model(name) ⇒ Object

Retrieve a model by its full name (‘Model’ as opposed to ‘models’)



206
207
208
209
210
211
212
213
214
# File 'lib/yodel/models/core/site/site.rb', line 206

def model(name)
  # get is required here instead calling 'model_types' explicitly as that relies
  # on method_missing which in turn sometimes calls this method (creating
  # infinite recursion)
  return nil if name.nil?
  model = @cached_models[name]
  return model unless model.nil?
  model_by_plural_name(get('model_plural_names')[name])
end

#model_by_plural_name(name) ⇒ Object

Retrieve a model by its plural name (‘models’ as opposed to ‘Model’). In general use the method missing functionality of site since it checks the cached_models hash before performing a lookup, whereas this method will always do a lookup.



191
192
193
194
195
196
197
198
199
200
201
202
203
# File 'lib/yodel/models/core/site/site.rb', line 191

def model_by_plural_name(name)
  # ensure the site has a reference to a model by this name. get is required here
  # instead calling 'model_types' explicitly as that relies on method_missing
  # which in turn sometimes calls this method (creating infinite recursion)
  model_id = get('model_types')[name]
  return nil if model_id.nil?
  
  # perform a lookup; nil will be returned if the model doesn't exist
  model = @models.find(model_id)
  @cached_models[name] = model
  @cached_models[model.name] = model
  @cached_records[model.id] = model
end

#option(path) ⇒ Object


Accessors


TODO: a better interface is site.options.name.option; site.options.pages.permalink_character



34
35
36
37
# File 'lib/yodel/models/core/site/site.rb', line 34

def option(path)
  component, option = path.split('.')
  options[component].try(:fetch, option, nil).try(:fetch, 'value', nil)
end

#partials_directoryObject



72
73
74
# File 'lib/yodel/models/core/site/site.rb', line 72

def partials_directory
  @partials_dir ||= File.join(root_directory, Yodel::PARTIALS_DIRECTORY_NAME)
end

#public_directoriesObject



60
61
62
# File 'lib/yodel/models/core/site/site.rb', line 60

def public_directories
  @public_dirs ||= Yodel.config.public_directories + [public_directory]
end

#public_directoryObject



56
57
58
# File 'lib/yodel/models/core/site/site.rb', line 56

def public_directory
  @public_dir ||= File.join(root_directory, Yodel::PUBLIC_DIRECTORY_NAME)
end

#reload_from_site_yamlObject



160
161
162
# File 'lib/yodel/models/core/site/site.rb', line 160

def reload_from_site_yaml
  update(YAML.load_file(site_yaml_path))
end

#remote_domainsObject



92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
# File 'lib/yodel/models/core/site/site.rb', line 92

def remote_domains
  domains.select do |domain|
    !domain.end_with?('.yodel') &&
    !domain.end_with?('.local') &&
    !domain.end_with?('.localhost') &&
    !domain.start_with?('192.168.') &&
    !domain.start_with?('10.') &&
    !domain.start_with?('127.') &&
    (!domain.start_with?('172.') || !(16..31).include?(domain.split('.')[1].to_i)) &&
    domain != '0.0.0.0' &&
    domain != '255.255.255.255' &&
    domain != 'localhost' &&
    domain != 'broadcasthost'
  end
end

#root_directoryObject



43
44
45
46
47
48
49
50
51
52
53
54
# File 'lib/yodel/models/core/site/site.rb', line 43

def root_directory
  # TODO: find a better way to distinguish between dev/prod and normal sites
  @root_directory ||= begin
    if name != 'yodel'
      get('root_directory')
    elsif Yodel.env.production?
      Yodel.extensions['yodel_production_environment'].lib_dir
    else
      Yodel.extensions['yodel_development_environment'].lib_dir
    end
  end
end

#site_yaml_pathObject



84
85
86
# File 'lib/yodel/models/core/site/site.rb', line 84

def site_yaml_path
  File.join(root_directory, Yodel::SITE_YML_FILE_NAME)
end

#update_site_ymlObject



148
149
150
151
152
153
154
155
156
157
158
# File 'lib/yodel/models/core/site/site.rb', line 148

def update_site_yml
  return unless Yodel.env.development?
  File.open(site_yaml_path, 'w') do |file|
    file.write(YAML.dump({
      name: name.to_s,
      extensions: extensions.to_a,
      domains: remote_domains.to_a,
      options: options.to_hash
    }))
  end
end