Ruby double pipe usage - ruby-on-rails

I have a file which have different paths for remote server and local server.
Remote server path:
"/app/public/front-end/public/JSONModels/IdPairing/Text.json"
Local server path:
"public/front-end/public/JSONModels/IdPairing/Text.json"
I basically wanna make sure my app finds correct path for the file regardless of which server I'm at.
So I found something like double pipe ( || ) in Ruby syntax like below:
File.read("/app/public/front-end/public/JSONModels/IdPairing/Text.json" || "public/front-end/public/JSONModels/IdPairing/Text.json")
But it seems like it only reads the first path. How do you make sure it reads the second path if the file is not being found in the first path?
Thanks

A lazy way is:
begin
File.read("/app/public/front-end/public/JSONModels/IdPairing/Text.json")
rescue
File.read("public/front-end/public/JSONModels/IdPairing/Text.json")
end

Why it doesn't work for you:
irb(main):001:0> File.read("some made up name")
Errno::ENOENT: No such file or directory - some made up name
from (irb):1:in `read'
from (irb):1
from /usr/bin/irb:12:in `<main>'
irb(main):002:0> File.read("some made up name" || "Gemfile")
Errno::ENOENT: No such file or directory - some made up name
from (irb):2:in `read'
from (irb):2
from /usr/bin/irb:12:in `<main>'
As you can see, when you try to read a file that doesn't exist, Ruby explodes.
That's what exist? is for.
What you should do
irb(main):003:0> filename = File.exist?("some made up name") ? "some made up name" : "Gemfile"
=> "Gemfile"
irb(main):004:0> File.read(filename)
That's one way to do it, at least.

I would suggest to put those paths into an environment specific config file. Take a look at railsconfig/config on GitHub.
After you have installed the gem, you can add a configuration to config/settings/<RAILS_ENV>.yml like
json_file: /app/public/front-end/public/JSONModels/IdPairing/Text.json
where <RAILS_ENV> can be development, test, production or a custom environment.
And in your code, just
File.read(Settings.json_file)

If you want to try these in sequence, define a list first:
FILES = [
"/app/public/front-end/public/JSONModels/IdPairing/Text.json",
"public/front-end/public/JSONModels/IdPairing/Text.json"
]
Then you can simply open the first one that exists:
path = FILES.find { |f| File.exists?(f) }
File.open(path)
The problem was that "string" || "string" will never work, the first string is logically true and the rest is irrelevant and ignored.

Related

Ruby on Rails copy S3 file with special characters (%C5) in path

I have a problem with my attachment system on web page. I store them on amazon S3 using paperclip. I have an option to copy attachment to new file. Everything works fine until there are polish special characters in title, like: ŁĄKA.jpg. Then I get an error:
Saving error: Appendix Paperclip::Errors::NotIdentifiedByImageMagickError
/Users/michal/.rbenv/versions/2.1.5/lib/ruby/gems/2.1.0/gems/activerecord-4.2.5/lib/active_record/validations.rb:79:in `raise_record_invalid'
/Users/michal/.rbenv/versions/2.1.5/lib/ruby/gems/2.1.0/gems/activerecord-4.2.5/lib/active_record/validations.rb:43:in `save!'
My code:
instance.appendixes.select {|a| a.temporary? && !a.appendix.exists?}.each do |a|
a.appendix = S3File.new(a.s3path)
a.process = false
a.appendix_url = nil
puts "CREATING NEW FILE from (temporary?) appendix: #{a.id}, path: #{a.s3path}, is_public: #{a.is_public}, determine_is_public: #{a.determine_is_public}"
a.is_public = a.determine_is_public
logger.debug("CREATING NEW FILE from (temporary?) appendix: #{a.id}, path: #{a.s3path}, is_public: #{a.is_public}, determine_is_public: #{a.determine_is_public}")
a.save! # bo delayed_job
end
I'm getting error on a.save! when path is like: appendixes/appendixes/242/original/%25C5%2581A%25CC%25A8KA.jpg, but works like charm when it is: appendixes/appendixes/243/original/laka.jpg or another file name without polish letters. Anybody had this kind of problem or have suggestions how to fix it?
Ok, I found what was wrong. I had to replace in a.s3path, the last part with original name (łąka.jpg) and everything works fine. So when I have:
S3File.new(appendixes/appendixes/243/original/łąka.jpg) it works good and finds the correct file on s3 server.

Writing a file to a specific path in ruby taking the file name from excel

