Issues recieving and parasing a put request in ruby on rails - ruby-on-rails-3

Having some issues parsing and retrieving a put request from a raspberry pi I have sending my website data.
I am trying to update some fields in my Worker model the controller is below
class WorkersController < ApplicationController
def new
#worker = Worker.new
#user = User.find(params[:user_id])
end
def create
#user = User.find(params[:user_id])
#worker= Worker.new(params[:worker])
#worker.user_id= #user.id
if #worker.save
flash[:success] = "Worker information saved!"
redirect_to #user
else
render 'new'
end
end
def show
end
def update
#user = User.find(params[:user_id])
#worker = Worker.find(params[:id])
#MHS = params[:SUMMARY][:MHS_av]
#worker.hashrate = #MHS
#worker.save
end
end
Below is the server side incoming put request
Started PUT "/users/1/workers/1" for xxx.xxx.xx.xxx at 2013-06-13 03:06:02 +0000
Processing by WorkersController#update as XML
Now here are the parameters
Parameters: {"STATUS"=>[{"STATUS"=>"S", "When"=>1371092750, "Code"=>11, "Msg"=>"Summary", "Description"=>"cgminer 3.1.1"}], "SUMMARY"=>[{"Elapsed"=>60394, "MHS av"=>1.92, "Found Blocks"=>1, "Getworks"=>1217, "Accepted"=>9104, "Rejected"=>138, "Hardware Errors"=>0, "Utility"=>9.04, "Discarded"=>2428, "Stale"=>20, "Get Failures"=>1, "Local Work"=>9513, "Remote Failures"=>0, "Network Blocks"=>458, "Total MH"=>116212.6295, "Work Utility"=>1769.84, "Difficulty Accepted"=>1747840.0, "Difficulty Rejected"=>26496.0, "Difficulty Stale"=>3840.0, "Best Share"=>74960510}], "id"=>"1", "user_id"=>"1", "worker"=>{}}
Followed by these Errors
WARNING: Can't verify CSRF token authenticity
at=info method=PUT path=/users/1/workers/1 host=miningmonitor.herokuapp.com fwd="xxx.xxx.xx.xxx" dyno=web.1 connect=1ms service=1029ms status=500 bytes=643
TypeError (can't convert Symbol into Integer):
app/controllers/workers_controller.rb:27:in `[]'
Completed 500 Internal Server Error in 345ms
app/controllers/workers_controller.rb:27:in `update'
I See that Ruby on rails is thinking the incoming message is XML but its JSON do I need to specify somewhere that this put request is JSON? Also I was told Ruby on rails just parses JSON into the params and I can just pull the data from the params is that true?
adding content from application.html.erb from layouts
<head>
<title>Mining Monitoring Website</title>
<%= stylesheet_link_tag "application", media: "all"%>
<%= javascript_include_tag "application" %>
<%= csrf_meta_tags %>
<%= render 'layouts/shim' %>
</head>

Look at it closely - SUMMARY is an array, not hash. I don't know how you're building POST (PUT) data, but accessing them in following way following should work
params[:SUMMARY][0][:MHS_av]
Also - please take a look at MHS_av - it looks like in incomming parameters it does not have an underscore.
CSRF is mising by a reason, right?

Related

How do I render a reply into turbolinks 5 with rails 5

I have a controller action where I'd like to receive form data, execute some business logic, then refresh the form. This works Ok if I save the object in the database then use a redirect_to. I would prefer the controller edit the object in memory and render the response directly.
For example, take a standard rails 5.1.4 generated app generated like so:
rails new turbolinks_example
rails g scaffold Thing name
rails db:migrate
The form, slightly edited for brevity and to enable turbolinks:
<%= form_with(model: thing) do |form| %>
<div class="field">
<%= form.label :name %>
<%= form.text_field :name, id: :thing_name %>
</div>
<div class="actions">
<%= form.submit %>
</div>
<% end %>
A) Now we edit the controller to change the object. This uses a redirect to edit and works:
ThingsController < ApplicationController
...
def update
if #thing.update(thing_params)
#thing.update name: "#{#thing.name} is OK"
redirect_to edit_thing_path(#thing)
end
end
B) This uses a render and does not work:
class ThingsController < ApplicationController
...
def update
if #thing.update(thing_params)
#thing.name = "#{#thing.name} is OK"
render :edit
end
end
end
With A)
- Update request is received by controller
- Object is modified (& saved)
- Redirect is returned
- Rediredted url is rendered
- DOM is updated
With B)
- Update request is received by controller
- Object is modified (in memory)
- Response is rendered
- Response is received by browser, but ignored
The response received, looks correct. Full HTML, with the changes made to the object. How do I get turbolinks to notice it and replace document.body like normal?
The full project, including development.log is on Github
The problem is that, in Rails 5:
Forms are remote by default: they are sent via AJAX unless local: true provided
When rendering HTML as a response to an AJAX call, nothing happens unless, of course, there is custom javascript in the client handling the response
Turbolinks is enabled by default, which handles redirect_to properly, but does nothing for render
I think this is an inconsistency in Rails that causes much confusion, such as the problem you exposed with your code. I created a gem turbolinks_render to deal with this problem. I also wrote a little post on this very same problem.
I hope that, one way or other, this gets fixed in future Rails versions.

