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
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
So I'm trying to create a feature for Typo (blogging app) that merges two articles in one. For some reason, I can't manage to save the merged article. I have followed several threads here, read over and over Rails and Ruby docs... And Can't figure out why it doesn't work
Besides finding what's wrong with my code, I'd like to know best solutions to see what's going on 'under the hood', to debug the code. Eg: See when methods are called, what parameters are passed...
Here is my code:
View:
<% if #article.id && #user_is_admin %>
<h4>Merge Articles</h4>
<%=form_tag :action => 'merge_with', :id => #article.id do %>
<%= label_tag 'merge_with', 'Article ID' %>
<%= text_field_tag 'merge_with' %>
<%= submit_tag 'Merge' %>
<% end %>
<% end %>
Controller
def merge_with
unless Profile.find(current_user.profile_id).label == "admin"
flash[:error] = _("You are not allowed to perform a merge action")
redirect_to :action => index
end
article = Article.find_by_id(params[:id])
debugger
if article.merge_with(params[:merge_with])
flash[:notice] = _("Articles successfully merged!")
redirect_to :action => :index
else
flash[:notice] = _("Articles couldn't be merged")
redirect_to :action => :edit, :id => params[:id]
end
end
Model:
def merge_with(other_article_id)
other_article = Article.find_by_id(other_article_id)
if not self.id or not other_article.id
return false
end
self.body = self.body + other_article.body
self.comments << other_article.comments
self.save!
other_article = Article.find_by_id(other_article_id)
other_article.destroy
end
Thanks in advance, and sorry if this is a rookie question :)
You did not mentioned what problem you are facing while saving, you just said you could not manage to save so I can't help you with that unless you provide some stack trace.
I will mention a few things though:
first is in your controller method you have multiple redirection code like redirect_to :action => index without any return from method so I think you will get multiple redirect or render error at some point like when unless executes and redirects but code continues the execution and throws error so try to reduce these redirects or mention it like redirect_to :action => index and return.
Then in model merge_with you are assigning other_article twice, you don't need the second one.
about debugging, you can create some puts line inside code and check it in rails server console to verify that the condition is executed like in controller method after if article.merge_with you can put:
puts "merge sucess"
and check console when merge action is called, if you see "merge sucess" then if block executed.
OR
use byebug like you used debugger. It will stop the execution where it will find the byebug word and will give access to a live session in rails console.
if you put it where you have debugger you can access the console and do the operations manually like run:
article.merge_with(params[:merge_with])
then see what happens. or put before self.save! in model and save it manually in console and check errors like self.errors.messages.
Stack trace is also helpful to see line by line code execution and identify the error.
I will update this if you post any info about what error you are facing
So as it stands I have a form partial which starts off as:
<%= form_for(#merchandise) do |f| %>
It works perfectly for editing the data that I have already assigned in the rails console. When I try to use it for a "new" form that creates new merchandise (in this case the singular form of merchandise, I don't have nested resources, multiple models etc.), I get a no Method error that states
"undefined method 'merchandises_path' for #<#<Class:0x64eaef0>:0x95d2370>".
When I explicitly state the URL in the form_for method:
<%= form_for(#merchandise url:new_merchandise_path) do |f| %>
I get it to open and I finally have access to the form, however in this case I get a routing error that states
"No route matches [POST] "merchandise/new"".
I decided to write out that route in my routes file which previously just had:
root "merchandise#index" resources :merchandise
After I add the route it literally does nothing. I click submit and it takes me to the form but there is no new data in the database. I am at a complete loss and have been at this for hours googling and stack overflowing and I just don't know what to do anymore. All help is seriously appreciated. I'm adding a pastebin with all my code in the following url:
http://pastebin.com/HDJdTMDt
I have two options for you to fix it:
Option 1:
Please try to do this for best practice in Rails:
routes.rb
change your routes use plural
resources :merchandises
merchandises_controller.rb
Rename your file controller and class into MerchandisesController
class MerchandisesController < ApplicationController
def index
#merchandise = Merchandise.all
end
def new
#merchandise = Merchandise.new
end
def create
#merchandise = Merchandise.new(merchandise_params)
if #merchandise.save
redirect_to merchandises_path
else
render :new
end
end
def show
#merchandise = Merchandise.find(params[:id])
end
def edit
#merchandise = Merchandise.find(params[:id])
end
def update
#merchandise = Merchandise.find(params[:id])
if #merchandise.update(merchandise_params)
redirect_to #merchandise, notice: "The movie was updated"
else
render :edit
end
end
def merchandise_params
params.require(:merchandise).permit(:shipper, :cosignee, :country_arrival_date, :warehouse_arrival_date, :carrier, :tracking_number, :pieces, :palets, :width, :height, :length, :weight, :description, :cargo_location, :tally_number, :customs_ref_number, :released_date, :updated_by, :country_shipped_to, :country_shipped_from)
end
end
Option 2:
If you want to not change many code
/merchandise/_form.html.erb
in partial file
/merchandise/new.html.erb
<%= render 'form', url: merchandise_path, method: 'post' %>
/merchandise/edit.html.erb
<%= render 'form', url: category_path(#merchendise.id), method: 'put' %>
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.
This seems like a fairly simple problem to me but I have been having some issues.
In one of my views I use something like
<% if current_page?(:controller => "activities", :action => "new") %>
*Do something here*
<% end %>
and it does something specific on the new page for a form. Easy enough and it works great.
Unfortunately, I've found that when you have a "new activity" form (assume normal scaffolding controller), the url will go from
http://localhost:3000/activities/new
after submitting an error prone form to
http://localhost:3000/activities
but it will still show the new activity form with the respective errors. So basically everything works how it is supposed to EXCEPT that I need the url to be http://localhost:3000/activities/new for the current_page? function to recognize that it is indeed a new form page.
I'm wondering if there is some kind of work around to this issue. Thanks!
OH and here is the controller code, in case anybody needs to see it
Controller Code
def new
#activity = Activity.new
end
def create
#activity = Activity.new(params[:activity])
if #activity.save
flash[:notice] = "Successfully created activity."
redirect_to #activity
else
render :action => 'new'
end
end
Think you will need to check for create as well as new
<% if current_page?(:controller => "activities", :action => "new") or current_page?(:controller => "activities", :action => "create") %>
not so pretty maybe wrap it up in a helper method?
You could also check if the created at field is blank. As it won't be set till the activity is created.