Ruby on Rails: How to POST in my API? - ruby-on-rails

I'm trying to create a task, but the attributes are null
Mi controller:
#app/controllers/api/v1/tasks_controller.rb
def create
respond_with Task.create(params[:Task])
end
I tried do POST to localhost:3000/api/v1/tasks with this data:
{"task": {"name":"hello world"}} or {"name":"hello world"}
but the result has attributes null:
#Response Body
{
"id": 1,
"name": null,
"created_at": "2014-03-23T22:41:37.961Z",
"updated_at": "2014-03-23T22:41:37.961Z"
}
Update:
# Server log
Started POST "/api/v1/tasks" for 127.0.0.1 at 2014-03-23 17:03:03 -0600
Processing by Api::V1::TasksController#create as JSON
(0.1ms) begin transaction
SQL (0.5ms) INSERT INTO "tasks" ("created_at", "updated_at") VALUES (?, ?) [["created_at", Sun, 23 Mar 2014 23:03:03 UTC +00:00], ["updated_at", Sun, 23 Mar 2014 23:03:03 UTC +00:00]]
(153.5ms) commit transaction
Completed 201 Created in 159ms (Views: 0.6ms | ActiveRecord: 154.0ms)

Thanks vee, emcanes, Carlos Figueiredo and BroiSatse for your answers. I solved the problem.
I changed create action:
#app/controllers/api/v1/tasks_controller.rb
def create
respond_with Task.create(task_params)
end
And I added:
#app/controllers/api/v1/tasks_controller.rb
private
...
def task_params
params.require(:task).permit(:name)
end

Related

Rails controller looks like it is saving all params, but fields are missing when I pull the record - Like post function

I am keeping an eye on my rails server and my rails console. Everything looks great in my server.
When I go to create a Like, my server saves all the stuff I'm looking to save.
Notice that I am passing in an author_id, a likable_id, and a likable_type. This association is polymorphic.
Like Create (0.6ms) INSERT INTO "likes" ("author_id", "likeable_type", "likeable_id", "created_at", "updated_at") VALUES ($1, $2, $3, $4, $5) RETURNING "id" [["author_id", 1], ["likeable_type", "Pin"], ["likeable_id", 34], ["created_at", "2020-12-18 04:52:49.973371"], ["updated_at", "2020-12-18 04:52:49.973371"]]
↳ app/controllers/api/likes_controller.rb:8
(1.9ms) COMMIT
↳ app/controllers/api/likes_controller.rb:8
Rendering api/likes/show.json.jbuilder
Rendered api/likes/_like.json.jbuilder (0.4ms)
Rendered api/likes/show.json.jbuilder (2.4ms)
Completed 200 OK in 75ms (Views: 8.1ms | ActiveRecord: 20.6ms)
Great! I get the 200OK! Awesome.
However, when I check Like.all in the console, It looks like the Like is being created with none of the params I passed into it above.
[55] pry(main)> Like.all
Like Load (0.3ms) SELECT "likes".* FROM "likes"
=> [#<Like:0x00007fbef776c7e0
id: 6, #<--- Only the id for the like is being shown :(
created_at: Fri, 18 Dec 2020 04:30:50 UTC +00:00,
updated_at: Fri, 18 Dec 2020 04:30:50 UTC +00:00>]
[56] pry(main)>
I found the answer. For whatever reason, my schema was not bugged out and somehow had extra text. I dropped the table and re-migrated.

Why some model attributes not saved in the db?