Devise sign_out_and_redirect flash notice

I'm running a Rails 3.2.14 app with Devise 2.1.2 and am checking for concurrent/duplicate sessions in my application controller.
I'd like to be able to display a flash notice in template view after I call signout_and_redirect in my application controller that displays "Duplicate login detected"
Here's what my code looks like:
application_controller.rb
def check_concurrent_session
if duplicate_session?
flash[:notice] = "Duplicate Login Detected"
sign_out_and_redirect(current_user)
end
end
def duplicate_session?
user_signed_in? && (current_user.login_token != session[:token])
end
I've tried it with the above code, but when I trigger a duplicate session the browser does sign out but does not display the flash notice.
In my application.html.erb I have the following setup to display flash notice/alerts.
<% if flash[:notice] %>
<p class="alert"><%= flash[:notice] %></p>
<% end %>
<% if flash[:alert] %>
<p class="alert"><%= flash[:alert] %></p>
<% end %>
Could you use session?
def check_concurrent_session
if duplicate_session?
sign_out_and_redirect(current_user)
session[:duplication_notice] = "Duplicate Login Detected"
end
end
# users/sessions_controller.rb
def new
if session[:duplication_notice].present?
flash.now[:alert] = session[:duplication_notice]
session.delete(:duplication_notice)
end
super
end
Lifetime of flash is until next action.
sign_out_and_redirect
authenticate_user!
sign_in
log
Started GET "/" for 127.0.0.1 at 2015-04-13 17:08:02 +0900
Processing by Users::FunctionsController#home as HTML
Filter chain halted as :check_concurrent_session rendered or redirected
Completed 302 Found in 9ms (ActiveRecord: 0.9ms)
Started GET "/" for 127.0.0.1 at 2015-04-13 17:08:02 +0900
Processing by Users::FunctionsController#home as HTML
Completed 401 Unauthorized in 1ms
Started GET "/users/sign_in" for 127.0.0.1 at 2015-04-13 17:08:02 +0900
Processing by Users::SessionsController#new as HTML
Completed 200 OK in 3258ms (Views: 3254.7ms | ActiveRecord: 0.3ms)
Because sign_out clear the session, session set after sign_out.
Anything you place in the flash will be exposed to the very next action
You can sign out without redirecting and make the redirect with flash message later. Using the after_sign_out_path_for method will ensure that you use the correct path for redirect even if it has been customized.
Following your example:
if duplicate_session?
user = current_user
sign_out(user)
redirect_to after_sign_out_path_for(user),
alert: 'Duplicate Login Detected'
end
For the more recent version of devise, you could also redirect to a new user session path after clearing the user session.
if duplicate_session?
flash[:notice] = "Duplicate Login Detected"
sign_out current_user
redirect_to new_user_session_path
end
This will persist the flash after redirect

Rails AJAX request 500 Internal Server Error details

