Simple SSH test Rails - ruby-on-rails

I am simply trying to list the directories after I ssh into a remote machine in my rails app but I am not getting the desired output, what is am I overlooking? The host is an IP.
controller-
def index
#ssh_test = Net::SSH.start( :host =>'xx.x.xx.xx',:user => 'name', :password => 'secret' ) do |ssh|
result = ssh.exec!('ls')
puts result
end
end
gemfile-
gem 'net-ssh'
view
<h2><%= #ssh_test %></h2>
Shouldn't the current directories directories print to my view? Thanks for your attention.
UPDATE
Here is updated progress, still don't seem to fully grasp this.
before_filter :set_ssh, :only => [:index]
def index
#ssh_dir = Net::SSH.start( #host, #user, :password => #password ) do |ssh|
result = ssh.exec!('ls')
end
def set_ssh
#host = 'xx.x.xx.xx'
#user = 'user'
#password = 'password'
end
view-
<h1><%= #ssh_dir( host, user, password).inspect %></h1>

You need to return the result and the way you're calling start is incorrect, try this:
def index
#ssh_test = Net::SSH.start('xx.x.xx.xx','name', :password => 'secret' ) do |ssh|
result = ssh.exec!('ls')
result
end
end
This is the correct way to call start in version 2 of net-ssh according to: http://net-ssh.github.com/net-ssh/
EDIT: Answering where to put your config.
If the ssh server you're going to use is fixed for all environments then I'd probably just put it in an initializer:
config/initializers/my_ssh_config.rb
which would have:
$SSH_HOST = 'xx.x.xx.xx'
$SSH_USERNAME = 'name'
$SSH_PASSWORD = 'secret'
Note, personally I would not store the username and password in the config, but maybe try that first just to get it working. (I'd generally make this an env var and do this $SSH_PASSWORD = ENV['SSH_PASSWORD'] etc)
Then your controller action would look like:
def index
#ssh_test = Net::SSH.start($SSH_HOST, $SSH_USERNAME, :password => $SSH_PASSWORD) do |ssh|
result = ssh.exec!('ls')
result
end
end
You could also add this to your environment files (e.g. test.rb, development.rb).

Related

rack-affiliates gem with localhost

I'm messing with Rack::Affiliates but I don't know if it works with the domain localhost in development environment.
1º This is my config in application.rb file:
config.middleware.use Rack::Affiliates, {:param => 'aff_id', :ttl => 6.months, :domain => '.localhost'}
2º I send a email with a link and param aff_id something like:
<%= link_to "accept invite", new_user_registration_url(:aff_id => #user.id) %>
3º In root action:
def index
if request.env['affiliate.tag'] && affiliate = User.find_by_affiliate_tag(request.env['affiliate.tag'])
logger.info "Halo, referral! You've been referred here by #{affiliate.name} from #{request.env['affiliate.from']} # #{Time.at(env['affiliate.time'])}"
else
logger.info "We're glad you found us on your own!"
end
respond_to do |format|
format.html
end
end
I'm getting the message on console:
We're glad you found us on your own!
What am I doing wrong?
Thanks!
Did you remember to include config.middleware.use Rack::Affiliates in your config/application.rb file?
If not, add it and see what happens.
Otherwise you can try debugging by changing the if statement to:
if request.env['affiliate.tag']
logger.info "request.env['affiliate.tag'] = #{request.env['affiliate.tag']}"
else
logger.info "We're glad you found us on your own!"
end
This should tell you if the affiliate.tag is getting set and if so to what value.
It's all due to User.find_by_affiliate_tag. have you any column named affiliate_tag.
If your are inviting using this link <%= link_to "accept invite", new_user_registration_url(:aff_id => #user.id) %> where you are using #user.id as aff_id.
So you have to use User.find_by_id instead of User.find_by_affiliate_tag
Final code snippet of exmaple contoller will look like
class ExampleController < ApplicationController
def index
str = if request.env['affiliate.tag'] && affiliate = User.find_by_id(request.env['affiliate.tag'])
"Halo, referral! You've been referred here by #{affiliate.name} from #{request.env['affiliate.from']} # #{Time.at(env['affiliate.time'])}"
else
"We're glad you found us on your own!"
end
render :text => str
end
end

Change ActionMailer Email URL Host Dynamically

In my application.html.erb I have <%= render #objects %>, that renders a bunch of _object.html.erb partials, each with a <%= link_to(object) %>. I render the same single partial <%= render #object %> in the email that is being sent when somebody leaves a comment but I want link to start with a server url.
I have tried everything:
link_to(object)
url_for(object)
before_filter :set_mailer_host
def set_mailer_host
ActionMailer::Base.default_url_options[:host] = request.host_with_port
end
default_url_options[:host] = "example.com"
def default_url_options
{ host: 'example.com' }
end
...Nothing works. With or without :only_links
In the end, I just built a dumb helper that prepends hostname to links:
# application_controller.rb
before_filter { App::request=request }
# application_helper.rb
def hostify obj
"http://#{App::request.host_with_port}#{url_for obj}"
end
# _object.html.erb:
<%= link_to obj.title, hostify(object) %>
Is there a normal way to do this?
I can't really tell what you're trying to link to or what 'obj' is referring to, but you can do something like:
link_to obj.title, {:host => 'example.com'}
or
link_to obj.title, {:controller => 'store', :action => 'view_cart', :host => 'example.com'}
Okay after spending some time with it, I think I am starting to figure it out.
You got to use restful routes then you can set default_url_options[:host] = host in the Mailer action and :only_path to true in default_url_options for other controllers. Plus :locale.
And in the view I have: objects_url(object)
Since I have different hostnames, I pass request.host_with_port as a parameter from a controller to the Mailer when sending mail.
link_to doesn't accept parameters and url_for() can only build url from parts of it.
def url_options
{ domain: 'example.com' }
end
Or better to merge in case you use other options:
def url_options
{ domain: 'example.com' }.merge(super)
end

Heroku deployment of Ruby on Rails Application with custom functions

I have designed a ruby on rails 3.2 application in which I have a Users model. I wrote a custom function in order to authenticate userName and password through another mobile application.
Everything is working fine in localhost and I am able to authenticate from the mobile application. So, I went a step further and deployed it in Heroku. Now the authenticate function is not working.
In my Gem File I have included the following:
group :production do
gem 'pg'
end
group :development do
gem 'sqlite3'
end
In my users_controller.rb I have written my custom authenticate function:
# http://wgo-ror.herokuapp.com/users/authenticate?userName=ramy&password=123456
def authenticate
usr = params[:userName]
pwd = params[:password]
#getUser = User.where("userName = ? AND password = ?", params[:userName], params[:password])
if (#getUser!=[])
respond_to do |format|
format.html { render :json => {:Success => true, :Data => #getUser}, :callback => params[:callback] }
format.json { render :json => {:Success => true, :Data => #getUser}, :callback => params[:callback] }
end
else
respond_to do |format|
format.html { render :json => {:Success => false, :Data => #getUser}, :callback => params[:callback] }
format.json { render :json => {:Success => false, :Data => #getUser}, :callback => params[:callback] }
end
end
end
I have also written another custom function called saveUser. This particular function is working fine even after I deployed it to heroku.
# http://wgo-ror.herokuapp.com/users/saveUser?id=1&userName=yrkapil&password=123456&email=yrkapil#gmail.com
def saveUser
#user = User.find(params[:id])
#user.update_attributes(:userName => params[:userName], :password => params[:password], :email => params[:email] )
end
In my routes.rb I have included the following:
match 'users/authenticate' => 'users#authenticate', :as => :authenticate
match 'users/saveUser' => 'users#saveUser', :as => :saveUser
resources :users
resources :festivals
root :to => 'users#index'
Am I missing something or is it because of postgresql? I am not getting any clue of how to do it. Please help me Guys. I really need to get this working. Thanks in advance!
You probably have a case issue in your userName column.
You created your userName column with something like this:
t.string :userName
and that would cause Rails to send SQL like this to the database:
create table users (
"userName" varchar(255),
...
)
Note the quotes around the userName identifier; the quotes make that column name case sensitive. But, unquoted identifiers in PostgreSQL are folded to lower case (the SQL standard says upper case but that's immaterial here). Essentially the quotes mean that you always have to say "userName" when referring to the column, you can't say username or userName or anything else.
SQLite, on the other hand, has a very loose interpretation of SQL so you can do things like this:
create table t ("userName" text);
insert into t values ('x');
select * from t where username = 'x';
and everything will work.
Every time you let ActiveRecord build the column name, it will quote it so this:
#user.update_attributes(:userName => params[:userName], :password => params[:password], :email => params[:email] )
will end up doing this:
update users
set "userName" = ...
and everyone is happy. However, you are using an SQL fragment right here:
#getUser = User.where("userName = ? AND password = ?", params[:userName], params[:password])
without quoting your userName identifier so PostgreSQL is probably complaining about an unknown column. If you did this:
#getUser = User.where('"userName" = ? AND password = ?', params[:userName], params[:password])
you'd have better luck. Or you could do this:
#getUser = User.where(:userName => params[:userName], :password => params[:password])
or this:
#getUser = User.where(:userName => params[:userName]).where(:password => params[:password])
You should do two things:
Stop using mixed case column names. Lower case column and table names with underscores to separate words is the usual practice with PostgreSQL (and Ruby and Rails for that matter).
Stop developing on top of SQLite and start developing on top of PostgreSQL if you're deploying to Heroku. Your development stack and your deployment stack should be the same (or as close to identical as possible).

How do you delay a rendering job?

This method works OK, but if I add delayed_job's handle_asychronously, I get can't convert nil into String:
def onixtwo
s = render_to_string(:template=>"isbns/onix.xml.builder")
send_data(s, :type=>"text/xml",:filename => "onix2.1.xml")
end
handle_asynchronously :onixtwo
So rendering with delayed job is clearly having a problem with params being passed. I've tried putting this job in a rake task but render_to_string is a controller action - and I'm using a current_user variable which needs to be referenced in the controller or view only. So... what's the best way to delay a rendering job?
/////////update////////
Given that I'm currently pair-programming with a toddler, I don't have the free hands to investigate additional class methods as wisely recommended in the comments - so as a quick and dirty I tried this:
def onixtwo
system " s = render_to_string(:template=>'isbns/onix.xml.builder') ; send_data(s, :type=>'text/xml',:filename => 'onix2.1.xml') & "
redirect_to isbns_path, :target => "_blank", :flash => { :success => "ONIX message being generated in the background." }
end
Why doesn't it work? No error message just no file produced - which is the case when I remove system ... &
For what it's worth, this is what I did, bypassing render_to_stream entirely. This is in /lib or app/classes (adding config.autoload_paths += %W(#{config.root}/classes into config/application.rb):
#classes/bookreport.rb
# -*- encoding : utf-8 -*-
require 'delayed_job'
require 'delayed/tasks'
class Bookreport
# This method takes args from the book report controller. First it sets the current period. Then it sorts out which report wants calling. Then it sends on the arguments to the correct class.
def initialize(method_name, client, user, books)
current_period = Period.where(["currentperiod = ? and client_id = ?", true, client]).first
get_class = method_name.capitalize.constantize.new
get_class.send(method_name.to_sym, client, user, books.to_a, current_period.enddate)
end
end
#app/classes/onixtwo.rb
require 'builder'
class Onixtwo
def onixtwo(client_id, user_id, books, enddate)
report_name = "#{Client.find_by_id(client_id).client_name}-#{Time.now}-onix-21"
filename = "#{Rails.root}/public/#{report_name}.xml"
current_company = Company.where(:client_id => client_id).first
File.open(filename, "w") do |file|
xml = ::Builder::XmlMarkup.new(:target => file, :indent => 2)
xml.instruct!(:xml, :version => "1.0", :encoding => "utf-8")
xml.declare! :DOCTYPE, :ONIXMessage, :SYSTEM, "http://www.editeur.org/onix/2.1/03/reference/onix-international.dtd"
xml.ONIXMessage do
xml.Header do
#masses of Builder code goes here...
end
end #of file
xmlfile = File.open(filename, "r")
onx = Onixarchive.new(:client_id => client_id, :user_id => user_id)
onx.xml = xmlfile
onx.save!
end #of method
handle_asynchronously :onixtwo
end #of class
Called from the view like this:
= link_to("Export to ONIX 2.1", params.merge({:controller=>"bookreports" , :action=>:new, :method_name => "onixtwo"}))
Via a controller like this:
class Books::BookreportsController < ApplicationController
#uses Ransack for search, hence the #q variable
def new
#q = Book.search(params[:q])
#books = #q.result.order('pub_date DESC')
method_name = params[:method_name]
Bookreport.new(method_name, #client, #user, #books)
redirect_to books_path, :flash => {:success => t("#{method_name.to_sym}").html_safe}
end
end

Twitter gem not working from controller in Rails

I've been using the Twitter gem in my latest Rails app, and so far have had no problems. I've registered the app, have set the API tokens in config/initializers/twitter.rb, and have tested that it works in a custom rake test that requires the gem. The problem, however, is that when I try to send a tweet form a controller, nothing happens. My initializer looks like so:
require 'twitter'
Twitter.configure do |config|
config.consumer_key = '###'
config.consumer_secret = '###'
config.oauth_token = '###'
config.oauth_token_secret = '###'
end
The ### are filled in correctly in my app, obviously. In my rake file, I require the gem at the top of the file, and am then able to send a test tweet with Twitter.update(tweet) however, the same syntax does not work from my controllers.
What am I doing wrong here? Do I need to re-initialize the gem from the controller?
After some tinkering, this is the simple solution:
#twitter = Twitter::Client.new
#twitter.update(tweet)
Adding that to my controller method worked perfectly, since the Twitter client had already been authenticated when the app started. This is the app sending out tweets, by the way, not users sending tweets through the app, so I didn't need to re-authenticate.
I am also using the Twitter gem and I use and authorizations controller for my oath, direct messages controller for Twitter DMs, and ajax on the front. The AppConfig is just a yml file that has my creds in it.
authorizations_controller.rb
class AuthorizationsController < ApplicationController
def new
set_oauth
render :update do |page|
page.redirect_to #oauth.request_token.authorize_url
end
end
def show
#oauth ||= Twitter::OAuth.new(AppConfig['consumer']['token'], AppConfig['consumer']['secret'])
#oauth.authorize_from_request(session['rtoken'], session['rsecret'], params[:oauth_verifier])
session['rtoken'] = nil
session['rsecret'] = nil
session['atoken'] = #oauth.access_token.token
session['asecret'] = #oauth.access_token.secret
redirect_path = session['admin'] ? admin_tweets_path : root_path
redirect_to redirect_path
end
end
direct_messages_controller.rb
class DirectMessagesController < ApplicationController
before_filter :authorize
def create
#client.update("##{AppConfig['user']} #{params[:tweet][:text]}")
render :update do |page|
page.replace_html 'tweet_update', "Your tweet has been sent to #{AppConfig['user']} and should be updated momentarily."
end
end
end
view.html.haml
#tweet_update
- form_remote_tag :url => direct_messages_url, :method => :post, :loading => "$('tweet_update').hide();$('loading').show()", :complete => "$('tweet_update').show();$('loading').hide()" do
%div{:class => "subheader float_left"}Tweet to Whoever
- if session_set?
%input{:type => "image", :src=>"/images/sendButton.jpg", :class =>"float_right", :style=>"margin-bottom: 4px"}
- else
%div{:class => "float_right", :id => "twitter_login_button"}= link_to_remote image_tag('twitter-darker.png'), :url => new_authorization_url, :method => :get
.float_clear
#tweetbox_bg
- textarea_options = {:id => "tweetbox", :style => "overflow: auto", :rows => "", :cols => ""}
- textarea_value = nil
- unless session_set?
- textarea_options.merge!(:disabled => "disabled")
- textarea_value = "Please login to tweet Whoever!"
= text_area_tag 'tweet[text]', textarea_value, textarea_options
My before filter 'authorize' just checks session:
def authorize
session_set? ? set_client : redirect_to(new_authorization_url)
end
Hope this helps.

Resources