Model creates blank page? - ruby-on-rails

when I enter information into my form for a new page, it lets you select which author has created the page, this all works fine.
when I go to save the page i get this error
ActiveRecord::AssociationTypeMismatch in PagesController#create
Author(#2162588860) expected, got String(#2151988680)
it also says I have problems in my Pages_controller in the create action and the show action.
def create
#page = Page.new(params[:page])
if #page.save
redirect_to(#page, :notice => 'Page was successfully created.')
else
render :action => "new"
end
end
def show
#page = Page.find(params[:id])
end
I have changed the params :id to author and it saves an empty record with none of the content that was entered in the form. What should I put in the params? or in the create and show action .
thank you

Looks, like you try to set author param to string while you need to set author_id. I can suupose, you used select control in form, builded like this:
f.select(:author, ... )
instead of
f.select(:author_id, ... )

Related

Send parameter to render

I have a form for creating a ticket, which needs an id of a project. This works but not when it comes to validation. If validation won't pass 'render :new' is executed and the project_id doesn't come with it.
I have tried 'redirect_to new_ticket_path(:project_id => params[:ticket][:project_id]) which renders the form again, but the error messages won't show up so it seems that I need to use 'render :new'.
How can I pass the project_id back to the form or reach project_id from the form without passing it?
def new
#ticket = Ticket.new
#id = params[:project_id]
#project = Project.find(#id)
end
def create
#ticket = Ticket.new(params[:ticket].merge(:user_id => current_user.id))
if #ticket.save
redirect_to #ticket
else
render :new <--- will render without the project_id
end
end
That will render just the view for 'new', but will not run the controller action. You'd need to set up your variables for the 'new' view in your 'create' action.
From http://guides.rubyonrails.org/layouts_and_rendering.html#using-render
Using render with :action is a frequent source of confusion for Rails
newcomers. The specified action is used to determine which view to
render, but Rails does not run any of the code for that action in the
controller. Any instance variables that you require in the view must
be set up in the current action before calling render.
The easiest way around this is to change 'new':
def new
#ticket = Ticket.new(:project_id => params[:project_id])
end
and change any references to #project in your 'new' form to #ticket.project. At that point, you shouldn't have to add anything to your 'create' action as long as your form includes a hidden field for the ticket's project id.
The easiest way to get this working (and I would do this anyway) is to nest the task resource under projects. That way you will always have project_id available in params.
# config/routes.rb
resources :projects do
resources :tasks
end
The urls will look like projects/123/tasks/new etc. Take a look at rake routes.
Write project id into a hidden field in your form and you will okay. And don't forget to initialize #id in your create action
def new
#ticket = Ticket.new
#id = params[:project_id]
#project = Project.find(#id)
end
def create
#ticket = Ticket.new(params[:ticket].merge(:user_id => current_user.id))
#id = params[:project_id] # but make sure it is under this key in params
if #ticket.save
redirect_to #ticket
else
render :new <--- will render without the project_id
end
end
and in the form add
<%= hidden_field :project_id, '', value: #id %>
Why don't you use:
flash[:alert] = #ticket.errors.inspect
redirect_to new_ticket_path(:project_id => params[:ticket][:project_id])

Excluding nested form fields in controller action with Hash#exclude before mass_assignment error is generated?

I currently have a create action in my sales controller that looks like this:
def create
#sale = Sale.new(params[:sale].except(:vehicles_attributes))
if #sale.save
redirect_to #sale, :notice => "Successfully created sale."
else
render :action => 'new'
end
end
The intention is to exclude a couple of attributes that are used only to populate linked selects, and should not be submitted (there are no columns for them).
With the controller code above, I am finding that the parameters still includes "sale"=>{"vehicles_attributes"=>{"0"=>{"make"=>"","model"=>""}}} so it seems that I have missed something in the controller code.
EDIT: After some more digging around, I have found that the mass_assignment exception is firing before my except code gets a chance to remove the params that shouldn't be sent by the form, so I am back to square one.
How can I ensure that I remove the fields that shouldn't be sent by the form before I get the mass_assignment error?
As far as I know the mass_assignment error should occur during the new call, so your way should work. Although I never used the except method. Have you tried using the reject! method?
def create
params[:sale].reject! { |k, v| k == :vehicles_attributes }
#sale = Sale.new(params[:sale])
if #sale.save
redirect_to #sale, :notice => "Successfully created sale."
else
render :action => 'new'
end
end
If you need to keep the :vehicles_attributes you can also use the reject method (without the bang) which gives you a copy instead of removing it from the original hash.

How do I get the ID of a model in a collection after it was created as part of a nested form?

I have a User model, which :has_many :widgets
Here is the 'edit' method:
def edit
#user = current_user
#user.widgets.build
end
I have an edit view which contains a user form and a widget form nested within it
In my UserController#update method, I save the data...all working as designed.
After save, I want to send the user to Widget#show with the ID of the widget that was just added to User.widgets
How do I get that ID?
Here is my update method:
def update
#user = User.find(params[:user][:id], :include => [:widgets])
if #user.update_attributes(params[:user])
redirect_to widget_path(????), notice: 'Your new Widget is ready' }
end
end
Couldn't you scope the #user.widgets.last.id request so that you are assured of getting their last widget, something like: #user.widgets.created_by(#user).last.id

instance var was not kept across the method

Here is code in customers controller:
def edit
#customer = Customer.find(params[:id])
#return_to = params[:return_to]
end
def update
#customer = Customer.find(params[:id])
if #customer.update_attributes(params[:customer], :as => :roles_new_update)
redirect_to #return_to, :notice => 'Customer was updated successfaully!'
else
render 'edit', :notice => 'Customer was not updated!'
end
end
It is verified that there is value in #return_to in method edit. However there is an error saying: Cannot redirect to nil! for
redirect_to #return_to, :notice => 'Customer was updated successfaully!'
in method update.
Any thoughts about the error? Thanks.
It's because when you are on the edit action, that is one request to show the form. Then when you submit the form, that is a second request calling the update action. Any states set in an action are confined to that action alone. There's a few ways to use data across multiple actions:
The database (So save it in a model)
The session hash
Pass it in the view to go into your form.
Because it's a redirect/return to value, i would suggestion using a session variable such as:
session[:return_to] = params[:return_to]
In your edit action, then just refer to that value in your update:
session[:return_to]
I don't understand; edit doesn't call update, so there'd be no intrinsic reason for #return_to to still exist.
Are you aware that controllers are created per-request?

Ruby on Rails when create method fails, render loses local variables

Hey guys I have a simple create method with some validations and whenever the create method fails due to validation errors it re-renders the 'new' action.
The problem is in my new action/view I have a local variable that is established in the action and passed to a partial to render some related information to what the user is creating.
Now when my create action fails and I try to re-render the 'new' action I'm getting the always awesome
undefined method `cover' for nil:NilClass
error.
What is the best way to handle re-establishing my action's local variables on a render instead of redirecting to the action again and the user losing the data they input?
For some clarification. Here is some sample code:
#controller.rb
def new
#summary = User.find(params[:user_id])
#page = Page.new
end
def create
#page = Page.new(params[:page])
if #page.save
redirect_to #page
else
render :action => 'new'
end
end
in my new.html.erb file i have something like this
<%= #summary.cover %>
#page form etc...
When you create the object and attempt to save it, the object still holds the values and the validation errors, so pass it on into the render. Usually it is named the same in your create method as it is in your new method, so the template just works.
if #my_object.save
flash[:notice] = "Successfully created."
redirect_to ....
else
render :action => 'new' #assuming new.html.erb uses #my_object
end

Resources