Ruby on Rails: hidden field value not inserting into database - ruby-on-rails

I have two hidden_fields, user_id and skill_id
<%= form_for #skill do |s| %>
<%= s.label :image, "Upload your skill" %>
<%= s.hidden_field :user_id, value: current_user.id %>
<%= s.hidden_field :skill_id, value: params[:id] %>
<%= s.file_field :image, multiple: true %>
<% end %>
In my controller I have this:
def reviews
#skill = Skill.new
end
I'm able to get the value for skill_id into my database, but I'm not able to get the value from user_id. In my rails console, I see that user_id is being passed through "skill", but doesn't show in my database.
Parameters: {"utf8"=>"✓", "authenticity_token"=>"5+wxS929uxtt..", "skill"=>{"user_id"=>"7", "skill_id"=>"132", ...
I even checked to see if I'm getting any value with <%= current_user.id %>, which I am.
Maybe someone can guide me to the right path in debugging this issue.
Thanks

<%= form_for #skill do |s| %>
<%= s.label :image, "Upload your skill" %>
<%= s.hidden_field :user_id, value: current_user.id %>
<%= s.hidden_field :skill_id, value: params[:id] %>
<%= s.file_field :image, multiple: true %>
<% end %>
This will go to the create action
So what you really want is to update an existing one since you are passing an existing skills id
def reviews
#skill = Skill.find params[:id]
end
Now your form can use this
<%= form_for #skill do |s| %>
<%= s.label :image, "Upload your skill" %>
<%= s.hidden_field :user_id, value: current_user.id %>
<%= s.file_field :image, multiple: true %>
<% end %>
It is now go to the update action, in your controller.
def update
#skill = Skill.find params[:id]
#skill.update_attributes params[:skill]
redirect_to root_path # redirect to somewhere
end
Try this.

You need a create controller that would look something like this:
def create
#skill = Skill.new(params[:skill])
if #skill.save
# Handle a successful save.
else
render 'new'
end
end
You may want to change the name of the def reviews controller to def new, and also add the new routes to config/routes.rb

Related

Can't insert data to db in ruby on rails

I just learn RoR and confuse now how to insert data to db. Here's my code:
book_insert.html.erb
<%= content_for :helloworld do %>
<%= form_tag("/insert", method: "post") do %>
<%= label_tag(:title, "Title") %>
<%= text_field_tag(:title) %><br>
<%= label_tag(:price, "Price") %>
<%= number_field_tag(:price) %><br>
<%= label_tag(:subject_id, "Subject ID") %>
<%= number_field_tag(:subject_id) %><br>
<%= label_tag(:description, "Description") %>
<%= text_field_tag(:description) %><br>
<br>
<%= submit_tag("Submit") %>
<% end %>
<% end %>
book_controller.rb
class BookController < ApplicationController
def insert
#book = Book.new(book_params)
#book.save
render :book_page
end
def book_params
params.require(:books).permit(:title, :price, :subject_id, :description)
end
def showinsert
render :book_insert
end
end
It returns error:
Completed 400 Bad Request in 4ms (ActiveRecord: 0.0ms)
ActionController::ParameterMissing (param is missing or the value is
empty: books):
Please help. Thanks
form_tag normally used to submit non-model actions to the mapped controller#action. You probably need to use form_for and its corresponding helpers inside the form
<%= content_for :helloworld do %>
<%= form_for Book.new, url: "/insert", method: "post" do |f| %>
<%= f.label :title %>
<%= f.text_field :title %><br>
<%= f.label :price %>
<%= f.number_field :price %><br>
<%= f.label :subject_id %>
<%= f.number_field :subject_id %><br>
<%= f.label :description %>
<%= f.text_field :description %><br>
<br>
<%= f.submit "Submit" %>
<% end %>
<% end %>
With the above code, the params would be passed inside :book => {} hash, so you need to change the book_params to below
def book_params
params.require(:book).permit(:title, :price, :subject_id, :description)
end #^
The params.require method requires that the key books is present in the hash - if not it raises an ActionController::ParameterMissing exception.
To nest inputs you need to name them accordingly:
<%= form_tag("/insert", method: "post") do %>
<%= label_tag("Title") %>
<%= text_field_tag("books[title]") %><br>
<%= label_tag("Price") %>
<%= number_field_tag("books[price]") %
...
<%= submit_tag("Submit") %>
<% end %>
This will give the params hash:
{ books: { title: 'Life & Times of Michael K', price: 99 } }
However thats pretty tedious. A better way is to use the forms helpers and setup your routes and controller according to the conventions:
# config/routes.rb
resources :books
# app/views/books/new.html.erb
<%= form_for(#book) do |f| %>
<div class="field">
<%= f.label :title %>
<%= f.text_field :title %>
</div>
# ...
<%= f.submit %>
<% end %>
# app/controllers/books_controller.rb
class BooksController < ApplicationController
# this renders the form to create a new book
# GET /books/new
def new
#book = Book.new
end
# In Rails its called create - not insert
# POST /books
def create
#book = Book.new(book_params)
if #book.save
redirect_to #book
else
render :new
end
end
# This is the path to show a book
# its also where we redirect after creating the book
# GET /books/:id
def show
#book = Book.find(params[:id])
end
# ...
private
def book_params
# note thats its book singular - not plural
params.require(:book).permit(:title, :price, :subject_id, :description)
end
end
You should do book in the book_params method instead of books:
def book_params
params.require(:book).permit(:title, :price, :subject_id, :description)
end

Submit values with link_to in Rails 5.1

So currently i have a link_to, where signed in users can click on:
<%= link_to "Enroll", [#task.project, #task] %>
The user has an association with the project, through subscription. To create a new subscription for a user with a project, i wrote some simple form for it.
<%= form_for([#project, #subzz]) do |f| %>
<%= f.hidden_field :project_id, :value => #project.id %>
<%= f.hidden_field :user_id, :value => current_user.id %>
<div class="actions">
<%= f.submit %>
</div>
<% end %>
Which works fine and creates the association. However, i want that the user is able to create the subscription whenever he clicks on 'enroll' instead of a second, extra submit button.
Any ideas how to approach this? I thought about using jQuery, but not sure how to inject the ids with it and if its the 'right' way to do it.
Thanks in advance everyone!
EDIT:
When using the method posted as answer, i get:
param is missing or the value is empty: sub
My updatet form:
<%= form_for([#project, #subzz], html: {role: "form", id: "project_form"}) do |f| %>
<%= hidden_field_tag :project_id, :value => #project.id %>
<%= hidden_field_tag :user_id, :value => current_user.id %>
<%= link_to "Enroll", [#task.project, #task], :onclick => "$('#project_form').submit() "%>
<% end %>
subs_controller.rb
class SubsController < ApplicationController
def create
#subz = Sub.create(sub_params)
project = #subz.project
redirect_to root_path
end
private
def sub_params
params.require(:sub).permit(:project_id, :user_id)
end
end
You can be using the existing form and link_to, just edit some like edit the dorm_tag like this
<%= form_for([#project, #subzz], html: {role: "form", id: "project_form"}) do |f| %>
and remove the button into form like this one
<div class="actions">
<%= f.submit %>
</div>
and edit the link_to like this
<%= link_to 'Enroll', "", :onclick => "$('#project_form').submit()" %>
it will work
Update
You can achieve this without a form, comment out this form and edit the link like below
<%= link_to 'Enroll', subs_path(project_id: #project.id, user_id: current_user.id), method: :post %>
and the create method update like below
def create
#subz = Sub.new(sub_params)
if #subz.save
flash[:success] = 'Sub was successfully submited.'
redirect_to root_path
else
flash[:danger] = 'Sub not submited'
redirect_to request.referer
end
end
that is easier
Or if you keep before one with form then the link out from the form and the create method edit like the following
def create
#subz = Sub.new(sub_params)
if #subz.save
flash[:success] = 'Sub was successfully submited.'
redirect_to root_path
else
flash[:danger] = 'Sub not submited'
redirect_to request.referer
end
end
and the form will look like this
<%= form_for([#project, #subzz], html: {role: "form", id: "project_form"}) do |f| %>
<%= hidden_field_tag :project_id, :value => #project.id %>
<%= hidden_field_tag :user_id, :value => current_user.id %>
<% end %>
<%= link_to "Enroll", [#task.project, #task], :onclick => "$('#project_form').submit() "%>
if you confused this [#task.project, #task] on link tag then use direct link
So i came up with the following solution:
I've added the sub handling to the application_controller, so that its availiable for the project_controller. I also added the project, tasks as a reference, so that i am able to redirect to a task via the sub_controller, instead of the project_controller.
application_controller.rb
def create
#subs = Sub.new(sub_params)
project = #subs.project
taskz = project.tasks.first
if #subs.save
redirect_to [taskz.project, taskz]
end
end
private
def sub_params
params.require(:sub).permit(:project_id, :user_id)
end
Inside the show.html.erb from the project_controller, i use the old form:
<%= form_for([#project, #subz] do |f| %>
<%= f.hidden_field :project_id, :value => #project.id %>
<%= f.hidden_field :user_id, :value => current_user.id %>
<%= f.submit "Submitted" %>
<% end %>
which works fine. Thanks for any previous help!

Error with simple_form on Rails

i'm trying to render a form but it's throwing an error and I can't find a reason for it.
controller
def new
#student = Student.find(params[:student_id])
#learning_instrument = LearningInstrument.new
end
def create
#student = Student.find(params[:student_id])
#learning_instrument = LearningInstrument.new(learning_instrument_params)
#learning_instrument.student = #student
if #learning_instrument.save
redirect_to student_path(#student)
else
render :new
end
end
private
def learning_instrument_params
params.require(:learning_instrument).permit(:level, :student_id, :instrument_id)
end
this is my form
<%= simple_form_for(#student, #learning_instrument) do |f| %>
<%= f.error_notification %>
<%= f.input :level %>
<%= f.association :instrument, collection: Instrument.all %>
<%= f.hidden_field :student, value: #student %>
<%= f.button :submit %>
<% end %>
I'm getting "can't write unknown attribute builder". I've done stuff like this some times and it worked but this time I can't get it to work
Thanks
can't write unknown attribute builder
This is because of this line <%= simple_form_for(#student, #learning_instrument) do |f| %> .You have to define simple_form_for for nested resources like below
<%= simple_form_for [#student, #learning_instrument] do |f| %>

Why is my nested attributes form not working in rails?

I have a model called profile that has_many jobs. I am using the cocoon gem in order to allow users to make a profile, and then on a separate page make as many jobs as they'd like. The profile form is working fine. The job form, however, doesn't seem to actually be creating the jobs. Since a user needs to fill out a profile form before they can fill out a jobs form, by the time they get to the jobs form, it will automatically go to the update action in the profiles controller instead of the create. I'm pretty sure the problem is in the profiles controller. Here is the profiles controller:
def new
if current_user.profile
redirect_to edit_profile_path(current_user.profile_name)
else
#profile = Profile.new
end
end
def create
#profile = current_user.build_profile(profile_params)
#profile.save
if current_user.profile.invalid?
render :new, :status => :unprocessable_entity
else
redirect_to profile_path(current_user.profile_name)
end
end
def edit
#profile = current_user.profile
end
def update
#if current_user.profile.jobs.any?
#profile_save = current_user.profile.update_attributes(profile_params)
if current_user.profile.invalid?
#profile = current_user.profile
render :edit, :status => :unprocessable_entity
else
redirect_to profile_path(current_user.profile_name)
end
end
private
def profile_params
params.fetch(:profile, {}).permit(:title,
:category, :description, :state, :zip_code, :rate,
jobs_attributes: [:firm, :position, :category, :description,
:begin, :end, :_destroy])
end
I use fetch instead of require because otherwise I received an error saying the profile was not found. Here is the form:
<%= simple_form_for #profile do |f| %>
<h3> Jobs </h3>
<%= f.simple_fields_for :jobs do |job| %>
<%= render 'job_fields', :f => job %>
<% end %>
<%= link_to_add_association 'add job', f, :jobs %>
<%= f.submit %>
<% end %>
And here is the job_fields partial:
.nested-fields
<%= f.input :firm, label: "Firm" %> <br>
<%= f.input :position, label: "Position" %> <br>
<%= f.input :category, label: "Category"%><br>
<%= f.input :begin, label: "Beginning", collection: 1960..2013 %><br>
<%= f.input :end, label: "End", collection: 1960..2013 %>
<%= f.input :description, label: "Description"%><br>
<%= link_to_remove_association "remove task", f %>
The problem could also be that I translated from HAML to ERB and I think I did it incorrectly.
Also, all profiles actually belong to a user, but i don't think that should make a difference. Thanks in advance for the help!
If the issue is that you want to call the create method for Jobs, you'll need to modify your form to explicitly use the post method. Something like:
<%= simple_form_for #profile, :url => new_jobs_path, :method => :post do |f| %>
<h3> Jobs </h3>
<%= f.simple_fields_for :jobs do |job| %>
<%= render 'job_fields', :f => job %>
<% end %>
<%= link_to_add_association 'add job', f, :jobs %>
<%= f.submit %>
<% end %>

params.require().permit does not work as expected

I have this controller
class PeopleController < ApplicationController
def new
#person = Person.new
#person.phones.new
end
# this is the action that gets called by the form
def create
render text: person_params.inspect
# #person = Person.new(person_params)
# #person.save
# redirect_to people_path
end
def index
#person = Person.all
end
private
def person_params
params.require(:person).permit(:name, phones_attributes: [ :id, :phone_number ])
end
end
and this view
<%= form_for :person, url: people_path do |f| %>
<p>
<%= f.label :name %><br />
<%= f.text_field :name %>
</p>
<%= f.fields_for :phones do |f_phone| %>
<div class="field">
<p>
<%= f_phone.label :phone_number %><br />
<%= f_phone.text_field :phone_number %>
</p>
</div>
<% end %>
<p>
<%= f.submit %>
</p>
<% end %>
When I fill out both form fields and hit "Save Person" I only get {"name"=>"foo"} - the phone number seems to vanish.
However, when I change phones_attributes to phones I get {"name"=>"foo", "phones"=>{"phone_number"=>"123"}} (this would however cause problems with the create function.
What's wrong here?
Please note that this question is strongly related to that one: accepts_nested_attributes_for: What am I doing wrong as well as to this posting: https://groups.google.com/forum/#!topic/rubyonrails-talk/4RF_CFChua0
You don't have #phones defined in the controller:
def new
#person = Person.new
#phones = #person.phones.new
end
Finally found the problem. In the view there should be
<%= form_for #person, url: people_path do |f| %>
Instead of
<%= form_for :person, url: people_path do |f| %>
#phron said that already here:
accepts_nested_attributes_for: What am I doing wrong

Resources