NoMethodError for child object in nested form - ruby-on-rails

I am trying to create two objects from one nested form in Rails, recipe which has_many :ingredients.
When I submit the form, Rails returns an error:
undefined method `ingredient' for #<Ingredient id: nil, ing: "a", amount: "a", recipe_id: nil> Did you mean? increment
Specifically pointing out the error in my create action:
#recipe = Recipe.new(recipe_params)
# #recipe.user_id = session[:user_id]
#recipe.save
redirect_to recipe_path(#recipe)
end
I suspect my problem is in model associations.
Full trace:
Started POST "/recipes" for ::1 at 2016-12-19 13:53:06 -0600
Processing by RecipesController#create as HTML
Parameters: {"utf8"=>"✓", "authenticity_token"=>"wmdURAmdmdHrbrW3+0z5MvEIOs7hY5QBfzKG/L1PSgFKJPRHbFQlGMpBYeIwYdnRxPprsEKk1HT7qQNbSOo42Q==",
"recipe"=>{"name"=>"adsfadsfa",
"steps"=>"a",
"ingredients_attributes"=>{"0"=>{"ing"=>"a", "amount"=>"a"}}},
"commit"=>"Add"}
ActionController::Parameters {"name"=>"adsfadsfa",
"steps"=>"a",
"ingredients_attributes"=>
<ActionController::Parameters
{"0"=><ActionController::Parameters
{"ing"=>"a", "amount"=>"a"} permitted: true>} permitted: true>} permitted: true>
(0.1ms) begin transaction
(0.1ms) rollback transaction
Completed 500 Internal Server Error in 47ms (ActiveRecord: 0.3ms)
app/controllers/recipes_controller.rb:13:in `create'
Rendering /Users/JCamp1991/.rvm/gems/ruby-2.3.1/gems/actionpack-5.0.0.1/lib/action_dispatch/middleware/templates/rescues/diagnostics.html.erb within rescues/layout
Rendering /Users/JCamp1991/.rvm/gems/ruby-2.3.1/gems/actionpack-5.0.0.1/lib/action_dispatch/middleware/templates/rescues/_source.html.erb
Rendered /Users/JCamp1991/.rvm/gems/ruby-2.3.1/gems/actionpack-5.0.0.1/lib/action_dispatch/middleware/templates/rescues/_source.html.erb (11.0ms)
Rendering /Users/JCamp1991/.rvm/gems/ruby-2.3.1/gems/actionpack-5.0.0.1/lib/action_dispatch/middleware/templates/rescues/_trace.html.erb
Rendered /Users/JCamp1991/.rvm/gems/ruby-2.3.1/gems/actionpack-5.0.0.1/lib/action_dispatch/middleware/templates/rescues/_trace.html.erb (5.6ms)
Rendering /Users/JCamp1991/.rvm/gems/ruby-2.3.1/gems/actionpack-5.0.0.1/lib/action_dispatch/middleware/templates/rescues/_request_and_response.html.erb
Rendered /Users/JCamp1991/.rvm/gems/ruby-2.3.1/gems/actionpack-5.0.0.1/lib/action_dispatch/middleware/templates/rescues/_request_and_response.html.erb (3.6ms)
Rendered /Users/JCamp1991/.rvm/gems/ruby-2.3.1/gems/actionpack-5.0.0.1/lib/action_dispatch/middleware/templates/rescues/diagnostics.html.erb within rescues/layout (153.7ms)
Rendering /Users/JCamp1991/.rvm/gems/ruby-2.3.1/gems/web-console-3.1.1/lib/web_console/templates/index.html.erb
Rendered /Users/JCamp1991/.rvm/gems/ruby-2.3.1/gems/web-console-3.1.1/lib/web_console/templates/_markup.html.erb (1.0ms)
Rendering /Users/JCamp1991/.rvm/gems/ruby-2.3.1/gems/web-console-3.1.1/lib/web_console/templates/console.js.erb within layouts/javascript
Rendering /Users/JCamp1991/.rvm/gems/ruby-2.3.1/gems/web-console-3.1.1/lib/web_console/templates/_inner_console_markup.html.erb within layouts/inlined_string
Rendered /Users/JCamp1991/.rvm/gems/ruby-2.3.1/gems/web-console-3.1.1/lib/web_console/templates/_inner_console_markup.html.erb within layouts/inlined_string (0.9ms)
Rendering /Users/JCamp1991/.rvm/gems/ruby-2.3.1/gems/web-console-3.1.1/lib/web_console/templates/_prompt_box_markup.html.erb within layouts/inlined_string
Rendered /Users/JCamp1991/.rvm/gems/ruby-2.3.1/gems/web-console-3.1.1/lib/web_console/templates/_prompt_box_markup.html.erb within layouts/inlined_string (1.0ms)
Rendering /Users/JCamp1991/.rvm/gems/ruby-2.3.1/gems/web-console-3.1.1/lib/web_console/templates/style.css.erb within layouts/inlined_string
Rendered /Users/JCamp1991/.rvm/gems/ruby-2.3.1/gems/web-console-3.1.1/lib/web_console/templates/style.css.erb within layouts/inlined_string (1.0ms)
Rendered /Users/JCamp1991/.rvm/gems/ruby-2.3.1/gems/web-console-3.1.1/lib/web_console/templates/console.js.erb within layouts/javascript (116.1ms)
Rendering /Users/JCamp1991/.rvm/gems/ruby-2.3.1/gems/web-console-3.1.1/lib/web_console/templates/main.js.erb within layouts/javascript
Rendered /Users/JCamp1991/.rvm/gems/ruby-2.3.1/gems/web-console-3.1.1/lib/web_console/templates/main.js.erb within layouts/javascript (0.9ms)
Rendered /Users/JCamp1991/.rvm/gems/ruby-2.3.1/gems/web-console-3.1.1/lib/web_console/templates/index.html.erb (229.6ms)
recipes_controller.rb:
...
def create
#recipe = Recipe.new(recipe_params)
#recipe.user_id = session[:user_id]
#recipe.save
redirect_to recipe_path(#recipe)
end
...
def recipe_params
params.require(:recipe).permit(:name, :steps, ingredients_attributes: [:ing, :amount])
end
Models:
class Ingredient < ApplicationRecord
belongs_to :recipe
...
end
class Recipe < ApplicationRecord
...
has_many :ingredients
accepts_nested_attributes_for :ingredients
validates_associated :ingredients
...
end
New recipe form:
<%= form_for #recipe do |f| %>
<h1>
<%= f.label :name %><br>
<%= f.text_field :name %><br>
</h1>
<h1>
<%= f.label :steps %><br>
<%= f.text_area :steps %><br>
</h1>
<%= f.fields_for :ingredients do |p| %>
<h1>
<%= p.label :ing %><br>
<%= p.text_area :ing %><br>
</h1>
<h1>
<%= p.label :amount %><br>
<%= p.text_area :amount %><br>
</h1>
<% end %>
<%= f.submit "Add" %><br>
Included in routes.rb:
resources :users do
resources :recipes
end
resources :recipes do
resources :ingredients
end
Github Repo for entire project:
https://github.com/jlcampbell1991/recipe-box

Ingredient model probably shouldn't have an ingredient attribute. What about name?
It also doesn't seem to be consistent between migrations
t.string :ing
and Model :
validates :ingredient, presence: true

Related

How to display date variables on site using Ruby on Rails?

I wanted to display my time variables to see when pass has started and when will it end but don't know how and couldn't find solution.
I tried something very simple but it doesn't work:
show.html.erb
<h1><%= #pass.name %></h1>
<p><%= #pass.valid_from %></p>
<p><%= #pass.valid_until %></p>
create_passes.rb migration
class CreatePasses < ActiveRecord::Migration[7.0]
def change
create_table :passes do |t|
t.time :valid_from
t.time :valid_until
t.boolean :is_time_limited
t.integer :entries_left
t.string :name
t.timestamps
end
end
end
passes_controller.rb
class PassesController < ApplicationController
def index
#passes = Pass.all
end
def show
#pass = Pass.find(params[:id])
end
def new
#pass = Pass.new
end
def create
#pass = Pass.new(pass_params)
if #pass.save
redirect_to #pass
else
render :new, status: :unprocessable_entity
end
end
def edit
#pass = Pass.find(params[:id])
end
def update
#pass = Pass.find(params[:id])
if #pass.update(pass_params)
redirect_to #pass
else
render :edit, status: :unprocessable_entity
end
end
def destroy
#pass = Pass.find(params[:id])
#pass.destroy
redirect_to root_path, status: :see_other
end
private
def pass_params
params.require(:pass).permit(:name, :is_time_limited, :valid_from, :valid_until, :entries_left)
end
end
new/edit pass form view
<%= form_with model: #pass do |form| %>
<div>
<%= form.label :name %><br>
<%= form.text_field :name %>
<% #pass.errors.full_messages_for(:name).each do |message| %>
<div><%= message %></div>
<% end %>
</div>
<div>
<%= form.label :valid_from %><br>
<%= form.date_field :valid_from %>
<% #pass.errors.full_messages_for(:name).each do |message| %>
<div><%= message %></div>
<% end %>
</div>
<div>
<%= form.label :valid_until %><br>
<%= form.date_field :valid_until %>
<% #pass.errors.full_messages_for(:name).each do |message| %>
<div><%= message %></div>
<% end %>
</div>
<div>
<%= form.submit %>
</div>
<% end %>
rails server log
Started GET "/passes/2" for ::1 at 2022-08-10 18:18:18 +0200
Processing by PassesController#show as HTML
Parameters: {"id"=>"2"}
(0.1ms) SELECT sqlite_version(*)
↳ app/controllers/passes_controller.rb:7:in `show'
Pass Load (0.2ms) SELECT "passes".* FROM "passes" WHERE "passes"."id" = ? LIMIT ? [["id", 2], ["LIMIT", 1]]
↳ app/controllers/passes_controller.rb:7:in `show'
Rendering layout layouts/application.html.erb
Rendering passes/show.html.erb within layouts/application
Rendered layouts/_navbar.html.erb (Duration: 1.0ms | Allocations: 724)
Rendered passes/show.html.erb within layouts/application (Duration: 2.8ms | Allocations: 1670)
Rendered layout layouts/application.html.erb (Duration: 6.9ms | Allocations: 4039)
Completed 200 OK in 31ms (Views: 7.5ms | ActiveRecord: 0.5ms | Allocations: 5333)
Also, is it better to use time or datatime type for dates and time?
Ok I believe I know why you are not getting any values.
You setup your DB to use a time field
t.time :valid_from
t.time :valid_until
But you are using a date_field in the view:
form.date_field :valid_from
You need to change this to:
form.time_field :valid_from
The difference between time or datetime is datetime includes a DATE and a TIME, where TIME ONLY has a time so it depends on what your use case is. You can also use just a date and then it would be
form.date_field :valid_from
If you need dates you will need to change your model and DB to use either t.date or t.datetime. If you don't have a lot of information in your DB you can do a rails db:rollback and modify your migration file would be the quickest and easiest way to fix it. IF you DO have data you will have to create a new migration to change the fields.

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

Rails 4: render controller/action again when validation fails

There are already a couple of questions addressing this issue:
render/redirect to new action when validation fails (rails)
Keeping validation errors after redirect from partial back to the same page that has the partial
I tried to implement some of the solutions recommended but did not manage fixing my issue.
So here we go.
In my Rails 4 app, there are four models:
class User < ActiveRecord::Base
has_many :administrations
has_many :calendars, through: :administrations
has_many :invitations, :class_name => "Invite", :foreign_key => 'recipient_id'
has_many :sent_invites, :class_name => "Invite", :foreign_key => 'sender_id'
end
class Calendar < ActiveRecord::Base
has_many :administrations
has_many :users, through: :administrations
has_many :invites
end
class Administration < ActiveRecord::Base
belongs_to :user
belongs_to :calendar
end
class Invite < ActiveRecord::Base
belongs_to :calendar
belongs_to :sender, :class_name => 'User'
belongs_to :recipient, :class_name => 'User'
end
Here, we are going to focus on the Invite and the Calendar models.
In the calendar edit view, I have a form to create a new invite:
<h2>Edit <%= #calendar.name %> calendar</h2>
<%= render 'form' %>
<h2>Invite new users to <%= #calendar.name %> calendar</h2>
<%= form_for #invite , :url => invites_path do |f| %>
<%= f.hidden_field :calendar_id, :value => #invite.calendar_id %>
<%= f.label :email %>
<%= f.email_field :email %>
<%= f.label "Role" %>
<%= f.radio_button(:recipient_role, "Editor") %>
<%= f.label "Editor" %>
<%= f.radio_button(:recipient_role, "Viewer") %>
<%= f.label "Viewer" %>
<%= f.submit 'Send' %>
<% end %>
<%= link_to 'Show', calendar_path %> |
<%= link_to 'Back', calendars_path %>
–––––
UPDATE: please note that I have defined a calendars.html.erb layout for my calendar views, including the following code to display alerts:
<% flash.each do |key, value| %>
<div class="alert alert-<%= key %>">
<%= value %>
</div>
<% end %>
–––––
In the Invite model, I want to validate the presence of :email and :recipient_role (both values submitted by the user through the form), so I added this to the Invite model:
validates :email, :recipient_role, presence: true
And I would like users to be redirected to the form with an error message if they forgot to fill one of these two fields, which I implemented with the following code in the InvitesController:
class InvitesController < ApplicationController
def create
# some code
if #invite.save
# some code
else
format.html { render :template => "calendars/edit", notice: 'Invitation could not be sent.' }
end
redirect_to calendar_path(#calendar), notice: 'Invitation was successfully sent.'
end
private
def invite_params
params.require(:invite).permit(:email, :calendar_id, :recipient_role)
end
end
In particular, I thought that the line format.html { render :template => "calendars/edit", notice: 'Invitation could not be sent.' } would allow me to do what I wanted, as recommended here.
However, when I try to submit the form with at least an empty field, I get the following error:
ArgumentError in InvitesController#create
too few arguments
end
else
format.html { render :template => "calendars/edit", notice: 'Invitation could not be sent.' }
end
redirect_to calendar_path(#calendar), notice: 'Invitation was successfully sent.'
end
And this is the server log:
Processing by InvitesController#create as HTML
Parameters: {"utf8"=>"✓", "authenticity_token"=>"p+yxM9Tw3JiNw/6Chv9//N8uvWhMy0TqrudTu0y9D9zXCl6kK2LtCqPu1rvTGv5gOMBuv2RK/IX2MBpWUTelZw==", "invite"=>{"calendar_id"=>"3", "email"=>"test#example.com"}, "commit"=>"Send"}
User Load (0.2ms) SELECT "users".* FROM "users" WHERE "users"."id" = ? ORDER BY "users"."id" ASC LIMIT 1 [["id", 1]]
Calendar Load (0.1ms) SELECT "calendars".* FROM "calendars" WHERE "calendars"."id" = ? LIMIT 1 [["id", 3]]
(0.0ms) begin transaction
(0.0ms) rollback transaction
Completed 500 Internal Server Error in 27ms (ActiveRecord: 1.3ms)
ArgumentError (too few arguments):
app/controllers/invites_controller.rb:16:in `format'
app/controllers/invites_controller.rb:16:in `create'
Rendered /Users/TXC/.rvm/gems/ruby-2.2.1#global/gems/actionpack-4.2.2/lib/action_dispatch/middleware/templates/rescues/_source.erb (3.7ms)
Rendered /Users/TXC/.rvm/gems/ruby-2.2.1#global/gems/actionpack-4.2.2/lib/action_dispatch/middleware/templates/rescues/_trace.html.erb (1.5ms)
Rendered /Users/TXC/.rvm/gems/ruby-2.2.1#global/gems/actionpack-4.2.2/lib/action_dispatch/middleware/templates/rescues/_request_and_response.html.erb (0.9ms)
Rendered /Users/TXC/.rvm/gems/ruby-2.2.1#global/gems/actionpack-4.2.2/lib/action_dispatch/middleware/templates/rescues/diagnostics.html.erb within rescues/layout (54.0ms)
Rendered /Users/TXC/.rvm/gems/ruby-2.2.1/gems/web-console-2.2.1/lib/web_console/templates/_markup.html.erb (0.3ms)
Rendered /Users/TXC/.rvm/gems/ruby-2.2.1/gems/web-console-2.2.1/lib/web_console/templates/_inner_console_markup.html.erb within layouts/inlined_string (0.3ms)
Rendered /Users/TXC/.rvm/gems/ruby-2.2.1/gems/web-console-2.2.1/lib/web_console/templates/_prompt_box_markup.html.erb within layouts/inlined_string (0.4ms)
Rendered /Users/TXC/.rvm/gems/ruby-2.2.1/gems/web-console-2.2.1/lib/web_console/templates/style.css.erb within layouts/inlined_string (0.3ms)
Rendered /Users/TXC/.rvm/gems/ruby-2.2.1/gems/web-console-2.2.1/lib/web_console/templates/console.js.erb within layouts/javascript (36.5ms)
Rendered /Users/TXC/.rvm/gems/ruby-2.2.1/gems/web-console-2.2.1/lib/web_console/templates/main.js.erb within layouts/javascript (0.2ms)
Rendered /Users/TXC/.rvm/gems/ruby-2.2.1/gems/web-console-2.2.1/lib/web_console/templates/error_page.js.erb within layouts/javascript (0.5ms)
Rendered /Users/TXC/.rvm/gems/ruby-2.2.1/gems/web-console-2.2.1/lib/web_console/templates/index.html.erb (83.2ms)
What am I doing wrong?
Do the following things please
def create
# some code
if #invite.save
redirect_to calendar_path(#calendar), notice: 'Invitation was successfully sent.'
else
render template: "calendars/edit", notice: 'Invitation could not be sent.'
end
end

Rails not updating attribute

Pretty standard update in my opinion, but upon submitting the put request, the attribute is not updated. Here is my relevant model:
class Vendor < ActiveRecord::Base
geocoded_by :address
after_validation :geocode,
:if => lambda{ |obj| obj.address_changed? }
end
My controller methods:
def edit
#vendor = Vendor.find(params[:id])
end
def update
#vendor = Vendor.find(params[:id])
if #vendor.update_attributes(vendor_params)
redirect_to vendors_mgmt_path
else
render 'edit'
end
end
def vendor_params
params.permit(:id, :name, :address, :image, :latitude, :longituded )
end
I see this in the server log after trying to update:
Started PUT "/vendors/1" for 127.0.0.1 at 2013-10-20 20:44:54 -0700
Processing by VendorsController#update as HTML
Parameters: {"utf8"=>"✓", "authenticity_token"=>"fTbZVEfckQz4xQzY5xSMQCArrGZqymNsVeyic/PXKcE=", "vendor"=>{"name"=>"Store", "address"=>"1221 E. Main St."}, "commit"=>"Save changes", "id"=>"1"}
User Load (0.3ms) SELECT "users".* FROM "users" WHERE "users"."id" = 1 LIMIT 1
Vendor Load (0.2ms) SELECT "vendors".* FROM "vendors" WHERE "vendors"."id" = ? LIMIT 1 [["id", "1"]]
Unpermitted parameters: utf8, _method, authenticity_token, vendor, commit
(0.1ms) begin transaction
(0.1ms) commit transaction
Redirected to http://localhost:3000/vendors/mgmt
Completed 302 Found in 10ms (ActiveRecord: 0.6ms)
This confuses me, because the Vendor form looks like so, and has no authenticity token etc.
<h1>Update <%= "#{#vendor.name}" %></h1>
<%= form_for(#vendor) do |f| %>
<%= f.label :name %>
<%= f.text_field :name %>
<%= f.label :address %>
<%= f.text_field :address %>
<%= f.label :Logo %>
<%= f.file_field :image %>
<%= f.submit "Save changes", class: "btn btn-success" %>
<% end %>
Anyone see any glaring errors? Any help is much appreciated. Thanks in advance!
Rails by default includes certain hidden fields in all forms, such as the authenticity_token, which is present to stop CSRF. (More info here) I would recommend changing the line:
params.permit(:id, :name, :address, :image, :latitude, :longituded )
to:
params.require(:vendor).permit(:id, :name, :address, :image, :latitude, :longituded)
Changing this line in your controller should permit the other parameters that are submitted by the form, not just the ones in the vendor param.
Also, you misspelled "longitude", I'm not sure if that's causing any additional trouble or if it's just a typo in your question instead.

Why am I getting argument out of range exception

Im a rails beginner on Rails 4. Im trying to create a wine list that takes the name of the winery and the year of the bottle. Here is my form
<%= form_for #wine do |f| %>
<%# render "errors", object: #wine %>
<div class="form-group input-group input-group-lg">
<%= f.text_field :name, placeholder: "Enter the winery name", class: "form-control input-lg" %>
</div>
<div class="form-group input-group input-group-lg">
<%= select_year(Date.today, start_year: Time.now.year, end_year: Time.now.year - 90, field_name: :year, prefix: :wine) %>
</div>
<div class="form_group input-group">
<%= f.submit "Add wine", class: "btn btn-success" %>
</div>
<% end %>
Here is my controller
class WinesController < ApplicationController
before_action :set_wine, only: [:show, :edit, :update, :destroy]
def index
#wines = Wine.all
end
def new
#wine = Wine.new
end
def create
#wine = Wine.new(wine_params)
if #wine.save
flash[:notice] = "Successfully created..."
redirect_to #wine
else
flash.now[:error] = "There was a problem"
render "new"
end
end
def show
end
def edit
end
def update
if #wine.update(wine_params)
redirect_to #wine
else
flash[:error] = "Something went wrong"
render "edit"
end
end
def destroy
#wine.destroy
redirect_to wines_path
end
private
def set_wine
#wine = Wine.find(params[:id])
end
def wine_params
params.require(:wine).permit(:name, :year)
end
end
I have my wines table with a name:string column and a year:datetime column
Whenever I try and create a new wine I get an argument out of range exception and it highlights #wine = Wine.new(wine_params) in my create action. What am I doing wrong?
My log
Started GET "/wines/new" for 127.0.0.1 at 2013-09-04 10:55:54 -0700
Processing by WinesController#new as HTML
Rendered wines/_form.html.erb (2.0ms)
Rendered wines/new.html.erb within layouts/application (2.6ms)
Rendered layouts/_header.html.erb (0.2ms)
Rendered layouts/_footer.html.erb (0.1ms)
Completed 200 OK in 10ms (Views: 9.3ms | ActiveRecord: 0.0ms)
Started GET "/assets/comingsoonbg.png" for 127.0.0.1 at 2013-09-04 10:55:54 -0700
Started GET "/wines/new" for 127.0.0.1 at 2013-09-04 10:55:54 -0700
Processing by WinesController#new as HTML
Rendered wines/_form.html.erb (2.1ms)
Rendered wines/new.html.erb within layouts/application (2.7ms)
Rendered layouts/_header.html.erb (0.2ms)
Rendered layouts/_footer.html.erb (0.1ms)
Completed 200 OK in 10ms (Views: 9.8ms | ActiveRecord: 0.0ms)
Started POST "/wines" for 127.0.0.1 at 2013-09-04 10:55:59 -0700
Processing by WinesController#create as HTML
Parameters: {"utf8"=>"✓", "authenticity_token"=>"FCd3wvCov+mugnJuzwplKD/eVskJKgxweh1mK0pG2wM=", "wine"=>{"name"=>"kjkljhk", "year"=>"2013"}, "commit"=>"Add wine"}
Completed 500 Internal Server Error in 1ms
ArgumentError (argument out of range):
app/controllers/wines_controller.rb:13:in `create'
Rendered /Users/me/.rvm/gems/ruby-2.0.0-p247/gems/actionpack-4.0.0/lib/action_dispatch/middleware/templates/rescues/_source.erb (0.7ms)
Rendered /Users/me/.rvm/gems/ruby-2.0.0-p247/gems/actionpack-4.0.0/lib/action_dispatch/middleware/templates/rescues/_trace.erb (0.9ms)
Rendered /Users/me/.rvm/gems/ruby-2.0.0-p247/gems/actionpack-4.0.0/lib/action_dispatch/middleware/templates/rescues/_request_and_response.erb (0.9ms)
Rendered /Users/me/.rvm/gems/ruby-2.0.0-p247/gems/actionpack-4.0.0/lib/action_dispatch/middleware/templates/rescues/diagnostics.erb within rescues/layout (16.2ms)
My schema for wines in schema.rb
create_table "wines", force: true do |t|
t.datetime "year"
t.datetime "created_at"
t.datetime "updated_at"
t.string "name"
end
Date and Time always require me to think twice! In the log, params contains a string with the year from the select_year. The simplest solution was to just store the integer representation, if all you'll need are years. If you later change to select_date, you'll need to build a Date object in your controller by extracting the parts from the params hash. See Form Helpers Guide for more detail... well, here is just a bit.
In the view:
<%= select_date Date.today, prefix: :start_date %>
In the controller, to make your Date object:
Date.civil(params[:start_date][:year].to_i, params[:start_date][:month].to_i, params[:start_date][:day].to_i)
ActiveRecord expects an attribute to have one entry in the params hash, but Date objects require multiple values. The date helper date_select (not select_date) will pass back a hash that Rails will convert, with multiparameter assignment, to a Date during mass assignment.
<%= date_select :person, :birth_date %>
If you used date_select, you's see something like this in the params hash:
{:person => {'birth_date(1i)' => '2008', 'birth_date(2i)' => '11', 'birth_date(3i)' => '22'}}
Notice the keys in the :person hash describe the order and type of the multipart object so that Rails can figure out how to create the attribute (for example, the hash key birth_date(2i) is the second component of the birth_date attribute in a Person model object and is an integer).

Resources