I have spent the past few hours trying to figure out what I am doing wrong, but I cannot come to a solution. Simply put, I am trying to populate a select box with data from a table called 'semesters'. (I've seen tons of questions regarding this on SO, but I cannot get them to work with my app).
Here's what I have:
Courses Controller
class CoursesController < ApplicationController
def create
#semesters = Semester.all()
#course = Course.new(params[:course])
# Save the object
if #course.save
flash[:notice] = "Course created."
redirect_to(:action => 'list')
else
# If save fails, redisplay the form so user can fix problems
render('new')
end
end
end
View
#views/courses/new.html.erb
<%= form_for(:course, :url => {:action => 'create'}) do |f| %>
<%= f.select(:semester, #semesters.map { |s| [ s.name, s.id ] }) %>
<%= submit_tag("Create Course") %>
<% end %>
I was hoping it would output:
<select>
<option id="1">Spring 2013</option>
<option id="2">Fall 2013</option>
</select>
But instead, I am getting the error:
views/courses/new.html.erb where line #32 raised:
undefined method `map' for nil:NilClass
Line #32 corresponds to my form helper select.
Any help on this would be great!
You should set your #semesters variable in controller:
def new
#semesters = Semester.all
end
The error occurs because unset instance variable is evaluated to nil, so you try to call map method on nil object.
Related
I am trying to create a destination, but it keeps telling me in my browser that 'name' is nil when it redirects redirects to my 'show' view.
Error I receive
undefined method `name' for nil:NilClass
Here are my controller actions for new, create, and show:
def show
#destination = Destination.find_by(id: params[:id])
end
def new
#destination = Destination.new
end
def create
#destination = Destination.create(dest_params)
redirect_to user_destination_path(current_user, #destination.id )
end
private
def dest_params
params.require(:destination).permit(:name,:user_id)
end
My new form where I enter the name of the destination:
<h2>Add a destination</h2>
<div>
<%= form_for #destination do |f|%>
<%= f.label :name %>
<%= f.text_field :name %><br>
<%= f.submit %>
<% end %>
</div>
here is my read/show view:
<h3>Added destination</h3>
<div>
<p><%= #destination.name %></p>
</div>
Before all this I was getting missing required keys [:id] errors, but I seemed to fix that but for some reason I suspect that might have something to do with the issue I am having now. Let me know if you are able to spot the issue
Updated Error
No route matches {:action=>"show", :controller=>"destinations", :id=>nil, :user_id=>"1"}, missing required keys: [:id]
The main problem here is a total lack of error handling. You're not checking at all if the user provided valid input or if the record was even saved in your create method.
def create
#destination = Destination.create(dest_params)
redirect_to user_destination_path(current_user, #destination.id )
end
If the record is not saved for example due to a failed validation #destination.id is nil.
In your show method you're using find_by instead of find which just lets the error slide instead of raising a ActiveRecord::RecordNotFound error.
Your controller should actually look like:
class DestinationsController
def show
# will raise if the record is not found and return a 404 not found response
# instead of just exploding
#destination = Destination.find(params[:id])
end
def new
#destination = Destination.new
end
def create
# never just assume that the record is created unless you want
# to get kicked in the pants.
#destination = Destination.new(dest_params)
if #destination.save
# this route really does not need to be nested.
# see https://guides.rubyonrails.org/routing.html#shallow-nesting
redirect_to user_destination_path(current_user, #destination)
else
# re-render the form with errors
render :new
end
end
private
def dest_params
params.require(:destination).permit(:name,:user_id)
end
end
I'm trying to archive a Product by using a link_to in Rails 5.
In the view:
<% #products.each do |product| %>
<%= link_to product_path(product, "product[archived]" => true),
:method => :put,
data: { confirm: 'Sure?' } do %>
<i class="fa fa-archive color-danger" aria-hidden="true"></i>
<% end %>
<% end %>
But after clicking on the link my ProductsController throws the following error:
undefined method `to_sym' for {:archived=>false}:Hash Did you mean? to_s to_yaml to_set
The error points to the if #product.update(product_params) line. Full update method is:
def update
#product = Product.find(params[:id])
puts #product.id
if #product.update(product_params)
redirect_to #product
else
render 'edit'
end
end
EDIT
Actually the offending line was a badly written validation in my Product model.
I had: validates_uniqueness_of :code, :scope => [:archived => false], where it should have been validates_uniqueness_of :code, conditions: -> { where.not(archived: true) }.
In hindsight it was a silly mistake, but now I'm wondering why it was throwing such a strange error and worse, the error was in the controller...
The scope attribute on the validation is expecting either a single attribute or an array of attributes from your model, something like
class Product < ApplicationRecord
validates_uniqueness_of :code, :scope => :archived
end
As it turns out, including the :scope option adds a where clause during the validation which looks like where(:archived => false) based on my example above.
From your original code validates_uniquesness_of :code, :scope => { :archived => false }, this results in the scope executing where({:archived => false} => nil). You can see that the hash argument to where is definitely off.
Later in the stack, ActiveRecord is going to try to turn the key from the argument hash into a symbol with to_sym and look for that key as an attribute on the Product model. However, the key in this case is the hash {:archived=>false} which does not respond to to_sym, and here the undefined method error gets raised.
The reason the error "appeared" in the controller is because the line product.update(product_params) in your controller is the beginning of the call chain that led to the bad validation being called in the model, which you have determined was the source of the error.
I have tried to get into rails and ruby by starting to work on a little project and have a problem I can't get around.
As I was trying to create a simple CRUD for an Object, the creation part made no sense anymore.
def create
if (params.nil? || params[:board].nil?)
return render status: 400
end
#board = Board.create(params["board"]["title"], params["board"]["description"])
#...
end
For whatever reason, it gives me an ArgumentError "wrong number of arguments (given 2, expected 0..1)". So I thought I'll simply create it myself and use the save-Method to save it into the database, but that didn't work out either:
#board = Board.new(params["board"]["title"], params["board"]["description"])
#board.save!
This gives me the NoMethodError "undefined method `reverse_merge!' for nil:NilClass".
I tried allot of debugging now but can't figure it out. And not, it's not nil, even though it's saying it's using the NilClass.
EDIT: Form Code (View)
<%= form_tag :action => 'create' do %>
<div class="fluid-container">
<p><label for="board_title">Title</label></p>
<%= text_field 'board', 'title' %>
</div>
<div class="fluid-container">
<p><label for="board_description">Description</label></p>
<%= text_area 'board', 'description' %>
</div>
<%= submit_tag %>
<% end %>
I really don't know what's going on, hopefully someone can help. Thanks in advance - PreFiX/Dominik
Instead of
#board = Board.create(params["board"]["title"], params["board"]["description"])
try
#board = Board.create(title: params["board"]["title"], description: params["board"]["description"])
You should be able to do this too
#board = Board.create(params[:board])
but for security reasons that wont work
http://api.rubyonrails.org/classes/ActionController/Parameters.html
When you try to create a new object, you should pass a hash and not strings like you did.
Replace your controller method to
def create
#board = Board.new(board_params)
if #board.save
redirect_to #board, notice: 'Board was successfully created.'
else
# render the new page
end
end
And add a private method
private
def board_params
params.require(:board).permit(:title, :description)
end
I have a from created in Ruby on rails. The code the form looks like this:
<%= simple_form_for(#action) do |f|%>
<%= render 'shared/error_messages' %>
<%=f.label :action_name, "Action name"%>
<%=f.text_field :action_name%></br>
<%=f.input :startDate,:as => :datetime_picker, :label =>"Start date"%>
<%=f.input :endDate,:as => :datetime_picker, :label =>"End date"%>
<%=f.label :contentURL, "Content url"%>
<%=f.text_field :contentURL%></br>
<%= f.button :submit, class: "btn btn-large btn-primary" %>
<%end%>
But when I click the submit button I get this error:
undefined method `permit' for "create":String
def action_params
params.require(:action).permit(:action_name, :startDate,:endDate,:contentURL)
All other forms a working ok, I guess it is something really obvious, just can't see it :(
I really appreciate any help, solving this problem.
Thanks!!
EDIT:
Controller code:
def create
action = Action.new(action_params)
if #action.save
flash[:success] = "New Action saved"
redirect_to "/"
else
render 'new'
end
end
private
def action_params
params.require(:action).permit(:action_name, :startDate,:endDate,:contentURL)
end
In Rails 4, you must use Strong Parameters in your controllers. Here's some explanation from the official blog. And some example:
class PeopleController < ActionController::Base
# This will raise an ActiveModel::ForbiddenAttributes exception because it's using mass assignment
# without an explicit permit step.
def create
Person.create(params[:person])
end
# This will pass with flying colors as long as there's a person key in the parameters, otherwise
# it'll raise a ActionController::MissingParameter exception, which will get caught by
# ActionController::Base and turned into that 400 Bad Request reply.
def update
redirect_to current_account.people.find(params[:id]).tap do |person|
person.update_attributes!(person_params)
end
end
private
# Using a private method to encapsulate the permissible parameters is just a good pattern
# since you'll be able to reuse the same permit list between create and update. Also, you
# can specialize this method with per-user checking of permissible attributes.
def person_params
params.required(:person).permit(:name, :age)
end
end
Notice how, in the last lines, under the private keyword, the person_params method is defined, which declares the permitted fields to be assigned by the create and update methods on top. And it's the person_params that is used for updating - the valid example - instead of the raw params array.
I'm studing Ruby on Rails with the "RoR Bible" by Thimothy Fisher. But one of the examples doesn't work. It's code - http://pastebin.com/gtjLsdt0
The error is: NoMethodError in Contact#new where line #4 raised:
undefined method `merge' for "first_name":String
that's my contact_controller. I'm just retyping example's code, and there weren't any words about merge
class ContactController < ApplicationController
def index
#contacts = Contact.find(:all);
end
def show
end
def new
#contact = Contact.new;
end
def create
end
def update
end
end
What is wrong??
Lol that example is completely wrong!
Instead of writing sth like this:
<%= f.text_field 'contact', 'first_name' %>
You should write
<%= f.text_field :first_name %>
Because by using f.field_type you assign the field to the :contact form which provides the f methods by iteration! Also you can write
<%= f.label :first_name, "description of first_name" %>
Instead of writing it manual!
// I loked up the book you refered it seems to be quit outdated. You may buy "The Rails 3 Way" or sth. that can hold up to the current rails version!