I am having some trouble writing a file to a specific path taking the file name from excel. Here is the code which I am using
out_file = File.new (#temp_path/ "#{obj_info[3].to_s}","w")
"#{obj_info[3].to_s}" = sample.txt
The value sample.txt comes from Excel during run time
#temp_path = "C:/Users/Somefolder/"
The error displayed is:
NoMethodError: undefined method `[]' for nil:NilClass
However, if the code is:
out_file = File.new ("#{obj_info[3].to_s}","w")
it successfully creates a file called sample.txt in the default directory. However, I want it to be stored in a specific directory and the file name needs to be passed from Excel.
Any help is much appreciated.
I believe your problem is because there a space between / and "
#temp_path/ "#{obj_info[3].to_s}
and I guess you want to build a path.
My advice is that you use File.join
f_path = File.join(#temp_path,obj_info[3].to_s)
out_file = File.new (f_path,"w")
Let me know if that solved the problem
You have 2 problems:
obj_info is nil so you make an error reading the value from excel, the error you get indicates it is on an array, in the code you published the only thing that's an array is what you read from excel.
Print the contents with p obj_info right before your code to check.
#temp_path and {obj_info[3].to_s} need to be concatenated to make a path.
You can do that with File.join like Mauricio suggests or like this
out_file = File.new ("#{#temp_path}/#{obj_info[3]}","w")
You can drop the to_s in this case.
It would be better if you publish the whole of your script that is meaningful.

Can't access File created by paperclip

Not sure what's the matter here :
file = Rails.root.join(Attachment.last.attachment.url(:original))
# => "/system/attachments/3/original/!my_awesome_pdf.pdf?1359735260"
Then I try and do this :
File.new(file, 'rb')
# => No such file or directory - /system/attachments/3/original/!my_awesome_pdf.pdf?1359735260
Why would that happen? I'm trying to be able to select the file to upload to GroupDocs.com
Ah the problem was that URI's will throw off Ruby from recognizing the name of the file. Removing the URI allows Ruby to open the file.

ruby reading files from S3 with open-URI

I'm having some problems reading a file from S3. I want to be able to load the ID3 tags remotely, but using open-URI doesn't work, it gives me the following error:
ruby-1.8.7-p302 > c=TagLib2::File.new(open(URI.parse("http://recordtemple.com.s3.amazonaws.com/music/745/original/The%20Stranger.mp3?1292096514")))
TypeError: can't convert Tempfile into String
from (irb):8:in `initialize'
from (irb):8:in `new'
from (irb):8
However, if i download the same file and put it on my desktop (ie no need for open-URI), it works just fine.
c=TagLib2::File.new("/Users/momofwombie/Desktop/blah.mp3")
is there something else I should be doing to read a remote file?
UPDATE: I just found this link, which may explain a little bit, but surely there must be some way to do this...
Read header data from files on remote server
Might want to check out AWS::S3, a Ruby Library for Amazon's Simple Storage Service
Do an AWS::S3:S3Object.find for the file and then an use about to retrieve the metadata
This solution assumes you have the AWS credentials and permission to access the S3 bucket that contains the files in question.
TagLib2::File.new doesn't take a file handle, which is what you are passing to it when you use open without a read.
Add on read and you'll get the contents of the URL, but TagLib2::File doesn't know what to do with that either, so you are forced to read the contents of the URL, and save it.
I also noticed you are unnecessarily complicating your use of OpenURI. You don't have to parse the URL using URI before passing it to open. Just pass the URL string.
require 'open-uri'
fname = File.basename($0) << '.' << $$.to_s
File.open(fname, 'wb') do |fo|
fo.print open("http://recordtemple.com.s3.amazonaws.com/music/745/original/The%20Stranger.mp3?1292096514").read
end
c = TagLib2::File.new(fname)
# do more processing...
File.delete(fname)
I don't have TagLib2 installed but I ran the rest of the code and the mp3 file downloaded to my disk and is playable. The File.delete would clean up afterwards, which should put you in the state you want to be in.
This solution isn't going to work much longer. Paperclip > 3.0.0 has removed to_file. I'm using S3 & Heroku. What I ended up doing was copying the file to a temporary location and parsing it from there. Here is my code:
dest = Tempfile.new(upload.spreadsheet_file_name)
dest.binmode
upload.spreadsheet.copy_to_local_file(:default_style, dest.path)
file_loc = dest.path
...
CSV.foreach(file_loc, :headers => true, :skip_blanks => true) do |row|}
This seems to work instead of open-URI:
Mp3Info.open(mp3.to_file.path) do |mp3info|
puts mp3info.tag.artist
end
Paperclip has a to_file method that downloads the file from S3.

Why can't Rails find this custom .yml file?

In applications.rb I added this:
SOME_CONFIG = = YAML.load_file(File.expand_path('../some_config.yml', __FILE__))
I placed the file in:
/some/folder/myapp/config/some_config.yml
Then when I run 'rails server' I get an error:
.. in 'initialize' : no such file or directory /some/folder/myapp/config/some_config.yml (Errno::ENDENT) .... 'open' .... 'load_file' ....
Is this a permissions issue?
I don't believe this to be a permissions issue.
1) Double check your spelling to make sure there are no typos.
2) Try reading another file, and see if it works.
3) Try: YAML.load_file(File.join(Rails.root, 'config', 'some_config.yml')) (Your error message shows that the issue is not in expanding the filename, but you never know).
4) Can you access it from the console?
my_data = HashWithIndifferentAccess.new( YAML.load(File.read(File.expand_path('../../some_file.yml', __FILE__))) )
now due to HashWithIndifferentAccess, you can get data in any of the given below syntax
my_data[:some_key] or my_data['some_key']

Resources