Ruby glob: Exclude dir and file - ruby-on-rails

For the import of my Sass files, I use sass-rails' (https://github.com/rails/sass-rails) glob feature. It says
Any valid ruby glob may be used
I want to exclude a directory and a file when using #import. Any ruby code using blocks don't work in this scenario. But even trying to exclude a single file doesn't work the way I want.
Consider this tree structure
/_bar.scss
/_foo.scss
/all.scss
For example, I want to exclude the file _foo.scss. I read here https://stackoverflow.com/a/27707682/228370, using a ! you can negate a pattern.
I tried the following:
Dir["{[!_foo]}*.scss"]
=> ["all.scss"]
But this skips _bar.scss. When looking into the glob reference of Ruby (http://ruby-doc.org/core-2.2.0/Dir.html#method-c-glob) it becomes clear why:
[set]
Matches any one character in set. Behaves exactly like character sets in Regexp, including set negation ([^a-z]).
(apparently, negation can be achieved with ! AND ^)
Because we have an underscore in our pattern, every file with an underscore gets excluded.
But what would be the solution, to exclude a fixed file?

There's probably a regex way of doing it. But if you're talking about one specific file, it might be easier to just do:
Dir["*.scss"].reject { |i| i == '_foo.scss' }

Related

Can I expand glob in context of a macro?

let's say that I want to generate multiple rules in a macro based on repository contents - something like:
def mymacro(dests) :
for d in dests:
myrule(name = d, ...)
# in a BUILD:
mymacro(dests = glob(["some/pkg/path/**"]))
So far, I've always gotten an empty list when I try this (although the path has many entries). Is such a thing possible or am I doing something wrong?
Using glob like that should work fine. Glob also works within a macro (though you have to do native.glob(...))
The glob pattern is probably just not matching anything. Glob will happily return an empty list if the pattern matches nothing (you can pass allow_empty=False to change that behavior).
Note that glob will not traverse into subpackages. So with your example some/pkg/path/**, if there's a build file in one of the subdirectories (some/BUILD, some/pkg/BUILD, some/pkg/path/BUILD, etc) then glob won't looking for anything in that subdirectory. To make files visible from one package to another, typically you'll have a filegroup (maybe with its own glob) in one package that another package depends on.

Define several modules in a single file

Is it possible to merge multiple module definitions in a single file and avoid possible clashes with Rails autoloading ?
Thanks !
I am not sure I understood how this would help “to avoid possible clashes with Rails autoloading”, but the answer is “yes”: one might define as many modules, classes, constants and whatever is defineable in the single file.
Ruby has no restriction on the relation between file names and modules/classes names. One might define modules A1 and A2 in file b.rb. Standard lib/namespace/class_name.rb convetion is the convention only, as soon as file is required, it’s content is being loaded.

rename file name with eloquent way

File.rename(blog_path + '/' + project_path, File.expand_path(topic_name, blog_path))
I use these code to rename ruby file name, but I think there is a better way to write this functionality with less code since it includes blog_path two times.
The code is OK, but I think there is no need to expand_path here - this method creates an absolute path from the the relative one.
Also, it is good to use File.join to create a path instead just concatenate it with slash - it will be completely OS independent. So I would write your code like this:
File.rename(File.join(blog_path, project_path), File.join(blog_path, topic_name))
Or if you want to get rid of doubled blog_path, change working directory before doing a rename:
Dir.chdir(blog_path)
File.rename(project_path, topic_name)
More info on working with files and directories in Ruby you can find in the article: Ruby for Admins: Files and Directories.

Ruby: Using a regular expression to find and open a file based on its filename?

I am trying to test the contents of a file that is generated from code. The problem is that the full name of the file is based on a timestamp abc123_#{d.strftime('%Y%m%d%I%M%S')}.log
How could I use File to find this file and read it? I tried doing File.exists?() with a regular expression as the parameter but that didn't work.
I found this in another question on stackoverflow:
File.basename(file_path).match(/_.*(css|scss|sass)/)
How would I be able to use that in my case where the file is located in mypublic folder?
ANSWER
So the two answers below both work and I used a combination of them.
Dir['public/*.log'].select { |f| f =~ /purge_cc_website/}
The * acts as a wildcard that is sort of a regular expression in itself. After that you filter the array using an actual regex.
Dir[] takes a file glob so, if your pattern isn't too complicated, you can just do:
Dir['public/abc123_*.log']
More glob info here.
File is for reading one file. You need to use Dir to find files by name.
files = Dir['*'].select {|x| x =~ /_.*(css|scss|sass)/ }
If you just want the last file in the case of dups:
files = Dir['*'].select {|x| x =~ /_.*(css|scss|sass)/ }.sort.last

Rails: Hash#to_json - split over multiple lines?

I'm having a slight annoyance with the javascript_I18n plugin, which generates js-friendly versions of the I18n translation tables, so that you can localise your javascript. It all works fine, but it works by calling to_json on each locale's translations hash and outputting the results into a file. When you call to_json on a hash the resulting string is all a single lne, which means you end up with files with an enormous line at the end.
This in turn is stopping git from being able to merge any changes, because the merge works on a line by line basis and can't deal with a single massive line with changes in the middle somewhere. It's not a massive problem because i can always just re-generate the js-friendly translation file with a rake task that comes with the plugin (which replaces the mid-merge file with a brand new one which i can just commit in), but it's just a bit annoying. It occurred to me that if the json was output on different lines, instead of all the same line, then it wouldn't be a problem, and it wouldn't even make the file that much bigger, just inserting two characters (\n) per line.
Before i try and hack the resulting string with a gsub to split it onto seperate lines, is there a nicer way to call to_json on a hash and output the results onto seperate lines? Or a nicer way to solve this problem generally? (i can't find much useful in the documentation for javascript_I18n).
Grateful for any advice - max
Not to answer you question, but to give a suggestion:
It would probably be easier to just ignore all the generated js translation files.
This is because even if you separate the translation into multiple lines, there are still chances of merge conflicts, which you probably already resolved once in your yaml file.
I would set it up this way:
1). gitignore all the js translation files.
2). In ActionController, add a before filter to generate the js files automatically on each load in development mode only.
3). Tweak your deploy.rb file to generate the js files after code update.
No more merge conflicts! (at least for js translation files) :D
Aaron Qian

Resources