Rails - Render Ajax inside a loop - ruby

I'd like to update several single table cell in my view with ajax.
Is there a chance to run the uptime partial several times during the loop?
Currently the loop iterates over all given records but the partial runs once.
def CheckUptimes
require 'net/ssh'
#username = "updater"
#password = "üqwlp+ß$2"
#cmd = "uptime"
#items = Item.all.where("(category = 'Ubuntu 14 LTS')")
#items.each do |ci|
#hostname = ci.name
begin
ssh = Net::SSH.start(#hostname, #username, :password => #password)
#uptime = ssh.exec!(#cmd)
ssh.close
#uptime = #uptime.strip
ci.update_attributes(:uptime => #uptime)
respond_to do |format|
format.html
format.js { render :partial => "uptime", :locals => { :id => ci.id, :uptime => #uptime } }
end
rescue
puts "Unable to connect to #{#hostname} using #{#username}/#{#password}"
end
end
end

If I understand well, I think you could save in two instance variables (Arrays) which hostnames were able to to connect and which not, and then in checkuptimes.js.erb you can show which ones are ok with render collection
Something like this
#con_ok=#con_ko=[]
#items.each do |ci|
#hostname = ci.name
begin
ssh = Net::SSH.start(#hostname, #username, :password => #password)
#uptime = ssh.exec!(#cmd)
ssh.close
#uptime = #uptime.strip
ci.update_attributes(:uptime => #uptime)
con_ok<<ci.id
rescue
con_ko<< ci.id
end
respond_to do |format| ## Not necessary ##
format.html
format.js
end
in checkuptimes.js.erb
$("#mydiv").html("<%= escape_javascript(render 'uptime', collection: #con_ok)%>");
in this example, the partial uptime will be rendered as many times as items contains #con_ok, with a local variable con_ok with the the item in the array (id)

Related

The action 'Search' cannot be found for InboxController

I am trying to add a search bar. I have also set the path. But everytime I try to click on search it directs me to this error. What is the error in this code?
This is my Inbox_Controller file. It says that the action 'Search' cannot be found in InboxController.
class InboxController < ApplicationController
before_action :valid_membership
before_action :change_password_next_login
before_action :agreed_to_terms
before_action :allowed_send_mail?
layout 'inbox'
def bulk
puts params
ids = params[:bulk_ids]
if ids
params[:commit]
case params[:commit]
when 'Archive'
ids.each do |id|
message = Message.find(id)
message.archived = true
message.save()
end
when 'Restore'
ids.each do |id|
message = Message.find(id)
message.archived = false
message.save()
end
else
puts 'invalid action!!'
end
if params[:folder] != ''
redirect_to inbox_index_path(folder: params[:folder])
else
redirect_to inbox_index_path
end
else
flash[:alert] = t('errors.inbox.no_emails_selected')
redirect_to :back
end
end
def index
per_page = 10
page = params[:page] ? params[:page] : 1
#inbox = Inbox.search(params[:search])
case params[:folder]
when 'archive'
#messages = current_user.archived_messages(page, per_page)
when 'drafts'
#messages = current_user.draft_messages(page, per_page)
when 'sent'
#messages = current_user.sent_messages(page, per_page)
else
#messages = current_user.received_messages(page, per_page)
end
end
def reply
original = Message.find(params[:id])
#quoted = "\n\nOn #{original.sent_time.strftime("%m/%d/%y %-I:%M %p")}, # {original.from.full_name} wrote:\n----------------\n#{original.body}"
#message = Message.new(
:parent => original,
:to => original.from,
:subject => "RE: #{original.subject}",
:body => #quoted,
)
render :compose
end
def move
#message = Message.find(params[:id])
folder = params[:destination]
case folder
when 'archive'
#message.archived = true
else
#message.archived = false
end
unless #message.save
puts #message.errors.full_messages
end
redirect_to inbox_index_path(folder: folder)
end
def show
#message = Message.find(params[:id])
if !#message.read? && #message.to == current_user
#message.read_time = DateTime.now
unless #message.save
puts #message.errors.full_messages
end
end
end
def edit
#message = Message.find(params[:id])
#message.to_name = #message.to.full_name
render 'compose'
end
def compose
#message = Message.new
if(params[:id])
#message.to = Mentor.find(params[:id])
end
end
def create
if(params[:message] && !params[:message][:id].empty?)
#message = Message.find(params[:message][:id])
#message.assign_attributes(message_params)
else
#message = Message.new(message_params)
end
if params[:parent_id] && !params[:parent_id].empty?
#message.parent = Message.find(params[:parent_id])
#message.replied_to_time = Time.now
end
#message.from = current_user
draft = params[:draft]
if draft
#message.draft = true
else
#message.sent_time = Time.now
#message.draft = false
end
# puts #message.as_json
if can_send_mail
if #message.save
if !draft
if current_user_or_guest.mentee?
current_user.credits += -1
current_user.save
end
UserMailer.inmail_notification(#message).deliver
end
redirect_to inbox_index_path(folder: draft ? 'drafts' : 'inbox'), notice: "Message successfully #{draft ? 'saved' : 'sent'}."
else
flash.now[:alert] = 'All email fields need to be filled out prior to sending/saving.'
render 'compose'
end
else
flash.now[:alert] = 'You do not have enough credits to send any more InMail to Game Changers.'
render 'compose'
end
ActivityLog.create(userid: current_user.id, points: 500, typeof: "message")
end
def allowed_send_mail?
unless !current_user.admin?
msg = "You are not authorized to access this page!"
show_error(msg)
end
end
def profile_complete
return true if current_user.mentor?
unless current_user.profile_complete?
flash[:alert] = t('errors.inbox.incomplete_profile')
redirect_to edit_user_registration_path
end
end
def message_params
params.require(:message).permit(:id, :to_name, :to_id, :subject, :body)
end
end
This is my relevant index.erb.html file.
<%= form_tag inbox_search_path, :method => 'get' do %>
<p>
<%= search_field_tag :Search, params[:search] %>
<%= submit_tag "Search", :name => nil %>
</p>
<% end %>
This is my relevant routes.rb file:
get 'inbox' => 'inbox#index', :as => 'inbox_index'
get 'inbox/show/:id' => 'inbox#show', :as => 'inbox_show'
get 'inbox/compose' => 'inbox#compose', :as => 'inbox_compose'
get 'inbox/compose/:id' => 'inbox#compose', :as => 'inbox_compose_to'
get 'inbox/edit/:id' => 'inbox#edit', :as => 'inbox_edit'
get 'inbox/move' => 'inbox#move', :as => 'inbox_move'
get 'inbox/reply' => 'inbox#reply', :as => 'inbox_reply'
get 'inbox/search' => 'inbox#search', :as => 'inbox_search'
post 'inbox/create' => 'inbox#create'
post 'inbox/bulk' => 'inbox#bulk'
There is no search method in this controller, the only search I see is a call to Inbox.search.
To debug this, start with the view where you actually do the "click". Is that click really supposed to trigger an action in your InboxController? If you think it should, why is there no action in that controller? If not, then the "click" was meant to go to another controller that actually would handle the search action, in which case you need to figure out why the "click" is trying to call a method in your InboxController rather than the desired controller. The problem could be something in your view or something in you routes, or you really should have that method in you InboxController, either way I suggest you try to figure out at least what should be happening and then post some more code stating what you think should be happening vs what is really happening.

Passing in an existing variable into a Ruby method

I'm trying to write a test to make sure existing users can't register (Using Cucumber, Watir-Webdriver and Page Objects)
I have the following code:
text_field(:email, :id => "user_email")
text_field(:password, :id => "user_password")
text_field(:password_confirmation, :id => "user_password_confirmation")
checkbox(:terms_privacy, :id => "user_accepts_terms")
button(:sign_up_button, :text => "Sign Up")
def unique_username
#username = "qa_automation"+"#{rand(6 ** 6)}"+"#gmail.com"
end
def sign_up
unique_username
self.email = #username
self.password = USERS['PASSWORD']
self.password_confirmation = USERS['PASSWORD']
self.check_terms_privacy
self.sign_up_button
puts "username: #{#username}"
#existing = #username
end
def sign_up_with_existing_account
puts "exisiting username: #{#existing}"
self.email = #exisiting
self.password = USERS['PASSWORD']
self.password_confirmation = USERS['PASSWORD']
self.check_terms_privacy
self.sign_up_button
puts "username: #{#existing}"
end
But the #existing variable is returning nothing. These two lines are giving me back nothing:
puts "exisiting username: #{#existing}"
self.email = #exisiting
So I guess I'm trying to figure out how to pass the #existing variable from the 'sign_up' method to the 'sign_up_with_existing_account' method? Thoughts?
You can't and should not want to do that. Testing would be a tangled mess if running one test could affect the result of another. You should set up the existing user ahead of time (using e.g. Before) so that any test that needs an existing user can take advantage of it.

rails sidekiq background process

i'm having an issue configuring the sidekiq server, the process seems to be running in the foreground as soon as i refresh my page. /consumers/fetch i need to put it in the background permanently.
consumers_controller.rb
require 'kafka'
class ConsumersController < ApplicationController
def fetch
#consumer = Kafka::Consumer.new( { :host => ENV["host"],
:port => ENV["port"],
:topic => ENV["topic"]})
#consumer.loop do |message|
logger.info "-------------#{message.inspect}--------------"
logger.info "-------------#{message.first.payload.inspect}--------------"
unless message.blank?
ConsumerWorker.perform_async(message.first.payload)
end
end
end
end
consumer_worker.rb
class ConsumerWorker
include Sidekiq::Worker
def perform(message)
payload = message.first["payload"]
hash = JSON.parse(payload)
return #message = Message.new(hash) if hash["concern"] == 'order_create' or hash["concern"] == 'first_payment'
end
end
message.rb
class Message
attr_reader :bundle_id, :order_id, :order_number, :event
def initialize(message)
#payload = message["payload"]
#bundle_id = #payload["bundle_id"]
#order_id = #payload["order_id"]
#order_number = #payload["order_number"]
#event = message["concern"]
end
end
I think you need to move this block
#consumer.loop do |message|
end
inside your worker somehow, as I think the consumption is done after block execution.

RSpec controller ajax request test

I am testing my controller but requests are coming via ajax. I do not know how I can approach this problem. I am trying way like HTTP requests but I user XHR before the HTTP request. However when I run the test, I see this problem,
1) RwsController Update widget score takes widget rate information
Failure/Error: mock_widget.should_receive(:update_attributes).with({'these' => 'params'})
(Mock "Widget_1003").update_attributes({"these"=>"params"})
expected: 1 time
received: 0 times
# ./spec/controllers/rws_controller_spec.rb:28:in `block (3 levels) in <top (required)>'
I have a controller, all ajax request are recording DB in here,
class RwsController < ApplicationController
layout 'widget'
skip_before_filter :verify_authenticity_token, :only => [:edit, :update, :show, :getUserInfo]
respond_to :js, :json, :html
#cookie check and show exact view
def show
#widget = Widget.find_by_uuid(params[:uuid])
if cookies["last_widget_id"] == #widget.uuid
render :action => "generate"
end
#widget = Widget.find_by_uuid(params[:uuid])
end
def edit
#widget = Widget.find_by_uuid(params[:uuid])
end
#after rating the rates and other details record on DB
def update
#widget = Widget.find_by_uuid(params[:uuid])
#logger.info("score-in: " + params[:score])
#widget.score = params[:score].to_i
#widget.total_score = params[:total_score].to_i
#widget.click_number = params[:click_number].to_i
#widget.average = params[:average].to_i
#set cookie
cookies[:last_widget_id] = {:value => #widget.uuid, :expires => 1.year.from_now}
#widget.save!
render :text => 'ok'
logger.info("score-out: " + #widget.score.to_s)
logger.info("cookie-id: " + cookies[:last_widget_id])
end
#iframe creates and calls .js.erb file
def generate
#widget = Widget.find_by_uuid(params[:uuid])
##widget_id = #widget.id
respond_to do |format|
format.js {}
end
end
#recording the visitor who visit the page
def getUserInfo
data = params[:mainURL]
data1 = params[:mainBrowserAgent]
data2 = params[:mainReferer]
data3 = params[:mainDisplayInfo]
data4 = params[:currentWidgetId]
#widgetTraffic = WidgetTraffic.new(params[:widget_traffic])
#widgetTraffic.widget_id = #widget_id
#widgetTraffic.main_url = data
#widgetTraffic.main_browser = data1
#widgetTraffic.main_referer = data2
#widgetTraffic.main_display = data3
#widgetTraffic.widget_id = data4
#widgetTraffic.save!
render :text => 'ok'
end
end
All scenario is that A user visit the side and click the link which has some information like score and others and ajax sends the data to controller to save it as you see in controller.
But I can not solve it? How can I?
Your update method updates the #widget object without using update_attributes:
def update
#widget = Widget.find_by_uuid(params[:uuid])
#logger.info("score-in: " + params[:score])
#widget.score = params[:score].to_i
#widget.total_score = params[:total_score].to_i
#widget.click_number = params[:click_number].to_i
#widget.average = params[:average].to_i
#set cookie
cookies[:last_widget_id] = {:value => #widget.uuid, :expires => 1.year.from_now}
#widget.save!
However, your test for update expects that you will call
#widget.update_attributes(params)
1) RwsController Update widget score takes widget rate information
Failure/Error: mock_widget.should_receive(:update_attributes).with({'these' => 'params'})
(Mock "Widget_1003").update_attributes({"these"=>"params"})
expected: 1 time
received: 0 times
I think most probably, the original update method did call update_attributes and then that code was modified. That is why the test is failing now.

How do I pass current_user into my model in Rails 3?

So I have a project model & user model. Each user belongs to a plan - that restricts the amount of projects they can have (i.e. plan_id = '1' can have 1 project, plan_id = '2' can have 3 projects, etc.).
I think I figured out how to do the actual restriction (i.e. in the project model, I do a validate :custom_method, and then define the method).
The issue is, that I need to reference the currently logged in user - i.e. current_user.
How do I do that given my code below ?
Projects Controller
def create
#project = current_user.projects.build(params[:project])
if #project.save
respond_with(#project, :status => :created, :location => #project) do |format|
flash.now[:notice] = 'Project was successfully created.'
format.html { redirect_to(#project) }
format.js { render :partial => "projects/show", :locals => {:project => #project}, :layout => false, :status => :created }
end
else
respond_with(#project.errors, :status => :unprocessable_entity) do |format|
format.js { render :json => #project.errors, :layout => false, :status => :unprocessable_entity }
format.html { render :action => "new" }
end
end
end
end
Project.rb
# == Schema Information
# Schema version: 20110131093541
#
# Table name: projects
#
# id :integer not null, primary key
# name :string(255)
# description :string(255)
# notified :boolean
# created_at :datetime
# updated_at :datetime
# client_id :integer
#
class Project < ActiveRecord::Base
has_and_belongs_to_many :users
belongs_to :client
has_many :stages, :dependent => :destroy, :order => 'created_at DESC'
has_many :comments
validate :number_of_projects
def number_of_projects
current_user.projects.count <= current_user.plan.num_of_projects
end
end
User.rb
# == Schema Information
# Schema version: 20110214082231
#
# Table name: users
#
# id :integer not null, primary key
# {edited for brevity}
# plan_id :integer
#
class User < ActiveRecord::Base
before_create :assign_to_trial_plan
has_and_belongs_to_many :projects
#{edited for brevity}
belongs_to :plan
def role_symbols
roles.map do |role|
role.name.underscore.to_sym
end
end
def space
total_size = 0
if self.uploads.count > 0
self.uploads.each do |upload|
total_size += upload[:image_file_size]
end
end
total_size
end
def assign_to_trial_plan
self.plan_id = '5' #make sure to update this if the Trial plan ID ever changes
end
end
If you're using current_user.projects.build, project.user is already current_user. Mission accomplished.
Edit: With HABTM, one of the users is current_user. You might consider a second association so you can say current_user.owned_projects.build and then project.owner.

Resources