Does buildr have pre-defined variables, like capistrano, for directories like 'target', 'reports', etc? If not, rather than hard-coding the location of these directories, how else can we locate/determine these paths?
The end goal is to create a task that will on-the-fly create a file and insert it into the target directory.
Buildr defines symbolic names for the special directories. The path_to (aka _) method accepts these symbolic names and automatically translates them into the paths for the current layout. E.g.,
define 'foo' do
puts _(:target, :main, :classes) # => /some/root/foo/target/classes
puts path_to(:source, :main, :java) # => /some/root/foo/src/main/java
end
As Antoine noted in reply to another answer, there's a list of these symbolic names in the documentation.
You can define a new layout and use it in your project.
The example of buildfile here:
my_layout = Layout.new
my_layout[:source, :main, :java] = 'java'
my_layout[:source, :main, :resources] = 'resources'
define 'foo', :layout=>my_layout do
...
end
Update
Link to Buildr's tutorial http://buildr.apache.org/extending.html#layouts
As UR6LAD says, buildr stores all its paths in a per-project instance of Layout. This page describes the default layout.
The target directory can be accessed using layout[:target].
Related
I have next folder structure:
-features
-admin
-desktop
-mobile
-step definitions
-support
I want to know from which folder current scenario is running now (admin / desktop / mobile).
Is it possible?
Because I want to add a condition into hooks file for execute needed conditions of different folders.
You can access details about the feature file location using the Scenario#location method, which returns a Cucumber::Core::Ast::Location::Precise. From that you can access the feature's file path using #file:
scenario.location.file
#=> "features/mobile/test.feature"
For example, the hook could look like:
Before do |scenario|
platform = scenario.location.file.split(File::SEPARATOR)[1].to_sym
#=> :admin:, :desktop or :mobile
# Output the platform (or whatever conditional logic you want)
case platform
when :admin then puts 'admin'
when :desktop then puts 'desktop'
when :mobile then puts 'mobile'
end
end
If you're using Ruby version 2.0 and above then the __dir__ method is your way to go (in case you want to get the absolute path):
# File: /home/xxx/folder/features/admin/test.rb
puts __dir__ # => "/home/xxx/folder/features/admin"
But what if you only want to know the name of the directory where the file resides? Then you could use File.basename:
# File: /home/xxx/folder/features/admin/test.rb
puts File.basename(__dir__) # => "admin"
I have for example directory structure like this:
./DIRECTORY/PROJECT_A/cars/
./DIRECTORY/PROJECT_B/planes/
./DIRECTORY/PROJECT_C/bikes/
I would like to recourse through them using wildcards and create other directory's, like this:
Dir['/DIRECTORY/PROJECT_*/*/'].each do FileUtils.mkdir_p 'TheNewDirectory'.
It seems "FileUtils" doesn't support wildcards.
I'm doing the same for creation of files on this way:
Dir['/DIRECTORY/PROJECT_*/*/'].each do |dir|
File.new File.join(dir, 'myFile.txt'), 'w+'
end
So I would like to do the same but for creation of directories. Any idea?
FileUtils is a module. It doesn't make sense to claim that a module "does not use wildcards".
Moreover, you are using only the function mkdir_p from FileUtils, and do not use any wildcard in its argument, so what you say, doesn't apply to your case either.
What happened is, that your are iterating through all the directories entries created by your Dir[...] expression, but then don't use the actual directory! A first step to write this better would be
Dir['/DIRECTORY/PROJECT_*/*/'].each { |d| FileUtils.mkdir_p("#{d}/TheNewDirectory") }
This works however only if it is guaranteed that d never takes the value of a plain file, and of course you can run this code only once (because the second time, you would obviously create directories of the form /DIRECTORY/PROJECT_FOO/BAR/TheNewDirectory/TheNewDirectory. I would therefore check, for the safe side, that it indeed makes sense to create the directory, before doing it.
To create directory, you need to specify full path of new directory using the current folder name:
Dir['/DIRECTORY/PROJECT_*/*/'].each do |f|
FileUtils.mkdir_p "#{f}/TheNewDirectory" if File.directory?(f)
end
I use the following tests in a nanoc rule for compiling various kinds of content (including partials) in multiple directories by matching them with their identically-named layouts.
Now I've added index files to each content dir, but these need the default layout. This obviously works fine if I add an item named 'index:' to the metadata in the 'index.md' files…
---
title: 'This page title'
index: 'y'
---
…but checking for if #item[:index] seems a bit clunky, so I've been trying (well, hacking around) to find a way to omit 'index:' from the metadata and test by nanoc rep name or identifier - see the commented-out if statements in the code below:
layouts = ['layoutone','layouttwo','layoutetc']
layouts.each do |dir|
compile "/#{dir}/*" do
# if item.identifier == "/#{dir}/index/"
# if item.identifier =~ %r{/\w/index/}
# if #item.rep_named(:index)
if #item[:index]
filter :kramdown
layout "default"
elsif #item[:inc]
filter :erb
filter :kramdown
layout "#{dir}"
else
filter :kramdown
layout "#{dir}"
end
end
end
What's wrong with the syntax/logic in my commented-out lines?
Edit:
I was missing the blindingly obvious here: simply add /content/dir_name.md at the same level as /content/dir_name/* to create /dir_name/index.html and /dir_name/*.html, and apply rules to those /content/dir_name.md files.
Did you change nanoc.yaml after nanoc create-site? Because I recall that by default, identifiers in nanoc don't contain the last index part of source file name.
Say, file content/dirA/index.markdown will have identifier /dirA/ or something, and compile to content/dirA/index.html. This may be the reason why your index regex didn't hit.
Yes, a little tricky, but nanoc is great.
update
I found a way to tell the content filename: item.raw_filename.
This document says it is only for binary files, while it also work on text files in my experiment.
# in compile block of Rules
item.identifier
# => "/aaa/"
item.raw_filename
# => "content/aaa.markdown"
I'm looking for a simple, concise example of using the inotify gem to detect a change to a directory.
It lacks examples.
There's an example in examples/watcher.rb.
That link is to aredridel's repo, since it looks like you linked to aredridel's docs, and aredridel is the one who wrote the example.
One of my projects I have used ruby-inotify for monitoring file creation under specific folder using following code
# frozen_string_literal: true
require 'rb-inotify'
# observe indicate folder, trigger event after
module ObserveFiles
def self.observe
watcher = INotify::Notifier.new
directory = CONFIG['xml_folder'] # folder that want to watch
watcher.watch(directory, :create) do |event|
# do your work where
# here, event.name is created file name
# event.absolute_name file absolute path
end
watcher.run
end
end
Use this code like
ObserveFiles.observe
Hope this will help someone.
I've placed a set of .rb files in a directory modules/. Each of these files contains a module. I'm loading all of these files from a separate script with this:
Dir["modules/*.rb"].each {|file| load file }
But then I have to include them, one by one, listing and naming each of them explicitly:
class Foo
include ModuleA
include ModuleB
# ... and so on.
end
I'm wondering if there is some non-explicit one-liner that can accomplish this, a la (pseudocode) ...
class Foo
for each loaded file
include the module(s) within that file
end
# ... other stuff.
end
I've considered actually reading the files' contents, searching for the string "module", and then extracting the module name, and somehow doing the include based on that -- but that seems ridiculous.
Is what I'm trying to do advisable and/or possible?
You can manually define some variable in each of your file and then check for its value while including the file.
For example, module1.rb:
export = ["MyModule"]
module MyModule
end
And the second one, module2.rb:
export = ["AnotherModule", "ThirdModule"]
module AnotherModule
end
module ThirdModule
end
And then just include all of them in your file (just the idea, it may not work correctly):
class Foo
Dir["modules/*.rb"].each do |file|
load file
if export != nil
export.each do { |m| include(Kernel.const_get(m))
end
end
end
I would expect it to be possible since you can place ruby code below class and include is also just a ruby call but you have to think of which module needs to be included where since your code is not the only one that loads and includes modules. And you wil not want to include all modules from the object space in your class.
So i personally would include them by name - you are adding funcionality to a class and by naming each module you document what is being added where.
And if you want this one liner: put a code in each module that adds its name to global list (remembering the disadvantages if using globals at all) and then iterate this list in the class definition to include all of them or part based on a criterium like name or what.