How to save Rails input parameters to file - ruby-on-rails

I created a small application using scaffold. I'm posting data via the chrome "PostMan" extension.
This is the default create method in my controller:
# POST /settings
# POST /settings.json
def create
#setting = Setting.new(setting_params)
respond_to do |format|
if #setting.save
format.html { redirect_to #setting, notice: 'Setting was successfully created.' }
format.json { render :show, status: :created, location: #setting }
puts Setting.new(setting_params).to_yaml
else
format.html { render :new }
format.json { render json: #setting.errors, status: :unprocessable_entity }
end
end
end
This is the log in Rails' console:
(0.2ms) begin transaction
SQL (1.0ms) INSERT INTO "settings" ("DetectionOnly", "SecRequestBodyAccess", "created_at", "updated_at") VALUES (?, ?, ?, ?) [["DetectionOnly", "f"], ["SecRequestBodyAccess", "f"], ["created_at", "2016-03-23 18:04:42.642492"], ["updated_at", "2016-03-23 18:04:42.642492"]
I'm trying to only log this transaction into a file and save output in YAML format .
I tried adding this right after #setting.save.
puts Setting.new(setting_params).to_yaml
What am I doing wrong here?

If you want to save the yaml to a separate file, you could open the file in append mode and append the yaml as follows in your create action where you have puts...:
...
settings_param_file = ... # File path
if #setting.save
File.open(settings_param_file, 'a') do |file|
file << Setting.new(setting_params).to_yaml
end
end
Also, using puts in your controller action should be considered invalid. Instead you should use Rails.logger or just logger in your controller. To log a debug message use:
logger.debug { Setting.new(setting_params).to_yaml }

Related

carrierwave works with form but not API in Rails 5

I am using carrierwave to accept an image from a Python API. I have the following code:
def create
#person = Person.new(person_params)
respond_to do |format|
if #person.save
format.html { redirect_to #person, notice: 'Person was successfully created.' }
format.json { render :show, status: :created, location: #person }
else
format.html { render :new }
format.json { render json: #person.errors, status: :unprocessable_entity }
end
end
end
def person_params
params.permit(:client_file_name, :name, :picture)
end
I had to take out params.require(:person) because the Python library I am using called requests does not allow you to send files in that form.
According to the server logs, the image is saving:
Started POST "/people" for 127.0.0.1 at 2017-11-19 11:49:19 -0500
Processing by PeopleController#create as */*
Parameters: {"picture"=>#<ActionDispatch::Http::UploadedFile:0x007fe5e8e900b8 #tempfile=#<Tempfile:/var/folders/77/2f_jjrld0dxgq3t8xv6clvph0000gn/T/RackMultipart20171119-13141-1nunpha.png>, #original_filename="Phil.png", #content_type=nil, #headers="Content-Disposition: form-data; name=\"picture\"; filename=\"Phil.png\"\r\n">}
(0.0ms) begin transaction
SQL (0.2ms) INSERT INTO "people" ("picture", "created_at", "updated_at") VALUES (?, ?, ?) [["picture", "Phil.png"], ["created_at", "2017-11-19 16:49:19.776189"], ["updated_at", "2017-11-19 16:49:19.776189"]]
(0.6ms) commit transaction
Redirected to http://localhost:3000/people/8
Completed 302 Found in 15ms (ActiveRecord: 1.5ms)
I am only doing this locally. When I look in the directory where the image should be saved, there is an image there called Phil.png which is what should happen except the image has zero bytes.
When I upload the same image using a form, everything works as expected. How do I fix this?
So I figured it out. Rails requires you to set the content-type to image/png, so adding that to the request solved the problem.

ActionController::UnknownFormat in MeetingsController#update

I have read countless SO questions about this issue, and can not find a solution.
I have a button that updates Meeting here:
<%= form_for(meeting) do |f| %>
<%= f.hidden_field :accepted, value: true %>
<%= button_tag(type: 'submit', class: "btn_primary") do %>
Accept <svg><use xlink:href="#checkmark"/></svg>
<% end %>
<% end %>
I get an unknown format error, BUT it still updates. What is causing this error?
I have tried removing respond_to do |format| from the update method. which solves the problem for this one button, but then breaks all the other buttons on the platform that calls meetings/update.
class MeetingsController < ApplicationController
respond_to :json, :html
def update
respond_to do |format| **error highlights this line**
if #meeting.update(meeting_params)
format.json { render :show, status: :ok, location: #meeting }
else
format.html { render :edit }
format.json { render json: #meeting.errors, status: :unprocessable_entity }
end
end
end
end
Console:
Started PATCH "/meetings/224" for 127.0.0.1 at 2016-11-11 16:05:27 -0500
Processing by MeetingsController#update as HTML
Parameters: {"utf8"=>"✓", "authenticity_token"=>"hK6AoOZuw9DWyKUXw1dXWOSUolooWgBUPnkItUJX5Tm7XvimsHd9518pkqwVvNhUi3L3vlA4OZaJZiAgrbS0Ig==", "meeting"=>{"accepted"=>"true"}, "button"=>"", "id"=>"224"}
User Load (0.4ms) SELECT "users".* FROM "users" WHERE "users"."id" = ? ORDER BY "users"."id" ASC LIMIT 1 [["id", 1]]
Meeting Load (0.2ms) SELECT "meetings".* FROM "meetings" WHERE "meetings"."id" = ? LIMIT 1 [["id", 224]]
(0.3ms) begin transaction
SQL (0.5ms) UPDATE "meetings" SET "accepted" = ?, "updated_at" = ? WHERE "meetings"."id" = ? [["accepted", "t"], ["updated_at", "2016-11-11 21:05:27.882521"], ["id", 224]]
(1.3ms) commit transaction
Completed 406 Not Acceptable in 24ms (ActiveRecord: 2.7ms)
ActionController::UnknownFormat (ActionController::UnknownFormat):
app/controllers/meetings_controller.rb:65:in `update'
This was never an issue, and seemingly came out of no where. What is the cause of this error? Thanks!
I think I know what the issue is. I've added a line to your update method
class MeetingsController < ApplicationController
respond_to :json, :html
def update
respond_to do |format| **error highlights this line**
if #meeting.update(meeting_params)
format.html { redirect_to some_rails_path }
format.json { render :show, status: :ok, location: #meeting }
else
format.html { render :edit }
format.json { render json: #meeting.errors, status: :unprocessable_entity }
end
end
end
end
The reason you're getting an unknown format error but still successfully updating meeting is because your method has solid logic, so it's updating the meeting, but then once it does that, and you're only telling it what to do in terms of JSON but not in terms of HTML, you address both in your else statement, but not if the update succeeds.
Is this supposed to be an ajax request? It doesn't seem to be. But you're rendering json instead of html. If you're going to allow the page to reload you need to add an html option to if #meeting.update(meeting_params)
Something like: format.html { redirect_to #meeting, notice: 'Meeting was successfully updated.' }
If you're doing an ajax request this isn't the correct answer, but I don't see any indication in your question that you are. Lmk if you need further clarification.

Received JSON in Rails API is not stored

I am working on a web service in Rails that receives data in JSON format from another Rails application. When the web service receives the data, it reads it but does not insert into the database. This is from the log file:
Processing by OrdersController#create as JSON
Parameters: {"name"=>"dst", "address"=>"dst", "email"=>"sdt"}
[1m[36m (0.2ms)[0m [1mbegin transaction[0m
[1m[35mSQL (0.5ms)[0m INSERT INTO "orders" ("created_at", "updated_at")
What should I do to get this data inside the INSERT statement? Do I need a new json.jbuilder file or something else? What am I missing?
Update: Putting the controller#create code here. Didn't paste it initially because it is the default created from the scaffold generator.
# POST /orders
# POST /orders.json
def create
#order = Order.new(order_params)
respond_to do |format|
if #order.save
format.html { redirect_to #order, notice: 'Order was successfully created.' }
format.json { render :show, status: :created, location: #order }
else
format.html { render :new }
format.json { render json: #order.errors, status: :unprocessable_entity }
end
end
end
order_params is presumably defined somewhere in your OrdersController. Normally model parameters in a request are nested under the resource ({order: {"name"=>"dst", "address"=>"dst", "email"=>"sdt"}) and then in order_params would be
def order_params
params.require(:order).permit(:name, :address, :email)
end
But if you can't change the JSON payload, you could just nix the require(:order) part and call params.permit(:name, :address, :email).
You can read the Rails guide on Strong Parameters here: http://edgeguides.rubyonrails.org/action_controller_overview.html#strong-parameters

Writing to Rails with a JSON API

I've been trying to write to a regular one model rails app from POSTman for a few days now, and can't figure out how to do it, or find any information on how to do it.
My app has a User model with a name field. All I'm trying to do is change the name remotely via JSON using POSTman.
Any help on how to do this is appreciated, including a link to a basic resource on how to do it.
I imagine this is pretty basic.
EDIT: here is a screenshot from the POSTman output
EDIT 2:
from server log:
Started PUT "/users/1.json" for 127.0.0.1 at 2013-07-17 16:53:36 -0400
Processing by UsersController#update as JSON
Parameters: {"name"=>"Jeff", "id"=>"1"}
User Load (0.2ms) SELECT "users".* FROM "users" WHERE "users"."id" = ? LIMIT 1 [["id", "1"]]
(0.1ms) begin transaction
(0.1ms) commit transaction
Completed 204 No Content in 3ms (ActiveRecord: 0.4ms)
The transaction is happening, but the record isn't actually being updated. Do I need to change something in the controller? It's just a regular rails generated controller with no changes.
EDIT 3:
Here is my output from just going to http://localhost:3000/users/1.json
{
"created_at": "2013-07-02T21:51:22Z",
"id": 1,
"name": "Arel",
"updated_at": "2013-07-02T21:51:22Z"
}
Again, I've changed nothing from the scaffold, and I haven't been able to figure out how to format the JSON to nest it under user like the answer suggests.
Here is the relevant part of my controller:
# GET /users/1
# GET /users/1.json
def show
#user = User.find(params[:id])
respond_to do |format|
format.html # show.html.erb
format.json { render json: #user }
end
end
# PUT /users/1
# PUT /users/1.json
def update
#user = User.find(params[:id])
respond_to do |format|
if #user.update_attributes(params[:user])
format.html { redirect_to #user, notice: 'User was successfully updated.' }
format.json { }
else
format.html { render action: "edit" }
format.json { render json: #user.errors, status: :unprocessable_entity }
end
end
end
I don't understand why this is so difficult. I'm just trying to update a name via JSON ...
For the controller you want to post to:
protect_from_forgery with: :null_session
or like from: How do I bypass protect_from_forgery in Rails 3 for a Facebook canvas app?
skip_before_filter :verify_authenticity_token, :only => [THE ACTION]
EDIT
Your JSON is incorrect... you are posting
{"name"=>"Jeff", "id"=>"1"}
Since your controller does user.update_attribute(params[:user]), your JSON needs to be under a user attribute
{
"id": 1,
"user": {
"name": "Jeff"
}
}
This will create a hash of
{"user"=>{"name"=>"Jeff"}, "id"=>"1"}

Basic .ajax post to a rails 3.2.2 scaffold generating "WARNING: Can't verify CSRF token authenticity"

I am trying to learn how to post some data using $.ajax through jquery to a simple rails scaffold project. There is one standard scaffold created controller => Images
class ImagesController < ApplicationController
# GET /images
# GET /images.json
def index
#images = Image.all
respond_to do |format|
format.html # index.html.erb
format.json { render json: #images }
end
end
# GET /images/1
# GET /images/1.json
def show
#image = Image.find(params[:id])
respond_to do |format|
format.html # show.html.erb
format.json { render json: #image }
end
end
# GET /images/new
# GET /images/new.json
def new
#image = Image.new
respond_to do |format|
format.html # new.html.erb
format.json { render json: #image }
end
end
# GET /images/1/edit
def edit
#image = Image.find(params[:id])
end
# POST /images
# POST /images.json
def create
#image = Image.new(params[:image])
respond_to do |format|
if #image.save
format.html { redirect_to #image, notice: 'Image was successfully created.' }
format.json { render json: #image, status: :created, location: #image }
else
format.html { render action: "new" }
format.json { render json: #image.errors, status: :unprocessable_entity }
end
end
end
# PUT /images/1
# PUT /images/1.json
def update
#image = Image.find(params[:id])
respond_to do |format|
if #image.update_attributes(params[:image])
format.html { redirect_to #image, notice: 'Image was successfully updated.' }
format.json { head :no_content }
else
format.html { render action: "edit" }
format.json { render json: #image.errors, status: :unprocessable_entity }
end
end
end
# DELETE /images/1
# DELETE /images/1.json
def destroy
#image = Image.find(params[:id])
#image.destroy
respond_to do |format|
format.html { redirect_to images_url }
format.json { head :no_content }
end
end
end
with one route => resources :images. The database schema consists of one field => t.string :name.
My initial test html file is:
<html>
<head>
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.5/jquery.min.js"> </script>
</head>
<body>
<script>
$(document).ready(function(){
$.ajax({
type: 'POST', url: "localhost:3000/images",
data: { name: "johngalt" }
});
});
</script>
</body>
The result from webrick is:
Started POST "/images" for 127.0.0.1 at 2012-04-17 09:50:19 -0500
Processing by ImagesController#create as */*
Parameters: {"name"=>"johngalt"}
WARNING: Can't verify CSRF token authenticity
(0.1ms) begin transaction
SQL (63.5ms) INSERT INTO "images" ("created_at", "name", "updated_at") VALUES (?, ?, ?) [["created_at", Tue, 17 Apr 2012 14:50:21 UTC +00:00], ["name", nil], ["updated_at", Tue, 17 Apr 2012 14:50:21 UTC +00:00]]
(2.0ms) commit transaction
Redirected to http://localhost:3000/images/7
Completed 302 Found in 81ms (ActiveRecord: 65.6ms)
I'm not sure why name doesn't contain "johngalt". Does this have something to do with the " WARNING: Can't verify CSRF token authenticity"?
Edit
When I use curl:
curl -d "image[name]=johngalt" localhost:3000/images.json
The record is created and the name field contains "johngalt". In essence, I'm trying to figure out the .ajax equivalent of doing what I was able to do in curl?
The CSRF token is automatically added in your post forms when you use the Rails form_for helper to create a form, and is meant to protect users against cross-site request forgery attacks. So, if you are trying to post in a javascript file you won't have access to the token.
You can disable CSRF token authentication for specific actions if you so wish, as long as you understand the consequences.
There are a few ways you can do that, listed here: Turn off CSRF token in rails 3
Edit Looking at your CURL example, it looks like you are ajax posting the wrong data. You are ommiting the 'image' param namespace. Try:
<script>
$(document).ready(function(){
$.ajax({
type: 'POST', url: "localhost:3000/images",
data: { image: { name: "johngalt" } }
});
});
</script>

Resources