Issue getting ActiveRecord::StatementInvalid on new record - ruby-on-rails

I'm tryint to save information but seems to be hard.
Here my controller /app/controllers/finance_management/voucher_controller.rb
class FinanceManagement::VoucherController < ActionController::Base
def new
#voucher = Voucher.new
end
def create
Voucher.create(params[:voucher])
end
def voucher_params
params.require(:voucher).permit(:voucher_num)
end
end
Here is my model /app/models/voucher.rb
class Voucher < ActiveRecord::Base
end
Here is my view /app/finance_management/voucher/new.html.erb
<%= form_for :obj_voucher, :url => { :controller => "finance_management/voucher", :action => "create" } do |f| %>
Number<%= f.text_field :voucher_num %>
<%= f.submit :submit %>
<% end %>
Here my routes.rb
Rails.application.routes.draw do
namespace :finance_management do
resources :voucher
end
match ':controller(/:action(/:id(.:format)))', via: [:get, :post]
end
Here my logs
Started POST "/finance_management/voucher" for 127.0.0.1 at 2016-01-17 21:00:39 -0500
Processing by FinanceManagement::VoucherController#create as HTML
Parameters: {"utf8"=>"✓", "authenticity_token"=>"222222=", "voucher"=>{"voucher_num"=>"1111"}, "commit"=>"submit"}
(0.1ms) BEGIN
SQL (1.5ms) INSERT INTO `vouchers` (`created_at`, `updated_at`) VALUES ('2016-01-18 02:00:39', '2016-01-18 02:00:39')
Mysql2::Error: Field 'voucher_num' doesn't have a default value: INSERT INTO `vouchers` (`created_at`, `updated_at`) VALUES ('2016-01-18 02:00:39', '2016-01-18 02:00:39')
(0.2ms) ROLLBACK
Completed 500 Internal Server Error in 5ms (ActiveRecord: 1.8ms)
ActiveRecord::StatementInvalid (Mysql2::Error: Field 'voucher_num' doesn't have a default value: INSERT INTO `vouchers` (`created_at`, `updated_at`) VALUES ('2016-01-18 02:00:39', '2016-01-18 02:00:39')):
I tried several ways but cannot save information but got errors:
<%= form_for :user, :url => {:controller=>"finance_management/voucher",:action=>'create'} do |f|%>
<%= form_for #user, :url => {:controller=>"finance_management/voucher",:action=>'create'} do |f|%>
Also changed this:
def create
#voucher= Voucher.create(params[:voucher_params])
end
def voucher_params
params.require(:voucher).permit(:voucher_num)
end
The field is not saving
Mysql2::Error: Field 'voucher_num' doesn't have a default value: INSERT INTO `vouchers` (`created_at`, `updated_at`) VALUES ('2016-01-18 02:00:39', '2016-01-18 02:00:39')

Try:
def create
Voucher.create(voucher_params)
end

ActionController params can't be used in ActiveModel mass assignment directly, you have to use strong parameters instead.

For benefit of the doubt, here's how the code should be structured:
#config/routes.rb
namespace :finance_management do
resources :vouchers
end
#app/controllers/financial_management/vouchers_controller.rb
class FinanceManagement::VouchersController < ActionController::Base
def new
#voucher = Voucher.new
end
def create
#voucher = Voucher.new voucher_params
#voucher.save
end
private
def voucher_params
params.require(:voucher).permit(:voucher_num)
end
end
#app/views/finance_management/vouchers/new.html.erb
<%= form_for [:financial_management, #voucher] do |f| %>
<%= f.text_field :voucher_num, placeholder: "Number" %>
<%= f.submit %>
<% end %>

Related

Having trouble submitting nested resource through form [Rails 5]

I have a Document that has_many Section, and each section has_one Comment. I want to be able to create both sections and comments in the Document show view, but I'm having trouble getting comments to go through.
Here's the relevant code with the closest I've got:
class CommentsController < ApplicationController
def create
#section = Section.find(params[:id])
#section.comment.create(comment_params)
end
private
def comment_params
params.require(:comment).permit(:body)
end
end
The routing:
resources :documents, shallow: true do
resources :sections do
resources :comments
end
end
And the view with the form:
# app/views/documents/show.html.erb
<% #document.sections.each do |section| %>
<%= section.body %>
<% if section.comment %>
<p>
<%= section.comment %>
</p>
<% else %>
<%= form_with url: section_comments_path(section.id), scope: 'comment' do |form| %>
<%= form.text_field :body, placeholder: "Comment" %>
<%= form.submit %>
<% end %>
<% end %>
<% end %>
It all seems to check out for me, but when I try to post a comment, here's what I get:
Started POST "/sections/51/comments" for ::1 at 2019-05-24 23:29:06 +0000
Processing by CommentsController#create as JS
Parameters: {"utf8"=>"✓", "authenticity_token"=>[...], "comment"=>{"body"=>"asdas"}, "commit"=>"Save comment", "section_id"=>"51"}
Section Load (0.5ms) SELECT "sections".* FROM "sections" WHERE "sections"."id" = ? LIMIT ? [["id", 51], ["LIMIT", 1]]
comment Load (0.4ms) SELECT "comments".* FROM "comments" WHERE "comments"."section_id" = ? LIMIT ? [["section_id", 51], ["LIMIT", 1]]
Completed 500 Internal Server Error in 11ms (ActiveRecord: 0.9ms)
NoMethodError (undefined method `create' for nil:NilClass):
app/controllers/comments_controller.rb:4:in `create'
Any ideas?
A has_one relationship returns the object itself. Therefore, #section.comment.create(comment_params) will not work because #section.comment is nil. Instead, try something like...
def create
#section = Section.find(params[:section_id])
#comment = Comment.create(comment_params)
#section.comment = #comment
...
end
Or, as stated in the Rails Guides...
When initializing a new has_one or belongs_to association you must use
the build_ prefix to build the association, rather than the
association.build method that would be used for has_many or
has_and_belongs_to_many associations. To create one, use the create_
prefix.
Which would look like this
def create
#section = Section.find(params[:section_id])
#section.create_comment(comment_params)
...
end
You likely need to change:
#section.comment.create(comment_params)
to:
#section.comments.create(comment_params)
If that doesn't work, try:
#section.comment.create!(comment_params)
and see what the exception says

Issue saving in nested form

I followed thos steps http://railscasts.com/episodes/197-nested-model-form-part-2 and changed purchase_product "survey" and supplier_product as "question" but is not saving and also not saving nested attributes.
Here is the controller /app/controller/purchase_product_controller.rb
class PurchaseProductController < ApplicationController
def new
#purchase = PurchaseProduct.new
1.times do
supplier_product = #purchase.supplier_products.build
end
end
def create
#purchase = PurchaseProduct.new(params[:purchase])
if #purchase.save
flash[:notice] = "Successfully created purchase."
redirect_to :action=>"index"
else
render :action => 'new'
end
end
end
Here models:
class PurchaseProduct < ActiveRecord::Base
has_many :supplier_products
accepts_nested_attributes_for :supplier_products ,:allow_destroy => true
end
class SupplierProduct < ActiveRecord::Base
belongs_to :purchase_product
end
Here is my routes: /config/routes.rb
ActionController::Routing::Routes.draw do |map|
map.root :controller => "purchase_product", :action=>"index"
map.connect ':controller/:action/:id'
map.connect ':controller/:action/:id.:format'
end
Here is the view: /app/view/purchase_product/new.html.erb
<% form_for #purchase, :url => {:controller=>"purchase_product",:action=>'create'}, :html => {:id => 'new_product_form'} do |f| %>
Name: <%= f.text_field :name %>
<% f.fields_for :supplier_products do |builder| %>
<%= render "supplier_product_fields", :f => builder %>
<% end %>
<p><%= link_to_add_fields "Add Supplier Product", f, :supplier_products %></p>
<p><%= f.submit "Submit" %></p>
<% end %>
Here is the partial view: /app/view/purchase_product/_supplier_product_fields.html.erb
<div class="fields">
Type Money: <%= f.select(:type_money,([["%", 0], ["$", 1] ]) ) %>
Cost: <%= f.text_field :amount %><%= link_to_remove_fields "remove", f %>
</div>
But was not saving and got this log:
Processing PurchaseProductController#create (for 127.0.0.1 at 2014-08-06 13:48:31) [POST]
Parameters: {"purchase_product"=>{"name"=>"testing", "supplier_products_attributes"=>{"0"=>{"amount"=>"333", "type_money"=>"0", "_destroy"=>""}}}, "commit"=>"Submit"}
PurchaseProduct Columns (0.6ms) SHOW FIELDS FROM `purchase_products`
SQL (0.1ms) BEGIN
PurchaseProduct Create (0.0ms) Mysql::Error: Column 'name' cannot be null: INSERT INTO `purchase_products` (`name`, `created_at`, `updated_at`) VALUES(NULL, '2014-08-06 18:48:31', '2014-08-06 18:48:31')
SQL (0.1ms) ROLLBACK
ActiveRecord::StatementInvalid (Mysql::Error: Column 'name' cannot be null: INSERT INTO `purchase_products` (`name`, `created_at`, `updated_at`) VALUES(NULL, '2014-08-06 18:48:31', '2014-08-06 18:48:31')):
I solved the problem of saving, changing this param in the view and saved but is not saving the other attributes
Name: <%= text_field_tag "name",#name,:name=>"purchase_product[name]" %>
I got this LOG:
Processing PurchaseProductController#create (for 127.0.0.1 at 2014-08-06 14:00:04) [POST]
Parameters: {"purchase_product"=>{"name"=>"TESTING", "supplier_products_attributes"=>{"0"=>{"amount"=>"100", "type_money"=>"0", "_destroy"=>""}}}, "commit"=>"Submit"}
PurchaseProduct Columns (0.7ms) SHOW FIELDS FROM `purchase_products`
SQL (0.1ms) BEGIN
PurchaseProduct Create (0.3ms) INSERT INTO `purchase_products` (`name`, `created_at`, `updated_at`) VALUES('TESTING', '2014-08-06 19:00:04', '2014-08-06 19:00:04')
SQL (37.0ms) COMMIT
Redirected to http://localhost:3000/
Completed in 44ms (DB: 38) | 302 Found [http://localhost/purchase_product/create]
I spent a long time searching about a solution also I recreated the project several times.
Attributes from supplier products are not saving.
Please somebody can help me with this issue?
In your controller you are grabbing the purchase key from the params hash.
#purchase = PurchaseProduct.new(params[:purchase])
But the parameters you need are actually going to be in params[:purchase_product].
#purchase = PurchaseProduct.new(params[:purchase_product])
When you use the form_for helper, the key will be named after the model which the form is built around. In your case it is a PurchaseProduct, hence why they'll be in params[:purchase_product]

How do I permit date selector attributes in Rails and Formtastic

Latest
I have switched to Simple form. No problem with permitting date attributes there.
Recent attempts
I have put a demo repository on Github illustrating the problem:
This one uses formtastic and displays my problem with:
Unpermitted parameters: date_of_receipt(1i), date_of_receipt(2i), date_of_receipt(3i), date_of_receipt(i)
https://github.com/bigos/permit_date_selector/commit/9f142b79c51e71dca35c988125a2912b83b91972
This one doesn't use formtastic and works fine;
https://github.com/bigos/permit_date_selector/commit/4c53b934ac5cd3f04241bf462e7b677ef5d28335
Initial post
When I try to submit my form I get this message
Unpermitted parameters: date_of_receipt(i)
I have :date_of_receipt in the list of permitted parameters.
My form input selecting the date looks as follows:
<%= f.input :date_of_receipt, as: :date_select %>
Should I give up on formtastic and go back to standard forms?
I've created a fresh Rails app (using Rails 4.1.5 and Formtastic 2.3.1) to try to replicate, and I can't, so I'm closing. Here's what I had:
# Migration
class CreatePosts < ActiveRecord::Migration
def change
create_table :posts do |t|
t.string :title
t.string :body
t.datetime :published_at
t.timestamps
end
end
end
# Model
class Post < ActiveRecord::Base
end
# Controller
class PostsController < ApplicationController
def new
#post = Post.new
end
def create
#post = Post.new(post_params)
if #post.save
redirect_to #post
else
render :new
end
end
def show
#post = Post.find(params[:id])
end
protected
def post_params
params[:post].permit(:title, :body, :published_at)
end
end
# View
<%= semantic_form_for #post do |f| %>
<%= f.inputs do %>
<%= f.input :title %>
<%= f.input :body %>
<%= f.input :published_at %>
<% end %>
<%= f.actions do %>
<%= f.action :submit %>
<% end %>
<% end %>
By simply permitting :published_at, I was able to successfully save a Post into the database with the time I had selected. Here's the development.log:
Started POST "/posts" for 127.0.0.1 at 2014-09-06 21:13:37 +1000
Processing by PostsController#create as HTML
Parameters: {"utf8"=>"✓", "authenticity_token"=>"Jv4Pd7aNgvjkCtzrX+gHNeCNfX3L8t6IpEOEAWzdeIo=", "post"=>{"title"=>"sdfgs", "body"=>"sdgfdfg", "published_at(1i)"=>"2019", "published_at(2i)"=>"1", "published_at(3i)"=>"1", "published_at(4i)"=>"00", "published_at(5i)"=>"01"}, "commit"=>"Create Post"}
(0.1ms) begin transaction
SQL (0.2ms) INSERT INTO "posts" ("body", "created_at", "published_at", "title", "updated_at") VALUES (?, ?, ?, ?, ?) [["body", "sdgfdfg"], ["created_at", "2014-09-06 11:13:37.685160"], ["published_at", "2019-01-01 00:01:00 .000000"], ["title", "sdfgs"], ["updated_at", "2014-09-06 11:13:37.685160"]]
(8.8ms) commit transaction
Redirected to http://localhost:3000/posts/3
Completed 302 Found in 12ms (ActiveRecord: 9.1ms)
There's no extra trickery required, this is how you do it :)
When you inspect the element on the page, you will see three different elements for date_select.
model[date_of_receipt(1i)], model[date_of_receipt(2i)], model[date_of_receipt(3i)]
So you will have to permit
date_of_receipt(1i), date_of_receipt(2i), date_of_receipt(3i)
in your controller

Redirecting from polymorphic association

I have a comments model that belongs to two models: submissions and posts
class Comment < ActiveRecord::Base
attr_accessible :content, :show
belongs_to :commentable, :polymorphic => true
end
class Submission < ActiveRecord::Base
has_many :comments, :as => :commentable, :dependent => :destroy
end
Submissions is a nested route and post is not.
In my comments controller:
def create
#commentable = find_commentable
#comment = #commentable.comments.build(params[:comment])
#comment.user = current_user
if #comment.save
#CommentMailer.comment_email(#user, #comment, #commentable).deliver
flash[:notice] = "Successfully created comment."
if #commentable == #submission
redirect_to [#contest, #commentable]
else
redirect_to [#commentable]
end
else
render :action => 'new'
end
end
find_contest
def find_contest
#contest = Contest.find(params[:contest_id])
end
find_commentable:
def find_commentable
params.each do |name, value|
if name =~ /(.+)_id$/
return $1.classify.constantize.find(value)
end
end
nil
end
The redirect to post via #commentable works fine, but the redirect to submissions is not finding the contest.
Started POST "/submissions/36/comments" for 127.0.0.1 at 2012-11-30 18:34:41 -0800
Processing by CommentsController#create as HTML
Parameters: {"utf8"=>"✓", "authenticity_token"=>"R62NH5/EE34FPapEqy7mfpa0wKz18GtSdhH8MGYq2Ec=", "comment"=>{"content"=>"test", "show"=>"true"}, "commit"=>"Create Comment", "submission_id"=>"36"}
User Load (0.4ms) SELECT "users".* FROM "users" WHERE "users"."id" = 2 ORDER BY users.created_at DESC LIMIT 1
Submission Load (0.3ms) SELECT "submissions".* FROM "submissions" WHERE "submissions"."id" = $1 ORDER BY submissions.created_at DESC LIMIT 1 [["id", "36"]]
Completed 500 Internal Server Error in 116ms
ActiveRecord::RecordNotFound (Couldn't find Contest without an ID):
app/controllers/comments_controller.rb:19:in `create'
Change to submission routes:
submissions GET /submissions(.:format) submissions#index
POST /submissions(.:format) submissions#create
new_submission GET /submissions/new(.:format) submissions#new
edit_submission GET /submissions/:id/edit(.:format) submissions#edit
submission GET /submissions/:id(.:format) submissions#show
PUT /submissions/:id(.:format) submissions#update
DELETE /submissions/:id(.:format) submissions#destroy
Submission form:
<%= simple_form_for #submission, :html => { :multipart => true } do |f| %>
<div class="span7 offset2 submission">
<fieldset class="well pleft80 edit">
<%= f.hidden_field :contest_id , :value => params[:contest_id] %>
<%= f.input :title %>
<%= f.input :description %>
<%= f.input :comment_show, :as => :hidden, :input_html => { :value => true } %>
</fieldset>
<fieldset class="well pleft80 noborder">
<%= f.fields_for :image do |img_field| %>
<h3>Upload Photo<%= img_field.file_field :source %></h3>
<% end %>
</fieldset>
<div class ="form-actions pleft80">
<%= f.submit nil, :class => 'btn btn-primary btn-large' %>
</div>
</div>
<% end %>
You don't need to instantiate or classify anything.
redirect_to #comment.commentable
If you can't do that then you will need to build a global helper module for it and include that into the controller.
module RouteHelpers
def comment_association_redirect_to(comment)
item = comment.commentable
case item.class.to_s
when 'Submission'
redirect_to submission_path(item)
end
end
end
And include it within the ApplicationController:
include RouteHelpers
Then you can call comment_association_redirect_to anywhere in your app (controllers and so on).
I stripped the nested routing out of the app and now it works fine and it's much simpler. Not sure I can think of a good reason to use nested routing when the views must relate the dependencies.

Rails Acts As Messageable setting up Form

I'm trying to use acts as message able gem and I'm following their example controller
SOLVED See Answer
I keep getting this error undefined method `send_message' for nil:NilClass when trying to send a message in the view
How should I adjust my code?
Thanks
View (Form)
<%= simple_form_for ActsAsMessageable::Message.new, :url => messages_path, :method => :post do |f| %>
<%= f.hidden_field :to, value: #gear.user.email %>
<%= f.input :body %>
<%= f.input :topic %>
<%= f.button :submit, class: 'btn' %>
<% end %>
User Model
class User < ActiveRecord::Base
acts_as_messageable :table_name => "messages", # default 'messages'
:required => [:topic, :body], # default [:topic, :body]
:class_name => "ActsAsMessageable::Message", # default "ActsAsMessageable::Message",
:dependent => :nullify # default :nullify
end
Messages Controller
class MessagesController < ApplicationController
def new
#message = ActsAsMessageable::Message.new
end
def create
#to = User.find_by_email(params[:acts_as_messageable_message][:to])
current_user.send_message(#to, params[:acts_as_messageable_message][:topic], params[:acts_as_messageable_message][:body])
end
end
Development Log
Started POST "/messages" for 127.0.0.1 at 2012-11-15 07:23:40 -0600
Processing by MessagesController#create as HTML
Parameters: {"utf8"=>"✓", "authenticity_token"=>"OqaDOP6PldbFVXWPZyijn+887Ym/fDsU0oqzVrL0rQA=", "acts_as_messageable_message"=>{"to"=>"xyz#test.com", "body"=>"test", "topic"=>"test"}, "commit"=>"Create Message"}
[1m[35mUser Load (0.5ms)[0m SELECT `users`.* FROM `users` WHERE `users`.`email` = 'xyz#test.com' LIMIT 1
Completed 500 Internal Server Error in 3ms
NoMethodError (undefined method `send_message' for nil:NilClass):
app/controllers/messages_controller.rb:29:in `create
'
From the error message and provided code seems like your params obj is not formated like you think. Give params[:acts_as_messageable_message] a try instead of [:message]. If that doesn't work check the log to see what is being passed in as params.
I ended up getting it working. The problem ultimately was the gem was using the User model and was expecting the controller to be the User controller not another controller called "Messages". So I simply moved my actions into my Users controller, added the routes and changed the view path, and it now works. #Alex.Bullard thanks for the help.
I'm posting my edits below:
Controller Change
class UsersController < ApplicationController
respond_to :html, :json
def new_message
#message = ActsAsMessageable::Message.new
end
def create_message
#to = User.find_by_email(params[:acts_as_messageable_message][:to])
current_user.send_message(#to, params[:acts_as_messageable_message][:topic], params[:acts_as_messageable_message][:body])
redirect_to :back, notice: "Message sent to Owner"
end
end
View
<%= simple_form_for ActsAsMessageable::Message.new, :url => create_message_users_path, :method => :post do |f| %>
<%= f.hidden_field :to, value: #gear.user.email %>
<%= f.input :body %>
<%= f.input :topic %>
<%= f.button :submit, class: 'btn' %>
<% end %>
Routes
resources :users, :except => [ :create, :new ] do
get "new_message", :on => :collection
post "create_message", :on => :collection
resources :store
end

Resources