I have a form partial as follows:
_internet_service_form.html.erb
<%= simple_form_for #internet_service, remote: true do |f| %>
<%= f.input :start_date %>
<%= f.button :submit %>
<% end %>
When I render it in the new action of the controller, it returns a 500 internal server with no further explanation.
When I render it in the edit action of the controller, it renders correctly.
If I replace the partial with a text block with no rails tags in it, it renders correctly, so I know it's not a routing error.
new.js.erb
$("#result-content").html("<%= escape_javascript(render(partial: 'new')) %>");
new.html.erb
<%= render partial: 'internet_service_form' %>
internet_service_controller.rb
def new
#internet_service = InternetService.new
end
def edit
#internet_service = InternetService.find(params[:id])
end
These actions are being performed through AJAX, and the most useful logs I'm getting out of the development log are:
Started POST "/accounts/29/internet_services/new.js" for 10.12.68.100 at 2013-02-13 00:28:11 +1300
Processing by InternetServicesController#new as JS
... snip ...
Rendered internet_services/_internet_service_form.html.erb (14.9ms)
Rendered internet_services/_new.html.erb (24.3ms)
Rendered internet_services/new.js.erb (32.2ms)
Completed 500 Internal Server Error in 231ms

Rails properly pass in id through form

I just need some clarity of thought on this one. I've got a Photos show page where a user can click "Like" to create a new like record for a particular photo.
On my photos show.html page I have the following form:
<%= form_for :like, :url => likes_path do |f| %>
<%= hidden_field_tag(:photo_id, #photo.id) %>
<%= f.submit "Like" %>
<% end %>
When I click the form I get a message that it "Couldn't find a Photo without an ID":
Started POST "/likes" for 127.0.0.1 at Sat Feb 25 16:43:21 -0500 2012
Processing by LikesController#create as HTML
Parameters: {"commit"=>"Like", "authenticity_token"=>"cQnuAHb/f6Sgo3aB5xPKErx3joQTV+DHGs0w9vi13vM=", "utf8"=>"\342\234\223", "photo_id"=>"47"}
Completed 404 Not Found in 68ms
ActiveRecord::RecordNotFound (Couldn't find Photo without an ID):
app/controllers/likes_controller.rb:8:in `create'
Not sure why when it seems to be passing in the photo_id correctly, no?
Here's a look at my likes_controller:
def create
#photo = Photo.find(params[:id])
#like = Like.new(:photo_id => :photo_id, :user_id => current_user.id)
end
Anyone see what I'm doing wrong here? Thanks.
It should work with Photo.find(params[:photo_id]).
The error message says that you called Photo.findwith a nil parameter, e.g. there is no parameter id in the request.

Is there any way to avoid having the browser's address changed after using "render"?

I am currently following the Ruby on Rails Tutorial by Michael Hartl. And there is something that has been bugging me for quite some time. I looked it up but I still can't find a good answer.
Anyway, I've noticed is when you have a validation error in the signup page it renders the original signup page and changes the nav bar address. I've matched /signup to the action new, but if I use render it changes from /signup to /users (the default, because of the RESTful standard I guess).
I'll leave some lines of my code:
routes.rb
resources :users
match '/signup', :to => 'users#new'
users_controller.rb
def new
#user = User.new
#title = "Sign up"
end
def create
#user = User.new(params[:user])
if #user.save
sign_in #user
flash[:success] = "Welcome to the Sample App!"
redirect_to user_path(#user)
else
#title = "Sign up"
#user.password = ""
#user.password_confirmation = ""
render 'new'
end
end
So I've tried to work around this by not using the render method but redirect_to instead but I'm having trouble using it. As it is actually sending data to the path provided, #user.errors gets overwritten by creating a new instance of the model and the flash variable cannot show the errors.
_errors.html.erb
<% if #user.errors.any? %>
<div id="error_explanation">
<h2>
<%= pluralize(#user.errors.count, "error") %>
prohibited the user from being saved:
</h2>
<p>There were problems with the following fields:</p>
<ul>
<% #user.errors.full_messages.each do |message| %>
<li><%= message %></li>
<% end %>
</ul>
</div>
<% end %>
My question is: is there any way that by using render I can change the url displayed on the navbar? It's really frustrating if someone makes a mistake in the signup form, presses enter in the navbar and ends up in a totally different place.
The reason why the address changes is because you have performed a POST request to /users/ therefore the browser is doing the correct thing by displaying the different address.
There are a few of ways around this:
Store the invalid User object and redirect back to the Users.new action.
Change the URL of the Users.create action.
Use history.replaceState to change the user's address bar.
The first option keeps the controller more RESTful, however it will need use of the :session or flash to persist the data across the redirect.
The second option keeps the code simpler, but involves fiddling with the routes.rb file.
The third option relies on javascript and support for HTML5 to mess with the user's browser history.
Personally I would leave the URL as is, but if I had a client who insisted on doing this, I would go for the second option.