I have a #miniatures model and a #lines model joined via a #minilines model.
In the #miniature show view I have this link
<%= link_to "Add to product line", new_miniline_path(:miniature_id => #miniature) %>
To a New #miniline form that takes the :miniature_id from a hidden field like so
<%= f.hidden_field :miniature_id, :value => #miniature.id %>
And then you select the desired #line from a dropdown.
This all works. What I can't get to work is for the controller to redirect a user back to the originating #miniature after the create action works.
This is what I have in my new and create actions in the controller
def new
#miniline = Miniline.new(#miniature)
#miniature = Miniature.find(params[:miniature_id])
#lines = Line.all
end
def create
#miniline = Miniline.new(miniline_params)
if #miniline.save
flash[:success] = "Miniature added to product line"
redirect_to miniature_path(#miniature)
else
flash[:success] = "Did not work!!!"
render 'new'
end
end
I've tried various alternatives to miniature_path(#miniature) like plain #miniature and miniature_path(:miniature_id) but to no avail. I suspect my problem is with the passing of the :miniature_id to the #minilines model. Any help very much appreciated as I've been banging my head for an hour or two.
redirect_to miniature_path(#miniline.miniature)
Assuming you have an association setup.
You haven't set #miniature in create which is that that doesn't work
You could also do
redirect_to #miniline.miniature
Related
I'm running into this issue working with a form in rails, and was wondering if anybody could take a quick look with it.
My view looks like
= form_for #form_submission do |f|
- if #form_submission.errors.any?
#error_explanation
%h2= "#{pluralize(#form_submission.errors.count, "error")} prohibited this form_submission from being saved:"
%ul
- #form_submission.errors.full_messages.each do |msg|
%li= msg
..and my controller is like so
class FormSubmissionsController < ApplicationController
invisible_captcha only: [:create], on_spam: :handle_spam
def new
#form_submission = FormSubmission.new(form_submission_params)
if #form_submission.save
redirect_to thank_you_path
else
redirect_to root_path
end
end
private
def handle_spam
redirect_to root_path
end
def form_submission_params
params.require(:form_submission).permit(:first_name, :last_name, :organization, :email, :phone)
end
end
Ultimately my problem is that I don't know what params i'm missing. Or even if my value is empty, how would I know, and what could I do to resolve that?
Standard rails approach to forms is your new action is a 'GET' and is used to show the new view for the creation of a resource. The form 'POST's to the create action with the form fields added to the params hash. Your controller methods should be
def new
#form_submission = FormSubmission.new
end
def create
#form_submission = FormSubmission.new(form_submission_params)
if #form_submission.save
redirect_to thank_you_path
else
redirect_to root_path
end
end
Check your routes by running rake routes in the terminal and make sure you have a routes to that point to form_submissions#new and form_submissions#create.
When you click on the submit button you will be able to view the parameters that are being passed in the logs and it should look something like
Parameters: {"utf8"=>"✓", "authenticity_token"=>"someRandomStuff", "form_submission"=>{"first_name"=>"value entered in first_name field", "last_name"=>"value entered in last_name field"}, "commit"=>"Value of submit button"}
Are you really creating a resource called FormSubmission?
I think you're doing it the wrong way.
this is what you should do :
def new
#form_submission = FormSubmission.new
end
def create
#form_submission = FormSubmission.new(form_submission_params)
if #form_submission.save
redirect_to thank_you_path
else
redirect_to root_path
end
end
As said in comments,
"new" action is used to initialize your ressource as empty or with default value.
"create" action is used to save your new ressource
The problem in brief: I'm working on a rails 4 app (4.1.8) and I'm trying to get flash[:notice] and flash[:alert] to show up under a form.
Two controllers: landingpage_controller and contacts_controller. The landingpage_controller serves a static landingpage through its show action and the contacts_controller has new and create actions, to store the contacts in a db table.
On the static landingpage, a modal with id="contact-modal" contains a partial with a simple_form_for #contact (see below). Upon submittal of the form, a db-entry is not created if the fields are not all filled out and a db-entry is created if the fields are filled out. However, no flash messages are displayed.
Wanted output:
Ideally the partial would re-load without leaving/closing the modal, with either: a success message and an empty form or a alert message and the form as it was upon submittal. How do I do this?
The controller: app/controllers/contacts_controller.rb
class ContactsController < ApplicationController
def new
#contact = Contact.new
render layout: "contact"
end
def create
#contact = Contact.new
respond_to do |format|
if #contact.save
flash[:notice] = "Success"
format.js
else
flash[:alert] = "Error"
format.js
end
end
end
private
def contact_params
params.require(:contact).permit(:email, :structure, :message_content)
end
end
The form: app/views/contacts/_new.html.haml
= simple_form_for #contact, html: { id: "contact-form"} do |c|
= c.input :email
= c.input :structure
= c.input :message_content
= c.button :submit
.messages-container
= if flash[:notice]
%p
= flash[:notice]
= if flash[:alert]
%p
= flash[:alert]
Routes:
resources :contacts, only: [:new, :create]
I'm aware that a partial reload probably involves AJAX. I've read several StackOverflow questions on this but have not been able to figure it out. See here, here and these two blog-posts: jetthoughts, ericlondon.
Your help is very much appreciated
There are several problems in your code:
views, that start with underscore are called partials and are not full actions, but just parts of reusable view code (you don't redirect to them, instead you use render since you usually don't want a full page reload.
1.1 Rename your _new.html.haml to _form.html.haml
2.1 Create a new view new.html.erb(I guess you have that already, otherwise your new action might not work properly) with content = render 'form'
From what I understand you don't want the modal to close, just to render a form after successful submission or if there is an error.
In that case:
1.create a create.js.erb file in your views/contacts folder
create.js.erb
$("#your_modal_id").html("<%= j( render 'form') %>")
2. change your create action
def create
#contact = Contact.new(contact_params)
respond_to do |format|
if #contact.save
flash[:notice] = "Success"
format.js
else
flash[:alert] = "Error"
format.js
end
end
end
to your form add remote: true
WARNING: This will leave your form filled in even if it is successful.
More about this topic see:
http://guides.rubyonrails.org/v4.1.8/working_with_javascript_in_rails.html#form-for
Hope it helps, and I hope I didn't forget anything
I'm trying to put a new form that creates new "Addicts" in a modal in my home page.
It's a simple form with 2 inputs, that when clicking on New, a modal pops up with that form in my index page.
I can't get it to work because it keeps saying "Couldnt find Addict without an ID".
My Pages Controller
class PagesController < ApplicationController
def home
#addict = Addict.find(params[:id])
#lanzaderas = Lanzadera.all
render 'index'
end
end
My Addict Controller
class AddictsController < ApplicationController
def index
#posts = Addict.all
end
def show
#addict = Addict.find(params[:id])
end
def new
#addict = Addict.new(params[:addict])
end
def create
#addict = Addict.new(params[:addict])
if #addict.save
redirect_to posts_path, :notice => "Your Addict was saved"
else
render "new"
end
end
def edit
end
def update
end
def destroy
end
end
end
My form in my modal
<%= form_for #addict do |f| %>
<%= f.input :name %>
<%= f.input :surname %>
<%= f.input :postal %>
<%= f.submit %>
<% end %>
I know it has something to do with the variable / id not being passed correctly in my Controller, but it's an error I get lots of times and don't know why I happens.
Thanks!
In def home in your PagesController you have this code:
#addict = Addict.find(params[:id])
I suspect, that you don't have the id for 'addict' in your parameters, when you visit your home action.
Do you want to display one particular addict in your 'home' page? If not, you can remove this line.
Update:
Change this in your AddictsController:
def new
#addict = Addict.new
end
In the new action you only "prepare" a new addict object. Using the find method is not possible, since the record hasn't been created yet.
If you're using Rails 4 you also have to permit your parameters (for security reasons; more info here: Railsguides: Strong Parameters)
In your case you have to do 2 things:
First: add this at the bottom of your AddictsController:
private
def addict_params
params.require(:addict).permit(:name, :surname, :postal)
end
Second: use this method in your create action instead of params[:addict]:
def create
#addict = Addict.new(addict_params)
if #addict.save
redirect_to posts_path, :notice => "Your Addict was saved"
else
render "new"
end
end
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])
So I'm using the excellent Ancestry gem But while the documentation seems very complete I don't understand how to pass the parameter of my element which I want to be the parent of my newly created element. Firstly, do I want to do it in the new or create action... allow me to explain. For example: (with some actions removed for brevity)
class PeopleController < ApplicationController
#...
def new
#person = Person.new
end
def create
#user = User.new(params[:user])
if #user.save
flash[:notice] = "Registration Successful."
redirect_to root_url
else
render :action => 'new'
end
end
end
So namely I don't know where to create the ancestry, the docs say:
...You can use the parent attribute to organise your records into a tree. If you have the id of the record you want to use as a parent and don’t want to fetch it, you can also use parent_id. Like any virtual model attributes, parent and parent_id can be set using parent= and parent_id= on a record or by including them in the hash passed to new, create, create!, update_attributes and update_attributes!. For example:
TreeNode.create! :name => 'Stinky', :parent => TreeNode.create!(:name => 'Squeeky')
I want to know what my controller show look like to allow me to set the parent of the #person when I create them.
So otherwise I'm stuck, I don't know what else to do here... but anyhow, I do know that this gem is similar to the more popular acts_as_tree, any help is super appreciated!
Updated
I think I almost have it but when I try this for my create action
def create
#parent = Recipe.find(params[:parent])
#recipe = Recipe.new(params[:recipe], :parent => #parent.id) do |recipe|
recipe.user_id = current_user.id
end
if #recipe.save
current_user.has_role!(:owner, #recipe)
redirect_to #recipe
else
render :action => 'new'
end
end
I get:
Couldn't find Recipe without an ID
Updated
My view has a link to the new action that looks like this <%= link_to "fork this recipe", {:controller => "recipes", :action => "new", :parent => #recipe} %>
That seems to look fine to me, also the url reads fine when you get to the form, recipes/new?parent=112, but I still get that error, there has to be a way for that parameter to be passed as the parent of the newly created object.
If it works like acts_as_tree then I'll assume that you can do something like this:
#parent.children.create(attributes)
Which will create a new child object with the parent set, regardless of what the attributes say.
According to the docs that you pasted you can do:
#...
#user = User.new(params[:user])
#user.parent_id = #parent_user.id
#user.save
#...
You can also include it in the params hash for the user -- your form submission would need to have params[:user][:parent_id]:
#user = User.create(params[:user])