I am building a Order management system. I recently posted a problem about adding a order to a customer. It seems that i have fixed it for 99%. if i look in my terminal it first finds the current customer ID and then creates a new order. The following result is.
Customer Load (0.2ms) SELECT "customers".* FROM "customers" WHERE "customers"."id" = ? LIMIT 1 [["id", 111]]
(0.1ms) begin transaction
SQL (0.4ms) INSERT INTO "orders" ("customer_id", "created_at", "updated_at") VALUES (?, ?, ?) [["customer_id", 111], ["created_at", "2015-11-12 13:28:21.185604"], ["updated_at", "2015-11-12 13:28:21.185604"]]
(8.2ms) commit transaction
But the problem is, it doesn't add the params. I did this intentionally just to check if my syntax would execute the following sql statement. But once i add params i get a common error "param is missing or the value is empty: order"
Here is my code:
Controller
def createorders
#customer = Customer.find(params[:id]) #find current id??
#current_user = Order.find(params[:id])
#orders = #customer.orders.new(order_params)
if #orders.save
flash[:notice] = "Subject created successfully"
redirect_to(:action => 'index')
else
#If save fails, redisplay the form so user can fix problems
render('new') #het zit in de new.html template
end
end
private
def order_params
#same as using "params[:subject]", expect that it:
# - raises an error if :subject is not present
# - allows listed attributes to be mass-assigned
params.require(:order).permit(:pakket, :verstuurt)
end
end
View
<%= link_to("<< Back to List", {:action => 'index'}, :class => 'back-link') %>
<div class="subject new">
<h2>Create Subject</h2>
<%= form_for(:order, :url=> {:action => 'createorders'}) do |f| %>
<table summary="subject form fields">
<tr>
<th>pakket</th>
<td><%= f.text_field(:pakket) %></td>
</tr>
<tr>
<th>verstuurt</th>
<td><%= f.text_field(:verstuurt) %></td>
</tr>
</table>
<div class="form-buttons">
<%= submit_tag("Create Subject") %>
</div>
<% end %>
</div>
Error message
ActionController::ParameterMissing in OrderController#createorders
param is missing or the value is empty: order
Extracted source (around line #107):
105
106
107
108
109
110
def order_params
params.require(:order).permit(:pakket, :verstuurt)
end
end
Serverside Log
Started GET "/order/createorders?id=111" for ::1 at 2015-11-13
11:58:30 +0100 Processing by OrderController#createorders as HTML
Parameters: {"id"=>"111"} Customer Load (0.2ms) SELECT
"customers".* FROM "customers" WHERE "customers"."id" = ? LIMIT 1
[["id", 111]] Completed 400 Bad Request in 5ms (ActiveRecord: 0.2ms)
ActionController::ParameterMissing (param is missing or the value is empty: order): app/controllers/order_controller.rb:107:in
order_params' app/controllers/order_controller.rb:44:in
createorders'
Rendered /Users/cecil/.rbenv/versions/2.2.3/lib/ruby/gems/2.2.0/gems/actionpack-4.2.4/lib/action_dispatch/middleware/templates/rescues/_source.erb
(8.3ms) Rendered
/Users/cecil/.rbenv/versions/2.2.3/lib/ruby/gems/2.2.0/gems/actionpack-4.2.4/lib/action_dispatch/middleware/templates/rescues/_trace.html.erb (2.6ms) Rendered
/Users/cecil/.rbenv/versions/2.2.3/lib/ruby/gems/2.2.0/gems/actionpack-4.2.4/lib/action_dispatch/middleware/templates/rescues/_request_and_response.html.erb
(1.3ms) Rendered
/Users/cecil/.rbenv/versions/2.2.3/lib/ruby/gems/2.2.0/gems/actionpack-4.2.4/lib/action_dispatch/middleware/templates/rescues/diagnostics.html.erb
within rescues/layout (68.2ms) Rendered
/Users/cecil/.rbenv/versions/2.2.3/lib/ruby/gems/2.2.0/gems/web-console-2.2.1/lib/web_console/templates/_markup.html.erb
(0.4ms) Rendered
/Users/cecil/.rbenv/versions/2.2.3/lib/ruby/gems/2.2.0/gems/web-console-2.2.1/lib/web_console/templates/_inner_console_markup.html.erb
within layouts/inlined_string (0.4ms) Rendered
/Users/cecil/.rbenv/versions/2.2.3/lib/ruby/gems/2.2.0/gems/web-console-2.2.1/lib/web_console/templates/_prompt_box_markup.html.erb
within layouts/inlined_string (0.4ms) Rendered
/Users/cecil/.rbenv/versions/2.2.3/lib/ruby/gems/2.2.0/gems/web-console-2.2.1/lib/web_console/templates/style.css.erb
within layouts/inlined_string (0.4ms) Rendered
/Users/cecil/.rbenv/versions/2.2.3/lib/ruby/gems/2.2.0/gems/web-console-2.2.1/lib/web_console/templates/console.js.erb
within layouts/javascript (60.3ms) Rendered
/Users/cecil/.rbenv/versions/2.2.3/lib/ruby/gems/2.2.0/gems/web-console-2.2.1/lib/web_console/templates/main.js.erb
within layouts/javascript (0.3ms) Rendered
/Users/cecil/.rbenv/versions/2.2.3/lib/ruby/gems/2.2.0/gems/web-console-2.2.1/lib/web_console/templates/error_page.js.erb within layouts/javascript (0.5ms) Rendered
/Users/cecil/.rbenv/versions/2.2.3/lib/ruby/gems/2.2.0/gems/web-console-2.2.1/lib/web_console/templates/index.html.erb
(124.2ms)
Thank you stackoverflow for showing me support. I am new with ruby, and i understand i am making noob mistakes. So pointing out flaws are welcome!
I was ignoring your minor, non-fatal issues earlier while I was focused on locating the major issue, but I'll include them now that the major issue is apparent.
First, I'll discuss Rails naming conventions a little bit. You have two models, which are named Customer and Order. You've used the singular form of the noun for these, which is good. Each instance of a model is one thing, so it should be singular. Your controller for the Order model actions, however, should be named with the plural form, so it should be called OrdersController. This is because it controls the actions related to all of your orders. This leads us to your createorders action, which would make a little more sense if it were named createorder, since it only creates one Order. Actually, though, the convention is to name that action create. The action is in your OrdersController, so we already assume that it deals with an Order instance. (When you have Rails automatically generate REST-ful routes for a model's controller with the resources function, it assumes you have an action named create.) Lastly, in your create method, the new Order instance that will be referenced in your view should be called #order instead of #orders, since it contains only one Order.
Now things get a little more complicated. Your param is missing error means exactly that. The parameters for the new Order instance are missing. The request to the server that is producing that error is a GET request that has only one parameter, which you're providing in your URL with ?id=111. Your form's data is not being submitted to the server with that GET request. You should be doing a POST request to create a new Order. I'm going to avoid further exploration (and speculation without seeing your full code) regarding why things aren't working right now and I'll just suggest some key adjustments. It's turning in to a bit a puzzle to figure out how your app works without seeing all of the pieces.
In routes.rb, you should have this line:
resources :customers, :orders
I've made minimal changes to the view you provided, which I assume is called show.html.erb and is in your app/views/customers folder:
<%= link_to("<< Back to List", {:action => 'index'}, :class => 'back-link') %>
<div class="subject new">
<h2>Create Subject</h2>
<%= form_for #order do |f| %>
<table summary="subject form fields">
<tr>
<th>pakket</th>
<td><%= f.text_field(:pakket) %></td>
</tr>
<tr>
<th>verstuurt</th>
<td><%= f.text_field(:verstuurt) %></td>
</tr>
</table>
<%= f.hidden_field :customer_id %>
<div class="form-buttons">
<%= submit_tag("Create Subject") %>
</div>
<% end %>
</div>
Here is the necessary code from customers_controller.rb to support it:
def show
customer = Customer.find params[:id]
#order = customer.orders.new
end
Notice, in the view, the parameter for form_for is the instance that was created in the controller. Also, I've added a hidden field to submit the customer_id with the new Order data.
Finally, your create action in orders_controller.rb might look like this:
def create
#order = Order.new(order_params)
if #order.save
flash[:notice] = "Subject created successfully"
redirect_to(:action => 'index')
else
render 'customers/show'
end
end
And your order_params method should be changed to include the customer_id parameter:
def order_params
params.require(:order).permit(:pakket, :verstuurt, :customer_id)
end
Notice that on a failed save, the action renders customers/show, because this is the page that they were on where the save failed. This will allow Rails to re-populate the form (in the same context) with the data that was present during the failed submission.
Related
I want to be able to delete pictures from my model attached to it.
I'm following the answer of this question https://stackoverflow.com/a/49517939/7295677
Here is my view :
<% #vente.image_vente.each do |image| %>
<tr>
<th><%= image_tag(url_for(image), width: "150", height: "100") %></th>
<th><%= link_to delete_image_attachment_gestion_vente_url(image.signed_id),class: "has-text-white", method: :delete, data: { confirm: "Voulez-vous vraiment supprimer cette image ?" } do%>
<button class="button is-dark">Supprimer l'image</button>
<% end %>
</th>
</tr>
<% end %>
Here is the method of my controller :
def delete_image_attachment
#image = ActiveStorage::Blob.find_signed(params[:id])
puts "-------------------------------"
#image.purge
puts "-------------------------------"
redirect_to action: "index"
end
And here is my route :
resources :gestion_vente do
member do
delete :delete_image_attachment
end
end
The problem is that nothing get deleted and I got this :
TRANSACTION (0.1ms) begin transaction
↳ app/controllers/gestion_vente_controller.rb:53:in `delete_image_attachment'
ActiveStorage::Attachment Exists? (0.5ms) SELECT 1 AS one FROM "active_storage_attachments" WHERE "active_storage_attachments"."blob_id" = ? LIMIT ? [["blob_id", 66], ["LIMIT", 1]]
↳ app/controllers/gestion_vente_controller.rb:53:in `delete_image_attachment'
TRANSACTION (0.1ms) rollback transaction
↳ app/controllers/gestion_vente_controller.rb:53:in `delete_image_attachment'
I think that it rollback the transaction without error message
Edit :
As Corentin Bourdat said I could use :
ActiveStorage:: Attachment.find(params[:id]).destroy
But it left me with something I didn't understood.
In my model I got
has_one_attached :image_principale
has_many_attached :image_vente
I want to only delete an occurence of :image_vente. The problem is that everytime it first delete my :image_principale
It's probably because by searching by id it doesn't care if the attachement is of :image_vente or :image_principale and I don't know how to do it
Why don't you just simply use ActiveStorage::Attachment destroy instead of blobs purge ?
Something like:
ActiveStorage:: Attachment.find(params[:id]).destroy
then add has_many_attached(dependent: :purge)to purge the blob immediately
Found a solution for the problem that could help others :
If you have multiple attachement types like me, it won't forcefully query the right attachement, when I did this :
#image = ActiveStorage::Attachment.find_by(params[:id])
#image.purge
redirect_to action: "index"
It deleted my :image_principale even if I specified the correct id of :image_vente
I corrected it by doing this instead
#image = ActiveStorage::Attachment.find_by(name:"image_vente", id:params[:id])
#image.purge
redirect_to action: "index"
I am stuck in that although my array parameter is being captured, it fails to insert it into the database. I do not get an unpermitted parameters error or anything. It just fails to recognize the array when inserting to the DB.
What I would like to do: Capture any box that is checked off, and insert the data as separate rows into the database.
Here is what I have:
/subscribe/categories/2
<div>
<%= simple_form_for #subscription do |f| %>
<div class="form-inputs">
<%= f.hidden_field :dashboard_id, value: 1 %>
<%= f.hidden_field :category_id, value: #category.id %>
<%= f.collection_check_boxes :feed_id, Feed.where("category_id = ?", #category), :id, :name %>
</div>
<div class="form-actions">
<%= f.button :submit %>
</div>
<% end %>
</div>
CategoriesController
def show
#subscription = Subscription.new
end
SubscriptionsController
def subscription_params
params.require(:subscription).permit(:dashboard_id, :category_id, :feed_id => [])
end
When submitted, here is the console output:
Processing by SubscriptionsController#create as HTML
Parameters: {"utf8"=>"✓", "authenticity_token"=>"Zw2VkwujDLQjV4krjPF8N1EiYo5L/XOrUwedlHCvwB0=", "subscription"=>{"dashboard_id"=>"1", "category_id"=>"2", "feed_id"=>["3", "4", ""]}, "commit"=>"Create Subscription"}
(0.2ms) BEGIN
SQL (1.6ms) INSERT INTO `subscriptions` (`category_id`, `created_at`, `dashboard_id`, `updated_at`) VALUES (2, '2014-01-06 02:17:41', 1, '2014-01-06 02:17:41')
(116.6ms) COMMIT
Redirected to http://localhost:3000/subscriptions/3
Completed 302 Found in 173ms (ActiveRecord: 119.3ms)
Two questions:
Why is there an extra "" for my feed_id array? (Only 2 possible checkboxes)
Why am I not capturing the array to insert it into the database?
Thanks!
The reason your array is not being inserted into the database is that Active Record currently does not support the Postgresql array type. In order to insert these as separate rows the check-boxes need to be represented as individual instances of a model.
Possibly something like...
Category < ActiveRecord::Base
has_many: feeds
...
end
Feed < ActiveRecord::Base
belongs_to: category
...
end
Now this would also mean that you would need to use the form_tag helper instead of the form_for. This would allow you to create a composite form consisting of multiple individual objects. Inserting this would just mean iterating and inserting over each object; giving you separate rows. Hope this helps.
For anyone that wants to know how to do this, here is one solution I've come up with. Everything in my first post remains the same. In my SubscriptionsController (from which the form is created), here is my create action:
def create
dashboard = params[:subscription][:dashboard_id]
category = params[:subscription][:category_id]
feed = params[:subscription][:feed_id]
#subscription = feed.map { |subscribe| Subscription.create(dashboard_id: dashboard, category_id: category, feed_id: subscribe) }
end
Works as advertised. If anyone thinks for some reason that I am overlooking this is a terrible idea, please comment.
I've searched and searched and nothing came up, so I need to ask you guys for help.
I have a simple new form that should take two fields from form_for and then post it into database. The problem is it doesn't.
My sample db has only two fields: name and site_id
Here's my new.html.erb:
<%= form_for #kejsu do |f| %>
<%= f.text_field :name %>
<%= f.text_field :site_id %>
<%= f.submit "Create" %>
<% end %>
Here's the controller:
def new
#kejsu = Kejs.new
end
def create
#kejsu = Kejs.new(params[:kejsu])
if #kejsu.save
redirect_to kejs_index_path
else
render "new"
end
end
After hitting submit button only timestamps are inserted. Here's the snippet from rails server:
Started POST "/cases" for 192.168.56.1 at 2013-12-10 23:11:03 +0000
Processing by KejsyController#create as HTML
Parameters: {"utf8"=>"â", "authenticity_token"=>"Sr2ssiwtRtk9pRT5VfuDFglsEmGnjzwVkRGGBSb2zhA=", "kejs"=> {"name"=>"aa", "site_id"=>"3"}, "commit"=>"Create"}
(0.1ms) begin transaction
SQL (5.1ms) INSERT INTO "kejs" ("created_at", "updated_at") VALUES (?, ?) [["created_at", Tue, 10 Dec 2013 23:11:03 UTC +00:00], ["updated_at", Tue, 10 Dec 2013 23:11:03 UTC +00:00]]
(4.0ms) commit transaction
Redirected to http://192.168.56.101:3000/cases
Completed 302 Found in 14ms (ActiveRecord: 9.2ms)
As you can see those fields are passed as parameters, but INSERT doesn't insert them at all.
I've tried it with default restful routing, writing my own routes and it doesn't work either way.
As a bonus my routes:
get 'cases' => 'kejsy#index', as: :kejs_index
get 'cases/new' => 'kejsy#new', as: :new_kejs
post 'cases' => 'kejsy#create'
Your params[:kejsu] reference uses :kejsu, but your parameters exist under params[:kejs], so you're picking up nil for the value.
The key in params is determined by the class name of the object passed to form_for (i.e. Kejs in this case), not by the variable name (i.e. #kejsu). If you think about it, this makes sense because the variable name is not even available to form_for, since the value of the #kejsu is what is passed.
to debug you can use render :text => params.inspect inside your controller so I will change my code like this
def create
render :text => params.inspect
end
Now go and sumbit your form. What is name of key inside your params? Is it kejsu or kejs?
If its kejs than you can change your code to
def create
#kejsu = Kejs.new(params[:kejs])
if #kejsu.save
redirect_to kejs_index_path
else
render "new"
end
end
As promised, the answer with strong parameters:
def create
#kejsu = Kejs.new(kejs_params)
if #kejsu.save
redirect_to kejs_index_path
else
render "new"
end
end
def kejs_params
params.require(:kejs).permit(:name, :site_id)
end
I needed to change the way I'm dealing with parameters passed via form by creating new method that permits given fields. Now it works like it supposed to.
Thanks for all the hints.
When submitting an answer I get this error:
ActiveRecord::RecordNotFound (Couldn't find Question with ID=answer):
app/controllers/questions_controller.rb:6:in `show'
From what I understand I either made a error with passing an argument from the form or
didn`t define it correctly in my controller.
Would appreciate some help finding this bug, thanks in advance!
Questions_Controller:
class QuestionsController < ApplicationController
def index
end
def show
#question = Question.find(params[:id])
#choices = #question.choices
end
def answer
#choice = Choice.find(:first, :conditions => { :id => params[:id] })
#answer = Answer.create(:question_id => #choice.question_id, :choice_id => #choice.id)
if Question.last == #choice.question
render :action => "thank_you"
else
question = Question.find(:first, :conditions => { :position => (#choice.question.position + 1) })
redirect_to question_path(:id => question.id)
end
end
end
views/questions/show.html.erb :
<div data-role="content">
<div align="center">
<h3><%= #question.question %></h3>
</div>
<br><br>
<ul data-role="listview">
<% #choices.each_with_index do |c, i| %>
<% i = i + 1 %>
<li data-theme="c">
<%= link_to "#{i}. #{c.choice}", answer_questions_path(:id => c.id) %>
</li>
<% end %>
</ul>
</div>
::EDIT::
This happens when I try to select a choice & submit an answer while on the first question.
Started GET "/questions/1" for 127.0.0.1 at Thu Dec 01 01:38:36 -0500 2011
Processing by QuestionsController#show as
Parameters: {"id"=>"1"}
SQL (0.6ms) SELECT name
FROM sqlite_master
WHERE type = 'table' AND NOT name = 'sqlite_sequence'
Question Load (0.3ms) SELECT "questions".* FROM "questions" WHERE "questions"."id" = 1 LIMIT 1
Choice Load (10.8ms) SELECT "choices".* FROM "choices" WHERE ("choices".question_id = 1)
Rendered questions/show.html.erb within layouts/application (28.8ms)
Completed 200 OK in 424ms (Views: 118.0ms | ActiveRecord: 11.6ms)
Started GET "/questions/answer?id=1" for 127.0.0.1 at Thu Dec 01 01:38:38 -0500 2011
Processing by QuestionsController#show as
Parameters: {"id"=>"answer"}
Question Load (0.1ms) SELECT "questions".* FROM "questions" WHERE "questions"."id" = 0 LIMIT 1
Completed in 10ms
ActiveRecord::RecordNotFound (Couldn't find Question with ID=answer):
app/controllers/questions_controller.rb:6:in `show'
Hope this helps.
My best guess is that you don't have a route correctly setup. Assuming that you're using Rails 3 and you're using resources, you need to do add the following:
resources :questions do
member do
put 'answer'
end
end
This will create a route like /questions/#{id}/answer.
Answer is not an HTTP verb, so using resources in your routes will not create a route to your answer action.
Edit based on comment:
First, if you're updating or creating data, you should use put or post. It's a bad idea to modify data on the server with a get. Secondly, I assume that you would be doing an answer per question. If that is the case, you should do the action on a member, not a collection. Also, in your answer action, you have params[:id]. You won't get params[:id] if you try to do an action on a collection rather than a member.
I'm following Ryan Bates, Railscast episode 52 and I've translated relevant parts of the code to work with Rails 3.0.0.beta2. In Ryan's case, he simply marks items incomplete and saves a timestamp. If an Item contains a timestamp the model returns the item in the completed list.
I'm attempting to save ALL values true or false, depending on whether the check_box_tag is selected or not (using boolean). I am able to save ONLY selected items, true or false. How can I save an entire list of items true or false, depending on whether the checkbox is selected? The following is my attempt:
controller logic:
def yardsign
Add.update_all(["yardsign=?", true], :id => params[:yard_ids])
redirect_to adds_path
end
html.erb:
<%= form_tag yardsign_adds_path, :method => :put do %>
<% #adds.each do |add| %>
<td><%= check_box_tag "yard_ids[]", add.id %></td>
<% end %>
<% end %>
routes.rb
resources :adds do
collection do
put :yardsign
end
end
Terminal
Started POST "/adds/yardsign" for 127.0.0.1 at 2010-04-15 19:22:49
Processing by AddsController#yardsign as HTML
Parameters: {"commit"=>"Update", "yardsigntakers"=>["1", "2"], "authenticity_token"=>"3arhsxg/Ky+0W7RNM2T3QditMTJmOnLR5CqmMYWN4Qw="}
User Load (0.3ms) SELECT "users".* FROM "users" WHERE ("users"."id" = 1) LIMIT 1
SQL (1.8ms) UPDATE "adds" SET yardsign='t' WHERE ("adds"."id" IN (1, 2))
Redirected to http://localhost:3000/adds
The HTML specification says unchecked check boxes are not successful, and thus web browsers do not send them
You'll need to do something like the check_box helper does and add a hidden input for unchecked items.