Attributes sent from link_to to create action is not saved - ruby-on-rails

I have the following link_to in my index.html.erb. Whenever I click on the link, it will create a new record in retrieval_requests table but for some reason user_id and package_id was not saved.
I'm not sure on how to go about this. I would appreciate any help.
Thanks.
index.html.erb
.
.
<%= link_to "Retrieve this package", retrieval_requests_path(user_id: current_user.id, package_id: item.package.id), :method => :post %>
.
.
retrieval_requests_controller.rb
class RetrievalRequestsController < ApplicationController
def index
#items = Item.where(:user_id => current_user.id)
end
def create
#retrieval_request = RetrievalRequest.new(params[:retrieval_request])
if #retrieval_request.save
redirect_to retrieval_requests_path, notice: "Successfully created retrieval request."
else
render :new
end
end
end

Since you're using a link and not a form, you're going to have to create the record with the individual params.
So instead of using params[:retrieval_request] (which don't exist), use params[:user_id] and params[:package_id].
When you pass parameters to a link helper, such as:
retrieval_requests_path(user_id: 3, package_id: 26)
It will create a URL that looks something like the following, depending on how you set up your routes:
"/retrieval_requests/3/26"
# or with no user_id or package_id set in routes:
"/retrieval_requests?user_id=3&package_id=26"
Then in your controller you need to grab those params separately.

Related

Param is missing or the value is empty: within new

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

Could find Addict without an ID

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

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])

How do I access a Profile model insider users_controller in ruby on rails?

I would like to access "profiles" table from my Profile model which belongs_to :user "User model".
Firstly in my show action of the users_controller I'd like to grab data from the profiles table in order to show on the users profile page.
Secondly I'd like to make it possible for users to edit these things using a form. I know this is done in the update action? while edit action makes it possible to show a form on the edit view page..
Here is my controller:
class UsersController < ApplicationController
def new
#user = User.new
#title = "Practice"
end
def create
#user = User.new(params[:user])
respond_to do |format|
if #user.save
#user.build_profile.save #same as Profile.new(:user_id => #user.id)
login #user
UserMailer.join_confirmation(#user).deliver
format.js { render :js => "window.location = '#{root_path}'" }
flash[:notice] = "Welcome!"
else
format.js { render :form_errors }
end
end
end
def show
end
def update
end
def edit
end
end
1) How would I access my profiles table?
The User has_one :profile
The Profile belongs_to :user
Advice will be appreciated. Took me half of the day to figure out how to have a row corresponding to a newly created user at sign up created in the profiles table and now the next step is to be able to grab data from the model in my users_controller. i know I could just create a profiles_controller and do things there but I don't want to attempt that right now as I'm sure there's a way to do it via the users_controller.
Thanks in advance for advice given.
View:
<%= #profile_data.first_name %>
<h4><%= current_user.username.capitalize %></h4>
<%= gravatar_image_tag(current_user.email, :alt => #title, :class => "gravatar", :gravatar => { :size => 150 }) %>
<br />
Trying to pull first_name from profiles table through users_controller
def show
#user = User.find_by_username(params[:username])
#profile_data = #user.profile
end
route:
match ':username' => "users#show"
I expect to see the name stored in first_name column of the profiles table when i visit localhost:3000/username
it doesn't show the users first name.
You can just do:
#user.profile
That will return the profile belonging to the User
Otherwise:
Profile.where('whatever condition you fancy')
will return A profile object based on conditions
You want a has_one:profile on the User model, and a belongs_to:user on the Profile model, making sure you have the appropriate user_id column in the profiles table. Add accepts_nested_attributes_for:profile to the User model and then you can create/edit the user's profile in the same form for editing users.
Read up on the rails release notes on nested attributes and guides: associations and forms.

Using parameters in my controller

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])

Resources