Class: Gin::AssetPipeline

Inherits:
Object
  • Object
show all
Defined in:
lib/gin/asset_pipeline.rb

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(manifest_file, render_dir, asset_paths, sprockets, &block) ⇒ AssetPipeline

Returns a new instance of AssetPipeline.


10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
# File 'lib/gin/asset_pipeline.rb', line 10

def initialize manifest_file, render_dir, asset_paths, sprockets, &block
  @rendering  = 0
  @logger     = $stderr
  @listen     = false
  @thread     = false
  @sprockets  = nil
  @flag_update = false

  @render_lock = Gin::RWLock.new
  @listen_lock = Gin::RWLock.new

  @manifest = Gin::AssetManifest.new(manifest_file, render_dir, asset_paths)

  setup_listener(asset_paths, sprockets, &block)
end

Instance Attribute Details

#loggerObject

Returns the value of attribute logger


8
9
10
# File 'lib/gin/asset_pipeline.rb', line 8

def logger
  @logger
end

Instance Method Details

#listenObject


84
85
86
87
88
89
90
91
92
# File 'lib/gin/asset_pipeline.rb', line 84

def listen
  stop if listen?

  @thread = Thread.new do
    listen!
  end

  @thread.abort_on_exception = true
end

#listen!Object


95
96
97
98
99
100
101
102
# File 'lib/gin/asset_pipeline.rb', line 95

def listen!
  @listen_lock.write_sync{ @listen = true }

  while listen? do
    render_all if outdated?
    sleep 0.2
  end
end

#listen?Boolean

Returns:

  • (Boolean)

105
106
107
# File 'lib/gin/asset_pipeline.rb', line 105

def listen?
  @listen_lock.read_sync{ @listen }
end

#log(str) ⇒ Object


71
72
73
# File 'lib/gin/asset_pipeline.rb', line 71

def log str
  @logger << "#{str}\n"
end

#manifest_fileObject


43
44
45
# File 'lib/gin/asset_pipeline.rb', line 43

def manifest_file
  @manifest.filepath
end

#manifest_file=(new_file) ⇒ Object


48
49
50
# File 'lib/gin/asset_pipeline.rb', line 48

def manifest_file= new_file
  @manifest.filepath = new_file
end

#outdated?Boolean

Returns:

  • (Boolean)

121
122
123
# File 'lib/gin/asset_pipeline.rb', line 121

def outdated?
  @flag_update || @manifest.outdated?
end

#remove_path(path) ⇒ Object


151
152
153
154
155
156
157
158
159
160
# File 'lib/gin/asset_pipeline.rb', line 151

def remove_path path
  log "Deleting asset: #{path}"
  File.delete(path)

  dir = File.dirname(path)
  while dir != self.render_dir && Dir[File.join(dir,'*')].empty?
    FileUtils.rm_r(dir)
    dir = File.dirname(dir)
  end
end

#render(path) ⇒ Object


202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
# File 'lib/gin/asset_pipeline.rb', line 202

def render path
  asset = @sprockets[path]
  return unless asset

  ext = render_ext(asset)
  render_path = File.join(self.render_dir, asset.logical_path)

  file_glob = render_path.sub(/(\.\w+)$/, "-*#{ext}")
  file_name = Dir[file_glob].first

  digest = asset.digest[0..7]
  return file_name if file_name && file_name.include?(digest)

  log "Rendering asset: #{path}"
  render_filename = file_glob.sub('*', digest)

  FileUtils.mkdir_p File.dirname(render_filename)
  File.open(render_filename, 'wb'){|f| f.write asset.source }

  File.delete(file_name) if file_name

  return render_filename
end

#render_allObject

Looks at all rendered, added, and modified assets and compiles those out of date or missing.


167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
# File 'lib/gin/asset_pipeline.rb', line 167

def render_all
  update_sprockets

  with_render_lock do
    sp_files = @sprockets.each_file.map(&:to_s).uniq

    # delete rendered files that aren't in the asset_dirs
    @manifest.assets.each do |asset_file, asset|
      valid_asset = sp_files.include?(asset_file)
      next if valid_asset

      target_file = asset.target_file
      remove_path target_file if target_file
      @manifest.delete(asset_file)
    end

    # render assets and update tree index
    sp_files.each do |asset_file|
      next unless @manifest.asset_outdated?(asset_file)
      sp_asset = @sprockets[asset_file] # First time render

      if target_file = render(asset_file)
        @manifest.stage asset_file, target_file,
          sp_asset.dependencies.map{|d| d.pathname.to_s }
      end
    end

    @manifest.commit!

    # save cache to disk
    @manifest.save_file!
  end
end

#render_dirObject


53
54
55
# File 'lib/gin/asset_pipeline.rb', line 53

def render_dir
  @manifest.render_dir
end

#render_dir=(new_dir) ⇒ Object


58
59
60
61
62
63
64
65
66
67
68
# File 'lib/gin/asset_pipeline.rb', line 58

def render_dir= new_dir
  new_dir = File.expand_path(new_dir)

  if @manifest.render_dir != new_dir
    @listen_lock.write_sync do
      # TODO: instead of re-rendering everything, maybe move rendered assets?
      @flag_update = true
      @manifest.render_dir = new_dir
    end
  end
end

#rendering?Boolean

Returns true if in the middle of rendering, otherwise false.

Returns:

  • (Boolean)

79
80
81
# File 'lib/gin/asset_pipeline.rb', line 79

def rendering?
  @render_lock.read_sync{ @rendering != 0 || @flag_update }
end

#setup_listener(asset_paths = [], spr = nil) {|spr| ... } ⇒ Object

Yields:

  • (spr)

27
28
29
30
31
32
33
34
35
36
37
38
39
40
# File 'lib/gin/asset_pipeline.rb', line 27

def setup_listener asset_paths=[], spr=nil, &block
  spr = Sprockets::Environment.new unless Sprockets::Environment === spr

  @manifest.asset_globs = asset_paths

  @manifest.source_dirs.each do |path|
    spr.append_path path
  end

  yield spr if block_given?

  @manifest.asset_globs |= spr.paths
  @sprockets = spr
end

#stopObject


110
111
112
# File 'lib/gin/asset_pipeline.rb', line 110

def stop
  @listen_lock.write_sync{ @listen = false }
end

#stop!Object


115
116
117
118
# File 'lib/gin/asset_pipeline.rb', line 115

def stop!
  stop
  @thread.join if @thread && @thread.alive?
end

#update_sprocketsObject


126
127
128
129
130
131
132
# File 'lib/gin/asset_pipeline.rb', line 126

def update_sprockets
  paths = @manifest.source_dirs
  return if @sprockets.paths == paths

  @sprockets.clear_paths
  paths.each{|path| @sprockets.append_path(path) }
end

#with_render_lock(&block) ⇒ Object


135
136
137
138
139
140
141
142
143
144
145
146
147
148
# File 'lib/gin/asset_pipeline.rb', line 135

def with_render_lock &block
  @render_lock.write_sync{ @rendering += 1 }
  start = Time.now
  block.call

  log "Assets rendered in (#{(Time.now.to_f - start.to_f).round(3)} sec)"

ensure
  @render_lock.write_sync do
    @rendering -= 1
    @rendering = 0 if @rendering < 0
    @flag_update = false
  end
end