I have created a ruby on rails application and would like to automate the creation of new model instances. I am currently using python scripts to log information on many machines and would like to find a way to send these log results to the rails server. I need to populate the forms with the contents of my logs in order to generate the associated database entries.
Is there an easy way to send HTTP Post requests that contain the log attributes I want in order to create these new model instances and database entries?
require "net/http"
require "uri"
uri = URI.parse("http://example.com/search")
# Shortcut
response = Net::HTTP.post_form(uri, {"q" => "My query", "per_page" => "50"})
http://www.rubyinside.com/nethttp-cheat-sheet-2940.html
Related
I am using the Apartment gem to switch the tenant (database) being used for a multi tenancy Rails application.
In my server logs I would like to output the current tenant (database) being used for every single line in the log file.
When I do rails s the server never actually starts with the code below that is in the initializers directory. The server just hangs... so odd. No error message and no running server. If I take out #{Apartment::Tenant.current} below everything is fine... but... I really want to know the current tenant (database) in my log files.
/initializers/log_formatting.rb:
class ActiveSupport::Logger::SimpleFormatter
def call(severity, time, progname, msg)
"#{Apartment::Tenant.current} #{msg.strip} (pid:#{$$})\n"
end
end
Any ideas on how to get the current tenant (database) being used output to every line of my log file?
Thank you!
I would suggest you to use log_tags.
From the rails documentation :
config.log_tags accepts a list of: methods that the request object responds to, a Proc that accepts the request object, or something that responds to to_s. This makes it easy to tag log lines with debug information like subdomain and request id - both very helpful in debugging multi-user production applications.
You can add this configuration in application.rb or production.rb whichever fits your need.
For ex: config.log_tags = [ :subdomain, :request_id, lambda { |request| request.headers["tenant_name"] } ]
Note: In case you are adding this for development environment and you are running on your_subdomain.localhost:3000 then subdomain won't be present as localhost doesn't support subdomains. There are some workarounds like modifying /etc/hosts file but i won't recommend it. The more cleaner solution is to use your_subdomain.lvh.me:3000
I need to read the content of a website, and save HTML of a part of this page.
For example, let's say I want to get only the description of an athlete on this page : https://www.olympic.org/usain-bolt : the section.text-content element.
How can I do in Rails to store that HTML in my database, to be able to provide it later via an API?
Anyone have a clue about this?
You can get the description easily openning the url, parsing the html and accessing the element you pointed, like:
require 'nokogiri'
require 'open-uri'
url = 'https://www.olympic.org/usain-bolt'
doc = Nokogiri.HTML(open(url))
puts doc.css('section.text-content').text
As you already have the data then you need a model where to store, you can create a new one, just as example called Athlete, using the rails generate command and migrate, like
$ rails g model Athlete description:text
$ rails db:migrate
The description is a text data type attribute, which allow you to store large texts, as the description.
Then you need to insert it, or update it. You can create a new record, and then update it. In the rails console, just:
Athlete.create
This will create a new athlete without description, but necessary to get it by its id. After that you can create a task, in the lib/tasks folder, you can create a file with .rake extension and add your code, using the way to create a task, like:
require 'nokogiri'
require 'open-uri'
namespace :feed do
desc 'Gets the athlete description and insert it in database.'
task athlete_description: :environment do
url = 'https://www.olympic.org/usain-bolt'
doc = Nokogiri.HTML(open(url))
description = doc.css('section.text-content').text
Athlete.find(1).update description: description
end
end
You have the libraries, get the data, and update to the record using ActiveRecord, you can easily run:
rails feed:athlete_description
# or
rake feed:athlete_description
Nokogiri might be able to do what you need by way of CSS selectors.
If not, you can use Net:HTTP to get the page contents into a local variable, then you can use string manipulation to find the piece you want and store it. Unfortunately, I don't think there's any straightforward way to select that element specifically with this method.
I created a small application that generates reports (mainly PDFs) from an sqlite3 database exported from GNUCash. I separated the app with a possibility of sharing it with other VFW posts that are currently using GNUCash or stuck with a paper general ledger. I call it a quasi API in that most reports can be generated in both HTML and PDF or it can just send data. Before I separated it, I had tried a multiple database approach, adding the sqlite3 database to my database.yaml along with my main postgresql database. It worked but that made the possibility of sharing difficult and I was a little skeptical about the approach.
All is fine with PDFs (prawn generated). I use RestClient to get the reports from the pdf server running on the same machine on a different port. For example, to generate a General Ledger this controller get action is called:
def ledger_pdf
resp = RestClient.get "http://localhost:8600/ledgers/#{params[:id]}/ledger_pdf"
send_data resp.body, filename: "Ledger#{params[:id]}",
type: "application/pdf",
disposition: "inline"
end
On the pdf server, this action responds
def ledger_pdf
pdf = Pdf::Ledger.new(view_context,params)
send_data pdf.render, filename: "Ledger#{params[:id]}",
type: "application/pdf",
disposition: "inline"
end
Getting the HTML version became a little more challenging! On the pdf server I have a one page menu that lists all the reports available, some by date and others with a collection route. This was for the 'sharing' version where someone only needs the reports and does not have another rails application that does other stuff. The server could be stand alone running on some box.
Rather then getting the data and creating a page on the main application from the data, I got the menu from the pdf server in an iframe tag. I though this was working great when I discovered that, in a view:
<iframe src="http://localhost:8600/ledgers/" width="100%" height="100%" id="rails_iframe">error!</iframe>
was calling localhost:8600 on my machine (which was running a development version and fooled me into thinking it was working!) rather than on the production server. After some researching I discovered that you can't do that. I guess the RestClient call to localhost:8600 is hidden from the browser, but the iframe call is not.
I guess I can get the HTML versions using the same RestClient approach and return text/html and use nokogiri to get the body/html and yield it somehow, if I knew how to do that.
The html.slim is really simple and I could just duplicate it on my main server after getting the data, but then I'd have two code bases to maintain.
Another approach would be to make it a real API and make it public so that the iframe approach would work, something I was trying to avoid (authentication and all that).
I guess my question is, does someone have another approach or can refine or give me pointers on my approaches.
You just need to add another action to your 'pdf' server which will render menu:
def menu
render json: {first: 'first/report', second: 'second/report'}
end
And then just fetch that menu from your main server (which is facing users):
def menu
resp = RestClient.get ...
# parse resp.body to get menu structure
# convert JSON response from pdf server to HTML with your ERB template
#menu_items = ...
end
Then just have route on your main server to pass information from collection server as well, something like:
get "reports/:collection/:date/:report", to: 'reports#fetch'
# then in your controller
def fetch
resp = RestClient.get "...#{params[:collection]}/#{params[:date]}/#{params[:report]}
...
end
Personally, I wouldn't use Rails server for pdf generation. I would've just used cron script which would run Ruby script for PDF generation, and then I would just upload them to S3 or some other cloud storage. My Rails server would've just return the link for that S3 file.
How can I use Rethinkdb's change feed in a webapp, see http://www.rethinkdb.com/docs/changefeeds/ruby/ ? I currently use Ruby on Rails. I've tried Googling 'rethinkdb "change feed" rails' and 'rethinkdb "change feed" websocket'
I would like to display updates on a webpage to a RethinkDB table with lowest latency as possible.
RethinkDB is meant to be used from the server (from Rails) and not from the client. It's really important to understand this! If you have a listener on your data (a changefeed), then hose changes will get routed to your Rails app.
If you want to add to query RethinkDB from the front-end (from the browser), you might be interested in these two projects:
https://github.com/mikemintz/rethinkdb-websocket-client
https://github.com/mikemintz/rethinkdb-websocket-server
Once these changes are routed to your application, then you can do with them as you wish. If what you want to do is route those changes to the front-end to just show the users these changes, you can just send them through a web socket. Faye is a really good library to do this.
This is how this would look like. In your ruby code, you would add something like this:
# Add Faye
App = Faye::RackAdapter.new MessageApp, mount: "/faye"
# Changefeed listener
r.table("messages").changes.em_run(Conn) do |err, change|
App.get_client.publish('/message/new', change["new_val"])
end
Basically, whenever there's a change in the messages table, send the new value over the web socket. You can take a look at the full example (with front-end code) here:
https://github.com/thejsj/ruby-and-rethinkdb/
And here is the Ruby file:
https://github.com/thejsj/ruby-and-rethinkdb/blob/master/server/main.rb
RethinkDB seems to not support complex client authentication (auth token is shared amongst all clients), so you can't do that client-side from Javascript.
But you can create a pipeline: run websocket on your server, which will fetch records from RethinkDB and pass it to clients. Using em-websocket it will look something like this:
require 'em-websocket'
require 'rethinkdb'
include RethinkDB::Shortcuts
EventMachine.run do
#clients = []
#cursor = r.table("authors").changes.run
EM::WebSocket.start(:host => '0.0.0.0', :port => '3001') do |ws|
ws.onopen do |handshake|
#clients << ws
end
ws.onclose do
#clients.delete ws
end
#cursor.each do |document|
#clients.each{|ws| ws.send document}
end
end
end
I have several api's that I am integrating with and need to call in various parts of my application.
What is the way to store the keys, the user/password, or token information, say, a configuration file and then how do I call them for use in other parts of the application?
Thanks.
Just to keep this question up-to-date, there is a new way to do this in Rails 4.1:
From the Rails guides:
Rails 4.1 generates a new secrets.yml file in the config folder. By default, this file contains the application's secret_key_base, but it could also be used to store other secrets such as access keys for external APIs.
You can store usernames/passwords and similar configuration information in mechanisms that rails already uses; you can either stuff the configuration data right into your environment configuration files (where production, testing, and development are configured), or you could use your own mechanism and:
require "yaml"
config_hash = YAML::load_file("/path/to/your/config.yaml")
Easiest is to store the info as constants in your various environment files. That way you can use different accounts for development, production, etc.
# Eg
# development/environment.rb
....
API_1_USER = "user101"
API_1_PW = "secret!"
Alternative is to create a yaml file, then read it when your app signs in to an api. This is the style used by rails itself with the config/databse.yml file
ADDED
You can also store as a constant using a hash or nested hash.
# Eg
# development/environment.rb
....
API_1 = {"user" => "user101", "pw" => "secret!"}
API_2 = {"user" => "user102", "pw" => "double_secret"}
# or nested hashes
API_KEYS = {
"api_1" => {"user" => "user101", "pw" => "secret!"},
"api_2" => {"user" => "user102", "pw" => "double_secret"}}
# using them in another file:
foo.signin(API_1['user'], API_1['pw'])
# or
foo.signin(API_KEYS["api_1"]['user'], API_KEYS["api_1"]['pw'])
# note, I use string constants instead of symbols to save vm (since the hash is
# not referenced more than once or twice). You could also use
# symbols as the keys, especially if the hash will be referenced often:
API_1 = {:user => "user101", :pw => "secret!"}
Check out Configatron, it's pretty awesome and can be used exactly for this purpose.