In my app, a micropost is simply called an "item". On each user's "show" page, there should be a form for making a new "item" that belongs to that user.
I am getting stuck making such a form.
When the form is submitted, the controller action below fires:
#user = User.find_by(name: params[:name])
#user.items.create(item_params)
redirect_to 'root'
By the way, the 'item_params' method is
params.require(:item).permit(:title, :content, :user_id)
I am getting an error about the second line. The error is
undefined method 'items' for nil:NilClass
I checked in the rails console whether I could make a new item by first selecting a user by name
#user = User.find_by(name: "tester1")
then create an item for it with the below statement:
#user.items.create(title: "new_item_title", content: "new_item_content")
and the new item was created as expected. I cannot explain the browser error, though.
EDIT
The form in question is on a "show_user". Here is the log for the HTTP request for that page:
Started GET "/center/show_user?utf8=%E2%9C%93&name=tester&commit=Search" for 12
.0.0.1 at 2014-03-19 11:46:51 -0700
Processing by CenterController#show_user as HTML
Parameters: {"utf8"=>"√", "name"=>"tester", "commit"=>"Search"}
←[1m←[35mUser Load (1.0ms)←[0m SELECT "users".* FROM "users" WHERE "users"."
ame" = 'tester' LIMIT 1
Rendered center/show_user.html.erb within layouts/application (2.0ms)
Completed 200 OK in 23ms (Views: 18.7ms | ActiveRecord: 1.0ms)
The form is hosted on this page. Here is the request that is sent with submission of the form:
Started POST "/center/show_user" for 127.0.0.1 at 2014-03-19 11:47:14 -0700
Processing by CenterController#create_item_owned as HTML
Parameters: {"utf8"=>"√", "authenticity_token"=>"P6mb63rhTHx6Q17zhfu4WXErG5Pb0
8t0d/L1RppKAl0=", "item"=>{"title"=>"uno", "content"=>"uno1"}, "commit"=>"Save I
tem"}
←[1m←[36mUser Load (1.0ms)←[0m ←[1mSELECT "users".* FROM "users" WHERE "users
"."name" IS NULL LIMIT 1←[0m
Completed 500 Internal Server Error in 4ms
NoMethodError (undefined method `items' for nil:NilClass):
app/controllers/center_controller.rb:18:in `create_item_owned'
So no information about the user is being passed along with the parameters when the form is submitted. How how I fix this?
Here are my relevant routes:
get "center/show_user/" => 'center#show_user'
post "center/show_user" => 'center#create_item_owned'
The "create_item_owned" action is the one described at the beginning of this question.
The "show_user" action is
#user = User.find_by(name: params[:name])
#new_item = Item.new
How should I forward along those parameters in such a way that the new object created by the form is automatically associated with the specific user in the database (along with automatic creation of foreign keys)?
My form is
<%= form_for :item do |x| %>
Title: <%= x.text_field :title %> <br>
Content: <%= x.text_field :content %> <br>
<%= x.submit %>
<% end %>
I think you might still have to find by id rather than by name. The name might not be passed in the params. You should check your logs to see what params are being sent.
Related
This probably is a nooby one. I'm building a search form.
In the model document.rb, I have this :
pg_search_scope :search_full_text,
:against => :full_text,
:using => {
:tsearch => {
:prefix => true
}
}
and in documents_controller.rb, I have :
def find
$results = Document.search_full_text(params[:ch_acte][:text])
end
But NOTHING gets send to the database. The server log only says:
Started POST "/documents/find" for ::1 at 2017-01-19 08:48:07 +0100
Processing by DocumentsController#find as HTML
Parameters: {"utf8"=>"✓", "authenticity_token"=>"ZkqVYMuqMqnUjLer/FVdBdtv4cycp71dXqPQw6j0mfHKX5ptin7p7YiYFj8bNtjciQDmHzbKtBnZoILpGGvl8Q==", "ch_acte"=>{"text"=>"complet", "words"=>"", #[cut for brievity]}, "commit"=>"Cherche"}
Rendering documents/find.html.erb within layouts/messources
Rendered documents/find.html.erb within layouts/messources (0.4ms)
Completed 200 OK in 216ms (Views: 210.2ms | ActiveRecord: 0.0ms)
Other than the method pg_search_scope in the model and calling that method in the controller, what must I do to get this sent to the database?
When I run Document.search_full_text("esp") in rails console, it works fine.
UPDATE
I added this in documents/find.html.erb :
<% $results.each do |m| %>
<p>The id is <%= m.id %>.</p>
<% end %>
I get an page that displays my menu, and only white after that...
You should understand that Rails tries to be as performant as possible. When you build a search it does NOT execute until you attempt to access the results of the search.
So you would do...
def find
#documents = Document.search_full_text(params[:ch_acte][:text])
end
Then in your find.html.erb you might do...
<% #documents.each do |document| %>
<%= document.name %>
<% end %>
The query is only executed when the #documents.each line is executed to retrieve the documents... i.e. only when it needs to be executed.
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.
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 trying to use accepts_nested_attributes_for on a has_one association model, and getting absolutely nowhere :-(
I have two models, a user and a location. A user has one location:
class User < ActiveRecord::Base
# current location
has_one :location, :dependent => :destroy
accepts_nested_attributes_for :location
end
class Location < ActiveRecord::Base
belongs_to :user
end
I can save changes to the model by using User.find(1).location.current_location_text = "blah" from the console, so I know the associations are set up correctly.
I have two forms on the edit user page. One that updates the main user attributes (and works fine and not shown below) and then this one that allows the user to update an attribute of the location model, called "current_location_text":
<%= form_for(#user) do |f| %>
<%= fields_for(#user.location) do |location_fields| %>
<%= location_fields.label :current_location_text, 'Current Location' %>
<%= location_fields.text_field :current_location_text, :placeholder => 'Road, City or Postcode' %>
<% end %>
<%= f.submit "Update Current Location" %>
<% end %>
This doesn't work. I'm slightly confused as the params sent by the form look incorrect. When the form is submitted, this is in the log:
Started PUT "/users/1" for 127.0.0.1 at 2011-10-08 00:28:05 +0100
Processing by UsersController#update as HTML
Parameters: {"utf8"=>"✓", "authenticity_token"=>"YdTAsXwEvRgXIqri+jfx3dLlYG2XWQTuYkgLDsO/OJw=", "location"=>{"current_location_text"=>"E14 8JS"}, "commit"=>"Update Current Location", "id"=>"1"}
User Load (10.3ms) SELECT `users`.* FROM `users` WHERE `users`.`id` = 1 LIMIT 1
User Load (5.3ms) SELECT `users`.* FROM `users` WHERE `users`.`id` = ? LIMIT 1 [["id", "1"]]
SQL (4.4ms) BEGIN
(2.5ms) COMMIT
Redirected to http://localhost:3000/users/1
Two things that I find bizarre about this:
There's the "COMMIT" message, but with no preceding update string, and no error. eg, if you tried to commit a protected attributed, you'd get the "you can't mass assign..." error message at that point.
The params look wrong to me. The "location" bit is nested as I'd expect, but I'd also expect this to be a nested within the "user" hash, something like this:
{"utf8"=>"✓", "authenticity_token"=>"YdTAsXwEvRgXIqri+jfx3dLlYG2XWQTuYkgLDsO/OJw=", "user"=>{"location"=>{"current_location_text"=>"E14 8JS"}, "commit"=>"Update Current Location", "id"=>"1"}}
I don't think I'm being completely stupid here. Am I missing something really obvious? I've tried adding extra hidden fields to my form, ie a user id, and then I get the user hash, but at the same level as the "location" hash, and not as a parent of it as I'd expect!
Also if it helps, here's my update within my UsersController:
def update
#user = User.find(params[:id])
if #user.update_attributes(params[:user])
redirect_to current_user, :notice => 'User was successfully updated.'
else
render :action => "edit"
end
end
and here's what's in my routes.rb (although I don't think it's relevant):
resources :users do
resource :location
end
Any help appreciated. If I don't solve this, the laptop is going out the window....
Thanks.
<%= fields_for(#user.location) do |location_fields| %>
This is your problem. You need to actually "nest" the fields_for inside your form, like this:
<% f.fields_for(#user.location) do |location_fields| -%>
Try this instead
<%= f.fields_for :location do |location_fields| %>
Rather than giving it the object itself, tell rails what association you want to have it load for