How to send data from Matlab to Rails - ruby-on-rails

I'm very new to Rails and web development.
I'm generating a bunch of objects in Matlab and I'd like send these objects to a database in my Rails app. Can anyone advise me on how to do this?
So far, on the Rails end, I've generated basic scaffolding for my data. I can add objects to my database using a form at '/myobjects/new'.
On the Matlab end, I've been trying to add objects using HTTP POST requests, like so:
s = urlread('http://localhost:3000/myobjects.json','POST',{'myobject','{name1:''value1''}'})
This fails and prints the following to the Rails console:
Started POST "/myobjects.json" for 127.0.0.1 at 2012-06-16 11:48:28 -0400
Processing by MyobjectsController#create as JSON
Parameters: {"myobject"=>"{name1:'value1'}"}
WARNING: Can't verify CSRF token authenticity
Completed 500 Internal Server Error in 1ms
NoMethodError (undefined method `stringify_keys' for "{name1:'value1'}":String):
app/controllers/myobjects_controller.rb:43:in `new'
app/controllers/myobjects_controller.rb:43:in `create'
This approach might be way off base, but hopefully the code above makes my goal clear. Can anyone tell me how to fix my code, or suggest a better strategy for getting my data into rails?
EDIT
At the moment my new and create methods look like this (but I can change them as required)
# GET /irs/new
# GET /irs/new.json
def new
#ir = Ir.new
respond_to do |format|
format.html # new.html.erb
format.json { render json: #ir }
end
end
# POST /irs
# POST /irs.json
def create
#ir = Ir.new(params[:ir])
respond_to do |format|
if #ir.save
format.html { redirect_to #ir, notice: 'Ir was successfully created.' }
format.json { render json: #ir, status: :created, location: #ir }
else
format.html { render action: "new" }
format.json { render json: #ir.errors, status: :unprocessable_entity }
end
end
end

In the end I gave up trying to do this with matlab's built-in functions. Instead, I imported a Java library (Apache HttpComponents). Here's the script I came up with. This did the job.
javaaddpath(['utils/httpcomponents-client-4.2/lib/httpcore-4.2.jar']);
javaaddpath(['utils/httpcomponents-client-4.2/lib/httpclient-4.2.jar']);
import org.apache.http.impl.client.DefaultHttpClient
import org.apache.http.client.methods.HttpPost
import org.apache.http.entity.StringEntity
httpclient = DefaultHttpClient();
httppost = HttpPost('http://127.0.0.1:3000/myobjects.json');
httppost.addHeader('Content-Type','application/json');
httppost.addHeader('Accept','application/json');
params = StringEntity('{"field1":"value1"}');
httppost.setEntity(params);
response = httpclient.execute(httppost);

You can avoid that specific problem by setting
class MyobjectsController < ApplicationController
protect_from_forgery :except => :create
...
end
within your controller. It disables the CSRF token validity check.

Related

Rails responding to Javascript request even though format.js is not on controller

In a standard, scaffolded Rails 5.1 (or 5.0) controller, you get this on the create action:
def create
#test = Test.new(test_params)
respond_to do |format|
if #test.save
format.html { redirect_to #test, notice: 'Test was successfully created.' }
format.json { render :show, status: :created, location: #test }
else
format.html { render :new }
format.json { render json: #test.errors, status: :unprocessable_entity }
end
end
end
As you see, there is no format.js there.
But if you add remote: true to the form (or, in Rails 5.1, you remove the local: true which will use the new default which is to post via ajax), the form works: the browser will send a post via xhr and redirect to the newly created record.
Looking at dev tools, I see that the response for the form submission was a 200 OK with the following content:
Turbolinks.clearCache()
Turbolinks.visit("http://localhost:3000/tests/10", {"action":"replace"})
Console also indicates it was processed by Javascript:
Started POST "/tests" for 127.0.0.1 at 2017-06-18 09:38:25 -0300
Processing by TestsController#create as JS
The question is then: how is Rails handling this response/redirect for the JS request if there's no format.js in the controller?
I'm all in for Rails magic but I want to know how this works, and I haven't seen this 'fallback the JS request to the format.html block' documented anywhere.
It looks like the code that is generating that response comes from the turbolinks-rails gem.
https://github.com/turbolinks/turbolinks-rails/blob/v5.0.1/lib/turbolinks/redirection.rb#L14
From the linked code it looks like turbolinks prepares a js response when redirect_to is called, the request is XHR, not a GET request, and turbolinks: false was not provided to the redirect_to call.
Turbolinks overrides ActionController redirect_to when the gem is present and app.config.turbolinks.auto_include is truthy.
def redirect_to(url = {}, options = {})
turbolinks = options.delete(:turbolinks)
super.tap do
if turbolinks != false && request.xhr? && !request.get?
visit_location_with_turbolinks(location, turbolinks)
else
if request.headers["Turbolinks-Referrer"]
store_turbolinks_location_in_session(location)
end
end
end
end
This behavior is intended and implemented by ActionView::LookupContext:
https://github.com/rails/rails/blob/master/actionview/lib/action_view/lookup_context.rb#L251
# Override formats= to expand ["*/*"] values and automatically
# add :html as fallback to :js.
def formats=(values)
if values
values.concat(default_formats) if values.delete "*/*".freeze
if values == [:js]
values << :html
#html_fallback_for_js = true
end
end
super(values)
end
There is an open PR to change this behavior, but it's stalling now:
https://github.com/rails/rails/pull/15224
There was some discussion about this other PR:
https://github.com/rails/rails/pull/5892

My rendering in Rails (possibly) causes a 422 error

I have received reports from users to my website that they get Error 422 when visiting a "result" page using POST. I cannot re-create this error at all so I am wondering if there is anything in my code below that would cause this error in formatting? I expect there could be errors here since I have upgraded a Rails 3.x project to a Rails 4.2.
I would either like to know if there is anything obvious in the code that would create 422 errors or if there is anyway to troubleshoot 422-errors.
Basically, in #show there is a POST method to result. It is creating a result text and lands on a url like /this-post-name/result?r=abc123 . I am rendering #show in /result because it is basically loading the same page again but with a "result box". Having to use /result is a choice I made as a newbie programmer and is not absolutely necessary, I think.
I am quite sure the error lies within the "respond_to" but can't figure that out, or troubleshoot it (i.e. re-create it).
Also, I am not sure if this is important, but I get tons of AuthencityToken errors on this page.
Edit: I managed to recreate this issue by accessing it through my iPhone and post a form, then I disabled cookies and send the form again. That would not be something people would do often but I guess having cookies disabled may cause this?
def show
#avaliable_posts = Post.where(:available => true)
end
def result
if request.get? && params[:r].blank? # Just visiting /result withoutout POST or ?r url
redirect_to category_path(#category)
else
set_round(session[:round_by_number])
# Either the visitor just posted the result or is revisiting through URL
if !params[:r].blank? # Visitor arrived from URL
#result = Result.find_by_scrambled_identifier(params[:r])
params_to_use = #result.params_used
#params_to_use = #result.params_used
else
params_to_use = params
#params_to_use = params_to_use
end
post_instance = #post.get_post_instance(params_to_use)
if post_instance.valid?
#post_result_array = post_instance.calculate_me(params_to_use)
#post_result_text_array = #post_result_array[0]
respond_to do |format|
format.html { render :action => "show" }
format.json { render :json => #post }
end
else # post not valid
#errors = post_instance.errors
respond_to do |format|
format.html { render :action => "show" }
format.xml { render :xml => #validator.errors, :status => :unprocessable_entity }
format.json { render :json => #post }
end
end
end
end
A 422 means Unprocessable Entity. Within your sample code is only one place with this http status code:
format.xml { render :xml => #validator.errors, :status => :unprocessable_entity }
Obviously this happens when format is XML and #validator contains an error.
Edit:
With the new information about the exception within the logs and the second linked stackoverflow question it seems to be releated to a known Rails issue
It seems like this issue is related to another issue that I have written another question for. I have an InvalidAuthencityToken issue with my website and the exceptions created through that cause a 422 (and not a 500) error as far as I understand from http://api.rubyonrails.org/v2.3/classes/ActionController/RequestForgeryProtection/ClassMethods.html
I am not 100% sure that this is the same issue but it seems quite likely and therefore I will close this question.

Rails, respond_to blocks and |format|

Rails scaffold generated the following:
respond_to do |format|
if #student.save
format.html { redirect_to #student, notice => 'Student was successfully created.' }
format.json { render :show, status: :created, location: #student }
else
format.html { render :new }
format.json { render json: #student.errors, status: :unprocessable_entity }
end
end
After reading this I understand how the respond_to is working (sort of), but I don't get what format is doing. Shouldn't it be either format.html or format.json and not both? What are these two lines actually doing?
format.html { render :new }
format.json { render json: #student.errors, status: :unprocessable_entity }
Is there an implied if in there? Is it something like
if (format == html) {}
if (format == json) {}
Side note: Why does update require the respond_to block while show will handle /students/1.json or /students/1 without any logic at all?
format is a local variable that respond_to yields. When you do format.html {} you are actually registering a callback block for a format.
Rails goes through the registered formats and tries to find a compatible format to the MIME type in the request. If there is no handler it will raise an error.
This could be explained as something like using syntactic sugar on top of a case statement (the Ruby equivalent of a switch statement). But the analogy is not completely accurate since Rails does a bit of work in matching the request type.
Also the code inside your block is not executed when the format.html block is registered (as it would be if it was just a conditional statement) but rather when respond_to finishes or not at all if you are using for example E-Tag caching.
Why does update require the respond_to block while show will handle
/students/1.json or /students/1 without any logic at all?
Rails handles many actions by using a convention over configuration approach and guessing the intent of the action.
def PostsController < ApplicationController
def index
# rails auto-magically fills in the controller with something
# like this
#posts = Post.all
respond_to do |format|
format.html { render :index }
format.json { render json: #posts }
end
end
def show
# convention over configuration is awesome!
#post = Post.find(params[:id])
respond_to do |format|
format.html { render :show }
format.json { render json: #post }
end
end
def new
#post = Post.new
render :new
end
def edit
#post = Post.find(params[:id])
render :edit
end
end
Rails assumes that there is a resource with the same name as the controller and auto-magically fills in the controller action. It also assumes there is a view in app/views/posts/(:action).html.[erb|haml|slim|jbuilder]. This is known as implicit rendering.
The comments show roughly what action rails attempts.
It does not fill in actions which operate on data (create, update, destroy) since the actual implementation can vary greatly and it's hard to make useful guesses.
Well, it depends on the format of the request. If a request demands HTML from the server, format.html block will be executed, and in the same way, if a request demands JSON format, format.json will be executed.
Rails will automatically(read: magically) handle the if (format == html) part for you. All you have to do is fill in the blanks. Same way, you can write a block for XML starting with format.xml.
And for the side note, I think you have said it otherwise. update method doesn't require respond_to block, while show requires. And the reason is very simple: update method is there to update the Model, and then, redirect you to somewhere, while show will always return you something. In your case, /students/1 will return you the first student created in the database, and the response will be HTML, while /students/1.json will return you the same result, but response will be JSON this time.
Well you could very well replace 'format' with 'foo' or 'banana' or whatever you want. It is just the variable name in this case because the variable that is sent to your block by respond_to is passing along the format as requested by the incoming http request's Accept header.
Sometimes you'll see 422 "Unacceptable" errors in your logs because you are receiving a request with an Accept header that does not request a mime type your app knows about.
As it is, your callers should be using a browser or be a JSON consumer sending the proper headers to receive responses from the boilerplate.

HTTP request - Ruby on Rails

I took over someone else's Rails project and I have a question about HTTP requests.
It SEEMS that I should be able to pass parameters through HTTP requests, I'm just unsure how. For example: rake routes shows
PUT /auction2s/:id(.:format) auction2s#update
Which seems to correspond to this function
# PUT /auction2s/1
# PUT /auction2s/1.json
def update
#auction2 = Auction2.find(params[:id])
print "Hello World"
respond_to do |format|
if #auction2.update_attributes(params[:auction2])
format.html { redirect_to #auction2, notice: 'Auction2 was successfully updated.' }
format.json { head :no_content }
else
format.html { render action: "edit" }
format.json { render json: #auction2.errors, status: :unprocessable_entity }
end
end
end
But I can't figure out the URL I would need to pass to, for instance, change
id=18445&done=true
into that function.
Any thoughts? Is the function structured right? Do I just need to pass the request in a Ruby format, not through the browser or AJAX (which is what I'm trying)?
You should have a form for this action. Most likely in this location -> app/views/auction1s/edit.html.erb. It will be edit.html.haml if you are using haml template engine. The form will be rendered in the view and user input will be sent as parameters to this action on submit of the form.

Heroku SocketError on POST submission

When submitting a form to create a simple object, I'm getting a SocketError:
Completed 500 Internal Server Error in 526ms
SocketError (getaddrinfo: Name or service not known):
app/controllers/posts_controller.rb:58:in `block in create'
app/controllers/posts_controller.rb:57:in `create'
I've Google'd and searched through StackOverflow, everyone else with similar errors seems to be sending email. I'm not -- this is just a form to create a simple blog post that belongs to a user.
This app IS using SendGrid (though this particular functionality does not use it), however, even after removing SendGrid, the SocketError persists.
Here's the code from the controller, referenced in the error message:
# POST /posts
# POST /posts.json
def create
#user = User.find(params[:user_id])
#post = #user.posts.new(params[:post])
respond_to do |format|
if #post.save
format.html { redirect_to user_posts_path, notice: 'Post was successfully created.' }
format.json { render json: #post, status: :created, location: #post }
else
format.html { render action: "new" }
format.json { render json: #post.errors, status: :unprocessable_entity }
end
end
end
Additionally, other posts mentioning this error seem to have issues with host declarations/URL's/URI's and weird configurations in production environment files. I don't seem to have these problems, and I can't seem to determine if this is a problem with my application or a host configuration issue with Heroku. I'm inclined to believe it's a mistake on my end.
I've been cranking on this for a while now, with no luck. Any help is appreciated!
Is a mail being delivered on post#save?
ActionMailer should be configured to use sendgrid manually on the Cedar stack:
https://devcenter.heroku.com/articles/sendgrid#actionmailer

Resources