I'm implementing likes for photos, and the id isn't being passed. I don't know why. Could someone please explain why? I feel it would help me understand rails better.
I get this error, after clicking like: "Couldn't find Photo without an ID"
On the photo show page I have this:
<%= form_for(#photolike, :url => {:controller => :photolikes, :action => 'create'}) do |f| %>
<%= f.hidden_field :photo_id, :value => #photo.id %>
<%= f.submit "like", class: "btn postbtn right" %>
<% end %>
this is the controller for photos
def show
if user_signed_in?
#comment = current_user.sent_photocoments.new(params[:photo_comment])
end
#photo = Photo.find(params[:id])
#photolike = Photolike.new
end
And in the photolikes controller, I have this:
def create
#photo = Photo.find(params[:id])
#photolike = Photolike.new(:photo_id => #photo.id, :user_id => current_user.id)
#photolike.addlike
#photolike.save
redirect_to #photo
end
def create
#photo = Photo.find(params[:photolike][:photo_id])
#photolike = Photolike.new(:photo_id => #photo.id, :user_id => current_user.id)
#photolike.addlike
#photolike.save
redirect_to #photo
end
Your submit is submitting the photo_id labeled as photo_id (in your hidden field). So your controller needs to retrieve it via params[:photo_id] rather than params[:id].
Related
I'm building a very basic rails application, that provides a form, and gets user submissions.
On the delete action, I keep getting the error: Couldn't find <object> (in this case, question) without an id.
I understand the delete action is asking to find the params by ID, and I'm not sure why it doesn't have an ID.
I added the field question_id to the table questions, hoping that would do it. Have read many other similar questions, the answer isn't clicking. THX in advance.
Index page
<% #questions.each do |display| %>
<table>
<th>Your answer</th></br>
<tr><%= display.answer %></tr></br>
<tr><%= link_to("Delete Action Item", {:action => 'delete'}) %></tr></br>
<% end %>
</table>
Delete view
<%= form_for(:question, :url => {:action => 'destroy', :id => #question.id}) do |f| %>
<p>You're deleting this action item forever - Ok?</p>
<%= submit_tag("Do it - Delete it") %>
<% end %>
Questions Controller
class QuestionsController < ApplicationController
def index
#questions = Question.all
end
def delete
#question = Question.find(params[:id])
end
def destroy
#question = Question.find(params[:id]).destroy
flash[:notice] = "Deleted Action - Nice job"
redirect_to(:action => 'new')
end
private
def question_params
params.require(:question).permit(:answer, :question_id)
end
end
In your index where you are creating the link, you aren't specifying the :id as an argument so your delete action has no params[:id]
Turn this:
<tr><%= link_to("Delete Action Item", {:action => 'delete'}) %></tr></br>
Into this:
<tr><%= link_to("Delete Action Item", {:action => 'delete', :id => display.id}) %></tr></br>
I am having trouble with the params.require().permit(). I have a User model from devise and a group model which represents a class (as in an academic class). When the user is on the groups index view I want them to be able to click join and become part of that group.
<%= form_for #student, :url => students_path(#student), method: :post do %>
<%= hidden_field :student_id, :value => current_user.id %>
<%= hidden_field :course_id, :value => group.id %>
<%= submit_tag "+ Join", :class => "btn btn-primary pull-right join-button" %>
<% end %>
My thinking was I would pass the current users id as well as the group ID that they click join for as hidden values so there would just be a join button.
My group controllers index method looks like this
def index
#groups = Group.all
#student = Student.new
end
My Student Controller looks like this:
class StudentsController < ApplicationController
before_action :set_student, only: [:show, :edit, :update, :destroy]
def index
##students = Student.all
#students = Student.where(:student_id => current_user.id)
#respond_with(#students)
end
def show
#respond_with(#student)
#students = Student.find(params[:id])
end
def new
#student = Student.new
#respond_with(#student)
end
def edit
end
def create
#student = Student.new(student_params)
#student.save
#respond_with(#student)
end
def update
#student.update(student_params)
#respond_with(#student)
end
def destroy
#student.destroy
#respond_with(#student)
end
private
def set_student
#student = Student.find(params[:id])
end
def student_params
params.require(:student).permit(:course_id, :student_id)
end
end
Whenever I try and submit the form (aka click the join button) I get an error saying:
param is missing or the value is empty: student
I also get this info which is correct as far as the student and group ID's
Request
Parameters:
{"authenticity_token"=>"/bJYZBGr6lfAzb9mYnvRfMZII+QS8iskd0MRuHh+RnE=",
"course_id"=>"10",
"student_id"=>"4"}
This also does insert into the database, but the student_id and course_id are nil. I am guessing this has something to do with strong params but I am not sure what I am doing wrong.
It looks like your form_builder object is missing from the form_for block. Try this:
<%= form_for #student, :url => students_path(#student), method: :post do |f| %>
<%= f.hidden_field :student_id, :value => current_user.id %>
<%= f.hidden_field :course_id, :value => group.id %>
<%= submit_tag "+ Join", :class => "btn btn-primary pull-right join-button" %>
<% end %>
without the builder I don't believe rails will provide a student hash in the submitted params
in the before _action set_student
you are usin param[:id] , while your params don't have it .. I think you should use param[:student_id] instead
Since you're passing #student isn't the path just student_path(#student) rather than what you had, which is students_path(#student)?
I have a form for casting your vote for your favourite image.
<%= form_for(#imagevote) do |f| %>
<% #miniature.collections(:photo).each do |collection| %>
<% if collection.photo.exists? %>
<td><div class="photo1">
<%= link_to image_tag(collection.photo.url(:thumb), :retina => true), collection.photo.url(:original), :retina => true, :class => "image-popup-no-margins" %>
<%= f.radio_button(:collection_id, collection.id) %>
<%= f.hidden_field :voter_id, :value => current_user.id %>
<%= f.hidden_field :voted_id, :value => collection.user_id %>
<%= f.hidden_field :miniature_id, :value => #miniature.id %>
<p>Painted by <%= link_to collection.user.name, collection.user %></p>
</div></td>
<% end %>
<% end %>
<%= f.submit "Vote" %>
<% end %>
Everything submits correctly except for the hidden_field :voted_id which for some reason duplicates the current_user.id.
UPDATE
I've tried logging in as another user and it seems that :voted_id is not duplicating current_user.id but rather that it is always "7" which was the :user_id I was using to test it before. Now logged in as user number 4 it is still entering the :voted_id as 7. I'm lost.
The link to the imagevotes view is as follows:
<%= link_to "See more and change your vote.", edit_imagevote_path(:miniature_id => #miniature, :voter_id => current_user.id) %>
Here is my image votes controller
class ImagevotesController < ApplicationController
respond_to :html, :js
def new
#imagevote = Imagevote.new
#miniature = Miniature.find(params[:miniature_id])
end
def edit
#imagevote = Imagevote.find_by_miniature_id_and_voter_id(params[:miniature_id],params[:voter_id])
#miniature = Miniature.find(params[:miniature_id])
end
def create
#imagevote = Imagevote.new(imagevote_params)
if #imagevote.save
flash[:success] = "Vote registered"
redirect_to :back
else
flash[:success] = "Vote not registered"
redirect_to :back
end
end
def update
#imagevote = Imagevote.find(params[:id])
if #imagevote.update_attributes(imagevote_params)
flash[:success] = "Vote changed."
redirect_to :back
else
redirect_to :back
end
end
private
def imagevote_params
params.require(:imagevote).permit(:collection_id, :voter_id, :voted_id, :miniature_id)
end
end
You only have one #imagevote object, but you are outputting the hidden fields inside your collection loop so you will have multiple fields in the form referencing the same attribute on the model: if you check the html that is generated, you should see multiple hidden fields with the same name attribute.
The way that browsers handle multiple inputs with the same name means that the param that comes through for :voted_id will always be the :user_id from the last collection.
It's difficult to say because you didn't provide your model and your loop code stripped.
I would guess that you loop over collection that belongs to the current_user. And in this case you will have current_user.id always be the same as collection.user_id. May be you wanted to see collection.photo_id?
I have a Project that belongs to User. In my user view I have a link to add a new project, with the parameter for the user I want to add the project to.
<%= link_to 'Add new project', :controller => "project", :action => "new", :id => #user %>
Url: /projects/new?id=62
Adding a project to a user works. The problem is when the validation fails while adding a new project and I do a render.
def create
#project = Project.new(params[:project])
if #project.save
redirect_to :action => "show", :id => #project.id
else
render :action => "new"
end
end
view:
<%= form_for #project do |f| %>
<%= f.label :name %>
<%= f.text_field :name %>
<%= f.hidden_field :user_id , :value => params[:id] %>
<%= f.submit "Create project" %>
<% end %>
routes
resources :users do
resources :projects
end
How can I keep the parameter for the user after the render? Or is there some better way to do this? Been looking at a lot of similar questions but can't get it to work.
try
render :action => "new", :id => #project.id
if its not works for you, then try alternate way to pass the parameter to your render action.
This can also help you->
Rails 3 Render => New with Parameter
You shouldn't use params[:id] to assign value to this form field. Instead, add this to your #new action in controller:
def new
#project = Project.new(user_id: params[:id])
end
and then just write this in your form:
<%= f.hidden_field :user_id %>
Because #project was defined in your #new and #create actions and because it already contains a Project instance with a user_id assigned to it, the value would automatically be added to this field.
I'm having a problem getting my first app (I'm a total newbie) to save a new associated record. I have two models (users and pictures) with a has_many/belongs_to association. I have set up the userController so that it can create a new picture as below:
def new_picture
#user = User.find(current_user.id)
#picture = #user.pictures.build
end
def create_picture
#user = User.find(params[:id])
#picture = #user.pictures.build(params[:picture])
if #picture.save
flash[:notice] = "Your picture was successfully added."
redirect_to :action => 'show', :id => #user.id
else
render :template => "new_picture"
end
end
and I use
<%= link_to("add picture", :action => 'new_picture', :id => #user.id) if current_user %>
to add a new one. But I'd also like to be able to edit. So I updated the usercontroller with some new code:
def edit_picture
#user = User.find(current_user.id)
#picture = #user.pictures.find(params[:id])
end
# When the user clicks the save button update record
def update_picture
#user = User.find(current_user.id)
#picture = #user.pictures.find(params[:picture])
respond_to do |format|
if #picture.update_attributes(params[:picture])
flash[:notice] = "Your picture was successfully updated."
redirect_to :action => 'show', :id => #user.id
else
render :template => "new_picture"
end
end
end
and added the edit link to show.erb:
<%= link_to("edit picture", :action => 'edit_picture', :id => picture.id) if current_user %>
It loads the edit form fine, with the data all in the right place, but on save all it's doing is giving me the error 'ArgumentError in UsersController#update_picture' with a bunch of Unknown key(s) from my pictures table.
Could somebody explain why? I feel like there is one piece of the jigsaw I haven't quite understood here....
Thanks in advance!
UPDATE: View code is as follows:
<h1>New picture for <%= #user.name %></h1>
<% form_for :picture, #picture, :html => { :multipart => true }, :url => {:action => 'update_picture', :id => #user.id} do |f| %>
Can't seem to see your problem in the view code, however you can do the same thing more elegantly (RESTful) as a nested route. That way you might be able to see the problem more clearly.
config/routes.rb:
resources :users do
member do
resources :pictures
end
end
app/controllers/pictures_controller.rb:
class PicturesController < ApplicationController
before_filter :find_picture, :only => [:edit, :update]
def edit
end
def update
if #picture.update_attributes params[:picture]
flash[:notice] = "Your picture was successfully updated."
redirect_to user_path(current_user)
else
render :edit
end
end
protected
def find_picture
#picture = current_user.pictures.find params[:id]
end
end
app/views/pictures/edit.html.erb:
<%= form_for [current_user, #picture] do |f| %>
<!-- some stuff -->
<% end %>
and to link to your edit form:
<%= link_to_if current_user, 'edit picture',
edit_user_picture_path(:user => current_user, :id => picture) %>
I suggest adding 'accepts_nested_attributes_for :pictures to the user model, and then do
<%= form_for #user do |form| %>
.. user fields
<%= form.fields_for :pictures do |picture_form| %>
.. picture fields
<% end %>
<%= form.submit %>
<% end %>
in the view.
Another option is to create a new controller for the pictures. That may be simpler.