I'm creating my first app in Sinatra and I have problems with logging. I read some topics here about logging in Sinatra and thanks to them I can log requests but I cannot see error stacks in my log file - they show only in console.
Here is what I've got so far:
app.rb
require 'rubygems'
require 'bundler'
Bundler.require(:default, ENV['RACK_ENV'].to_sym)
require 'sinatra/base'
require 'sinatra/config_file'
require 'sinatra/partial'
class App < Sinatra::Base
configure do
enable :sessions, :logging, :partial_underscores, :dump_errors, :raise_errors
log_file = File.new("#{settings.root}/log/#{settings.environment}.log", 'a+')
log_file.sync = true
use Rack::CommonLogger, log_file
set :root, File.dirname(__FILE__)
set :logger_level, :info
set :logger_log_file, File.join(File.dirname(__FILE__), "/log/#{environment}.log")
helpers do
def logger
#logger ||= begin
#logger = ::Logger.new(self.class.logger_log_file)
#logger.level = ::Logger.const_get((self.class.logger_level || :warn).to_s.upcase)
#logger.datetime_format = "%Y-%m-%d %H:%M:%S"
#logger
end
end
end
end
error do
logger.error env['sinatra.error'].message
redirect to('500.html')
end
end
And when I set
get '/' do
raise 'some test error'
end
Stack trace shows only in console. Any ideas what I'm doing wrong?
Related
I am new in ruby on rails and I want to read data from a JSON file from a specified directory, but I constantly get an error in chap3(File name)
Errno::ENOENT in TopController#chap3. No such file or directory # rb_sysopen - links.json.
In the console, I get a message
Failed to load resource: the server responded with a status of 500 (Internal Server Error)
How I can fix that?
Code:
require "json"
class TopController < ApplicationController
def index
#message = "おはようございます!"
end
def chap3
data = File.read('links.json')
datahash = JSON.parse(data)
puts datahash.keys
end
def getName
render plain: "名前は、#{params[:name]}"
end
def database
#members = Member.all
end
end
JSON file:
{ "data": [
{"link1": "http://localhost:3000/chap3/a.html"},
{"link2": "http://localhost:3000/chap3/b.html"},
{"link3": "http://localhost:3000/chap3/c.html"},
{"link4": "http://localhost:3000/chap3/d.html"},
{"link5": "http://localhost:3000/chap3/e.html"},
{"link6": "http://localhost:3000/chap3/f.html"},
{"link7": "http://localhost:3000/chap3/g.html"}]}
I would change these two lines
data = File.read('links.json')
datahash = JSON.parse(data)
in the controller to
datahash = Rails.root.join('app/controllers/links.json').read
Note: I would consider moving this kind of configuration file into the /config folder and creating a simple Ruby class to handle it. Additionally, you might want to consider paths instead of URLs with a host because localhost:3000 might work in the development environment but in production, you will need to return non-localhost URLs anyway.
Rails use the content of file in the controller
#data = File.read("#{Rails.root}/app/controllers/links.json")
I've written a simple plugin that generates a small JSON file
module Jekyll
require 'pathname'
require 'json'
class SearchFileGenerator < Generator
safe true
def generate(site)
output = [{"title" => "Test"}]
path = Pathname.new(site.dest) + "search.json"
FileUtils.mkdir_p(File.dirname(path))
File.open(path, 'w') do |f|
f.write("---\nlayout: null\n---\n")
f.write(output.to_json)
end
# 1/0
end
end
end
But the generated JSON file gets deleted every time Jekyll runs to completion. If I uncomment the division by zero line and cause it to error out, I can see that the search.json file is being generated, but it's getting subsequently deleted. How do I prevent this?
I found the following issue, which suggested adding the file to keep_files: https://github.com/jekyll/jekyll/issues/5162 which worked:
The new code seems to avoid search.json from getting deleted:
module Jekyll
require 'pathname'
require 'json'
class SearchFileGenerator < Generator
safe true
def generate(site)
output = [{"title" => "Test"}]
path = Pathname.new(site.dest) + "search.json"
FileUtils.mkdir_p(File.dirname(path))
File.open(path, 'w') do |f|
f.write("---\nlayout: null\n---\n")
f.write(output.to_json)
end
site.keep_files << "search.json"
end
end
end
Add your new page to site.pages :
module Jekyll
class SearchFileGenerator < Generator
def generate(site)
#site = site
search = PageWithoutAFile.new(#site, site.source, "/", "search.json")
search.data["layout"] = nil
search.content = [{"title" => "Test 32"}].to_json
#site.pages << search
end
end
end
Inspired by jekyll-feed code.
I'm a newbie to this, and can't figure out how to solve this error that I get when attempting to query from the database. The error reads:
rm: cannot unlink 'C:/Users/myName/Documents/GitHub/active_record_lite/lib../cats.db': Permission denied
Error: unable to open database "'C:\Users\myName\Documents\GitHub\active_record_lite'": unable to open database file
By going to "Properties" and viewing the "Security" tab, everything is checked under "Allow" for security, so I assume that the project and all subfiles have full permission (is this correct?).
I have a "cats.db" and "cats.sql" file in the project folder.
This is where I attempt to query from the database:
require_relative 'db_connection'
require 'active_support/inflector'
class SQLObject
def self.columns
cols = DBConnection.execute2(<<-SQL, #table_name)
SELECT
*
FROM
?
SQL
And here is a db_connection.rb file:
require 'sqlite3'
# https://tomafro.net/2010/01/tip-relative-paths-with-file-expand-path
ROOT_FOLDER = File.join(File.dirname(__FILE__), '..')
CATS_SQL_FILE = File.join(ROOT_FOLDER, 'cats.sql')
CATS_DB_FILE = File.join(ROOT_FOLDER, 'cats.db')
class DBConnection
def self.open(db_file_name)
#db = SQLite3::Database.new(db_file_name)
#db.results_as_hash = true
#db.type_translation = true
#db
end
def self.reset
commands = [
"rm '#{CATS_DB_FILE}'",
"cat '#{CATS_SQL_FILE}' | sqlite3 '#{CATS_DB_FILE}'"
]
commands.each { |command| `#{command}` }
DBConnection.open(CATS_DB_FILE)
end
def self.instance
reset if #db.nil?
#db
end
def self.execute(*args)
puts args[0]
instance.execute(*args)
end
def self.execute2(*args)
puts args[0]
instance.execute2(*args)
end
def self.last_insert_row_id
instance.last_insert_row_id
end
private
def initialize(db_file_name)
end
end
Any advice/suggestions welcomed! Thanks!
I have the code that implement csv upload like this:
def Hotel.import(file)
CSV.foreach(file.path, headers: true) do |row|
product = find_by_id(row["id"]) || new
product.attributes = row.to_hash
product.save
end
end
def import
Hotel.import(params[:file])
redirect_to root_url, notice: "Product was successfully Imported."
end
so how do I write rspec test for this?
There are lots of ways to write controller specs. There are many good resources online outlining how to write them in different styles. I suggest starting with the RSpec docs on controller specs:
https://github.com/rspec/rspec-rails#controller-specs
https://www.relishapp.com/rspec/rspec-rails/v/2-14/docs/controller-specs
In general they go something like:
require "spec_helper"
describe ProductsController do
describe "POST #import" do
it "redirects to the home page" do
allow(Hotel).to receive(:import).with("foo.txt")
post :import, file: "foo.txt"
expect(response).to redirect_to root_url
end
it "adds a flash notice" do
allow(Hotel).to receive(:import).with("foo.txt")
post :import, file: "foo.txt"
expect(flash[:notice]).to eq "Product was successfully imported."
end
it "imports the hotel file" do
expect(Hotel).to receive(:import).with("foo.txt")
post :import, file: "foo.txt"
end
end
end
If any one needed model tests for rspec.
require 'rails_helper'
RSpec.describe Product, type: :model do
describe 'import' do
before :each do
#file = fixture_file_upload('data.csv', 'csv')
end
context 'when file is provided' do
it 'imports products' do
Product.import(#file)
expect(Product.find_by(part_number: '0121G00047P').description)
.to eq 'GALV x FAB x .026 x 29.88 x 17.56'
end
end
end
end
I have my Report model:
class Report < ActiveRecord::Base
belongs_to :user
attr_accessible :ready_status, :document
mount_uploader :document, DocumentUploader
def attach( report_file )
self.update_attributes( :document => File.open( report_file ), :ready_status => true )
end
end
This model has attach metod, which i use to save document and other param. Now i want to test that this function works.
/spec/models/report_spec.rb
# encoding: utf-8
require 'spec_helper'
describe Report do
before(:each) do
#user = User.make!
end
...
context "File's saving" do
before(:each) do
#report = #user.reports.create
#csv_report_file = "#{Rails.root}/spec/files/report.csv"
end
it "CSV should be saved" do
csv_report_filename = #csv_report_file.split("/").last
#report.attach #csv_report_file
#report.reload
#report.document.file.filename.should == csv_report_filename
end
end
end
When i try to saving file from /spec/files i get such error:
Report File's saving CSV should be saved
Failure/Error: #report.document.file.filename.should == csv_report_filename
NoMethodError:
undefined method `filename' for nil:NilClass
But when i try another file from another folder (for example "#{Rails.root}/samples/my-report.csv") then my test passes.
How can i fix that?
Oh, i found the answer. Carrierwave doesn't save empty file and i had one. When i added some data in the file (/spec/files/report.csv) my problem has gone.