I have a Quote model in my rails app which has various attr types, some of which are being sent to / saved by the db, some are not and I cannot understand why. Please can you help me understand, thanks.
quotes_controller.rb
class QuotesController < ApplicationController
def create
#quote = Quote.new(quote_params)
if #quote.save
redirect_to root_url, notice: 'Quote request created'
else
render :new
end
end
private
def quote_params
params.require(:quote).permit(:gla, :prev_cover, :co_name, :postcode, :industry, :lives_overseas,
:scheme_start_date, :payment_frequency, :commision_level)
end
end
quote.rb model
class Quote < ApplicationRecord
validates :gla, presence: { message: "Must be selected" }
enum industry: [ :financial_services, :architect, :business_consultancy ]
enum payment_frequency: [ :annually, :monthly ]
end
schema.rb
create_table "quotes", force: :cascade do |t|
t.boolean "prev_cover"
t.string "co_name"
t.integer "co_number"
t.string "postcode"
t.string "industry"
t.boolean "lives_overseas"
t.date "scheme_start_date"
t.string "payment_frequency"
t.integer "commission_level"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.boolean "gla"
end
rails console:
Pry> Quote.last.attributes
Quote Load (0.4ms) SELECT "quotes".* FROM "quotes" ORDER BY "quotes"."id" DESC LIMIT $1 [["LIMIT", 1]]
=> {"id"=>6,
"prev_cover"=>true,
"co_name"=>"test1",
"co_number"=>nil,
"postcode"=>"al1 1aa",
"industry"=>nil,
"lives_overseas"=>true,
"scheme_start_date"=>Wed, 31 May 2017,
"payment_frequency"=>nil,
"commission_level"=>nil,
"created_at"=>Wed, 31 May 2017 19:23:07 UTC +00:00,
"updated_at"=>Wed, 31 May 2017 19:23:07 UTC +00:00,
"gla"=>true}
Stack Trace:
Started POST "/quotes" for 127.0.0.1 at 2017-05-31 21:04:37 +0100
Processing by QuotesController#create as HTML
Parameters: {"utf8"=>"✓", "authenticity_token"=>"ILAo0Bs9Wq9lrVPlM2e6+a1kioV9zbni9Uxd5Yt/QSLNY3aVWyJ4TsEUmXN62RWgbueHksr/yN6avwEm8v7bEQ==", "quote"=>{"gla"=>"1", "prev_cover"=>"true", "co_name"=>"testing1", "co_number"=>"123456", "postcode"=>"al1 1aa", "industry"=>"", "lives_overseas"=>"true", "scheme_start_date(1i)"=>"2017", "scheme_start_date(2i)"=>"5", "scheme_start_date(3i)"=>"31", "payment_frequency"=>"", "commission_level"=>"10"}, "commit"=>"Get quote"}
Unpermitted parameters: co_number, commission_level
(0.1ms) BEGIN
SQL (0.2ms) INSERT INTO "quotes" ("prev_cover", "co_name", "postcode", "lives_overseas", "scheme_start_date", "created_at", "updated_at", "gla") VALUES ($1, $2, $3, $4, $5, $6, $7, $8) RETURNING "id" [["prev_cover", "t"], ["co_name", "testing1"], ["postcode", "al1 1aa"], ["lives_overseas", "t"], ["scheme_start_date", "2017-05-31"], ["created_at", "2017-05-31 20:04:37.489368"], ["updated_at", "2017-05-31 20:04:37.489368"], ["gla", "t"]]
(0.3ms) COMMIT
Redirected to http://localhost:3000/
Completed 302 Found in 3ms (ActiveRecord: 0.6ms)
Started GET "/" for 127.0.0.1 at 2017-05-31 21:04:37 +0100
Processing by QuotesController#new as HTML
Rendering quotes/new.html.erb within layouts/application
Rendered quotes/new.html.erb within layouts/application (9.3ms)
Completed 200 OK in 34ms (Views: 32.7ms | ActiveRecord: 0.0ms)
From Rails console.
[1] pry(main)> Quote.last
Quote Load (0.2ms) SELECT "quotes".* FROM "quotes" ORDER BY "quotes"."id" DESC LIMIT $1 [["LIMIT", 1]]
=> #<Quote:0x007f951b14e918
id: 7,
prev_cover: true,
co_name: "testing1",
co_number: nil,
postcode: "al1 1aa",
industry: nil,
lives_overseas: true,
scheme_start_date: Wed, 31 May 2017,
payment_frequency: nil,
commission_level: nil,
created_at: Wed, 31 May 2017 20:04:37 UTC +00:00,
updated_at: Wed, 31 May 2017 20:04:37 UTC +00:00,
gla: true>
Ok stack trace and #toddmetheny help me sort out the missing or typo'd permitted attrs. Now just the enums Quote.industries and Quote.payment_frequencies whose values aren't getting saved.
Ok, so code changed to;
And this sends the attrs from the form, but they still don't get created in the db, stack trace:
Started POST "/quotes" for 127.0.0.1 at 2017-05-31 21:39:58 +0100
Processing by QuotesController#create as HTML
Parameters: {"utf8"=>"✓", "authenticity_token"=>"rkgX7CwrEHS/KnqG1C77mYkCiCEOWGshTxMCsbtGPdjGiDP20J4ccrAgplAGuKrdJyhECRWrsmXI0Ee9GNa6Zw==", "quote"=>{"gla"=>"1", "prev_cover"=>"true", "co_name"=>"halejulia", "co_number"=>"134532", "postcode"=>"al1 1aa", "industry"=>"financial_services", "lives_overseas"=>"true", "scheme_start_date(1i)"=>"2017", "scheme_start_date(2i)"=>"5", "scheme_start_date(3i)"=>"31", "payment_frequency"=>"monthly", "commission_level"=>"10"}, "commit"=>"Get quote"}
(0.1ms) BEGIN
SQL (0.3ms) INSERT INTO "quotes" ("prev_cover", "co_name", "co_number", "postcode", "industry", "lives_overseas", "scheme_start_date", "payment_frequency", "commission_level", "created_at", "updated_at", "gla") VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12) RETURNING "id" [["prev_cover", "t"], ["co_name", "halejulia"], ["co_number", 134532], ["postcode", "al1 1aa"], ["industry", 0], ["lives_overseas", "t"], ["scheme_start_date", "2017-05-31"], ["payment_frequency", 1], ["commission_level", 10], ["created_at", "2017-05-31 20:39:58.957674"], ["updated_at", "2017-05-31 20:39:58.957674"], ["gla", "t"]]
(0.3ms) COMMIT
Redirected to http://localhost:3000/
Completed 302 Found in 3ms (ActiveRecord: 0.7ms)
rails console :
Quote.last.payment_frequency
Quote Load (0.4ms) SELECT "quotes".* FROM "quotes" ORDER BY "quotes"."id" DESC LIMIT $1 [["LIMIT", 1]]
=> nil
So still the params aren't being persisted in the db, they're permitted params! any ideas?
Strange, a psql select * from .. query shows that the values have been saved, yet Rails console; Quote.last.payment_frequency returns nil???
Aha, i see that for a enum the column type should be integer, yet it is string in my model, could this be the issue perhaps?
Data type of enum'd attrs changed to integer and all behaves as expected.
Post the stack trace. co_number isn't whitelisted in the permitted params. So that's at least part of the issue with that particular field. The others are...but post what you're actually seeing in the logs so we can see what's being passed through the form. There will also be messages in the stack trace that give you clues as to why those values aren't saving.
Update: the stack trace lists 2 unpermitted parameters: co_number and commission_level (you have a typo permitting commission level and co_number isn't there)
A couple things have blank values, too...like payment_frequency and industry...I'd dig into why those things are blank if they shouldn't be. Does the form have values for those things? They aren't being passed. That seems to account for the rest of your nil values.

Saving a collection of objects rails 4 (strong params)

I am currently working on the backend of shop. The Client wants to be able to see a list of all products and update the stock values for all the products in one submission of a form. I have a working solution, but it's a very 'hacky' and introduces a lot of issues. I am new to Ruby on Rails and web development in general so I'm still learning a few of the fundamental conventions and what not.
I will paste my working solution and then attempt to explain the problem I have:
class Product < ActiveRecord::Base
has_many :stocks
...
end
class Stock < ActiveRecord::Base
belongs_to :product
...
end
stock_controller.rb
class StocksController < ApplicationController
def index
#products = Product.all.includes(:stocks)
end
...
def update_current
#stock_params = params[:stock]
#stock_params.each do |stock_params|
params.permit(:current_stock, :product_id)
#stock = Stock.new(stock_params)
#stock.save
end
redirect_to stocks_path, notice: 'Stocks were successfully updated'
end
...
stocks.index.html.erb
...
<%= form_tag url_for(:action => 'update_current') do |f| %>
<% #products.each do |product| %>
<tr>
<td><%= product.product_name %></td>
<td><%= product.minimum_stock %></td>
<td><%= text_field_tag "stock[][current_stock]", product.stocks.last.current_stock %></td>
<%= hidden_field_tag "stock[][product_id]", product.stocks.last.product_id %>
</tr>
<% end %>
<%= submit_tag 'save' %>
<% end %>
...
When I hit the submit button params set is as it needs to be:
console :
Started POST "/stocks/update_current" for 127.0.0.1 at 2013-10-24 11:54:03 +0100
Processing by StocksController#update_current as HTML
Parameters: {"utf8"=>"✓", "authenticity_token"=>"NlabBuwI06t+YN5O6p7dm+Zg2Bwc9uXrKUdWaBqNs9w=", "stock"=>[{"current_stock"=>"1", "product_id"=>"1"}, {"current_stock"=>"2", "product_id"=>"2"}, {"current_stock"=>"3", "product_id"=>"24"}, {"current_stock"=>"4", "product_id"=>"25"}, {"current_stock"=>"5", "product_id"=>"23"}, {"current_stock"=>"6", "product_id"=>"21"}, {"current_stock"=>"7", "product_id"=>"19"}, {"current_stock"=>"8", "product_id"=>"22"}, {"current_stock"=>"9", "product_id"=>"5"}], "commit"=>"save"}
Unpermitted parameters: utf8, authenticity_token, stock, commit
(0.2ms) BEGIN
SQL (136.6ms) INSERT INTO "stocks" ("created_at", "current_stock", "product_id", "updated_at") VALUES ($1, $2, $3, $4) RETURNING "id" [["created_at", Thu, 24 Oct 2013 10:54:03 UTC +00:00], ["current_stock", 1], ["product_id", 1], ["updated_at", Thu, 24 Oct 2013 10:54:03 UTC +00:00]]
(24.2ms) COMMIT
Unpermitted parameters: utf8, authenticity_token, stock, commit
(0.2ms) BEGIN
SQL (0.7ms) INSERT INTO "stocks" ("created_at", "current_stock", "product_id", "updated_at") VALUES ($1, $2, $3, $4) RETURNING "id" [["created_at", Thu, 24 Oct 2013 10:54:03 UTC +00:00], ["current_stock", 2], ["product_id", 2], ["updated_at", Thu, 24 Oct 2013 10:54:03 UTC +00:00]]
(0.7ms) COMMIT
Unpermitted parameters: utf8, authenticity_token, stock, commit
(0.1ms) BEGIN
SQL (0.4ms) INSERT INTO "stocks" ("created_at", "current_stock", "product_id", "updated_at") VALUES ($1, $2, $3, $4) RETURNING "id" [["created_at", Thu, 24 Oct 2013 10:54:03 UTC +00:00], ["current_stock", 3], ["product_id", 24], ["updated_at", Thu, 24 Oct 2013 10:54:03 UTC +00:00]]
(0.6ms) COMMIT
As you can see form the log the authenticity_token, and other params are unpermitted. Now I understand the purpose of the token and the other params, what I do not know, why exactly I am running into this issue.
My guess is the way I am permitting the params. I don't get how to tell strong_params to permit an array of hashes: stock => [{:current_stock, :product_id},{:current_stock, :product_id}, ..., ....]. params.permit(stock: [:current_stock, :product_id]) ???
It doesn't make sense in this case to nest stocks under product, as I am working with a collection of products opposed to a single product.
In an ideal world, I would like to be able to insert the new stock values for all products in one submit and save to the database with one query. I feel as if Ajax may be a viable solution, but again, until I fully understand whats going on I don't want to confuse things even more.
Any solutions or advice is much appreciated. I hope the above makes sense! It's very difficult to articulate these things sometimes.
This may or may not be your problem, but in your update_current method, shouldn't it be stock_params.permit(:current_stock, :product_id) ? Also a minor point, why do you have |f| in your form_tag if you don't use it.

Create action always creates two identical table entries instead of one

I have a create action in my ProductsController (the params come from a form in my view):
def create
vendor = #current_vendor
product = Product.create(:name => params[:product][:name])
vendor.products << product
vendor.belongings.create(:product_id => product.id, :count => params[:belonging][:count], :detail => params[:belonging][:detail])
if vendor.save
flash[:notice] = "Produkt hinzugefügt!"
redirect_back_or_default root_url
else
render :action => :new
end
end
It creates a variable "vendor", which stores the currently logged-in vendor (Authlogic)
A new Product is created (the product name is from the input field in the form) and stored in the variable "product"
The "product" is being connected to the current vendor
In the belongings table, additional informations to the product are being stored
it saves the whole thing
It's a many-to-many relationship throught the belongings table.
My problem is, the create action always creates the product twice!
Thanks for your help! :)
My console log when I create a new object through my form is:
Started POST "/products" for 127.0.0.1 at 2013-09-15 20:40:26 +0200
Processing by ProductsController#create as HTML
Parameters: {"utf8"=>"✓", "authenticity_token"=>"lNk/qQMP0xhlCuGgHtU+d5NEvIlCFcPSKB0FxDZH0zY=", "product"=>{"name"=>"Erdbeeren"}, "belonging"=>{"count"=>"20", "detail"=>"Rot"}, "commit"=>"Create"}
DEPRECATION WARNING: ActiveRecord::Base#with_scope and #with_exclusive_scope are deprecated. Please use ActiveRecord::Relation#scoping instead. (You can use #merge to merge multiple scopes together.). (called from current_vendor_session at /Users/reto_gian/Desktop/dici/app/controllers/application_controller.rb:11)
Vendor Load (0.3ms) SELECT "vendors".* FROM "vendors" WHERE "vendors"."persistence_token" = '04f75db0e2ef108ddb0ae1be1da167536d47b4d79c60ecb443ad2ea5717ecd752388e581f9379746568c72372be4f08585aa5581915b1be64dc412cded73a705' LIMIT 1
(0.1ms) begin transaction
SQL (0.8ms) INSERT INTO "products" ("created_at", "name", "updated_at") VALUES (?, ?, ?) [["created_at", Sun, 15 Sep 2013 18:40:26 UTC +00:00], ["name", "Erdbeeren"], ["updated_at", Sun, 15 Sep 2013 18:40:26 UTC +00:00]]
(0.8ms) commit transaction
(0.1ms) begin transaction
SQL (0.6ms) INSERT INTO "belongings" ("created_at", "product_id", "updated_at", "vendor_id") VALUES (?, ?, ?, ?) [["created_at", Sun, 15 Sep 2013 18:40:26 UTC +00:00], ["product_id", 7], ["updated_at", Sun, 15 Sep 2013 18:40:26 UTC +00:00], ["vendor_id", 1]]
(0.9ms) commit transaction
(0.1ms) begin transaction
SQL (0.6ms) INSERT INTO "belongings" ("count", "created_at", "detail", "product_id", "updated_at", "vendor_id") VALUES (?, ?, ?, ?, ?, ?) [["count", "20"], ["created_at", Sun, 15 Sep 2013 18:40:26 UTC +00:00], ["detail", "Rot"], ["product_id", 7], ["updated_at", Sun, 15 Sep 2013 18:40:26 UTC +00:00], ["vendor_id", 1]]
(0.9ms) commit transaction
Redirected to http://localhost:3000/
Completed 302 Found in 30ms (ActiveRecord: 5.1ms)
I think the problem could be in the line
vendor.products << product
this is adding the variable product (which is Product.create(:name => params[:product][:name]) to vendor.products a second time - which is unnecessary and likely the source of your problem

uuid_it : Can't mass-assign protected attributes: uuid

I used uuid_id gem to generate UUID for various models in my application(Rails 3.2.5 with Ruby 1.9.3p194). I correctly followed the steps given here
I am getting this error while creating the model tagged as uuid_it. It works fine if I remove uuid_it call from the model
Here is snapshot of the log
SQL (2.1ms) INSERT INTO "applications" ("created_at", "description", "name", "updated_at") VALUES ($1, $2, $3, $4) RETURNING "id" [["created_at", Mon, 03 Sep 2012 10:17:59 UTC +00:00], ["description", "data mining"], ["name", "BlueBerry"], ["updated_at", Mon, 03 Sep 2012 10:17:59 UTC +00:00]]
Uuid Load (1.2ms) SELECT "uuids".* FROM "uuids" WHERE "uuids"."uuidable_id" = 5 AND "uuids"."uuidable_type" = 'Application' LIMIT 1
(0.2ms) ROLLBACK
Completed 500 Internal Server Error in 81ms
ActiveModel::MassAssignmentSecurity::Error (Can't mass-assign protected attributes: uuid):
app/controllers/applications_controller.rb:13:in `create'
where line 13 is application.create
EDIT
app/controllers/applications.rb
class ApplicationsController < ApplicationController
# some code here
def create
#application = Application.new(params[:application])
#application.creator = current_user
#application.organization = current_organization
if #application.save
redirect_to #application, notice: "Successfully created application."
else
render action: 'new'
end
end
# few lines here
end

Resources