ruby on rails undefined method form_for - ruby-on-rails

I'm trying to use PaperClip inside my application.
I have 3 models: menu, user and pub. I would like the user to be able to add a menu, which is a pdf file, for a pub. So when I upload the pdf file, I would like to have a column in the menu model with the pub id.
menu.rb
has_attached_file :document
validates_attachment :document, :content_type => {:content_type => %w(application/pdf)}
new.html.erb
<div class="page-header"><h1>Upload Menu</h1></div>
<%= form_for ([#pub, #menu]), html: { multipart: true } do |f| %>
<%= render 'shared/error_messages', object: f.object %>
<div class="form-group">
<%= f.label :title %>
<%= text_field :title, class: 'form-control' %>
<%= f.label :document %>
<%= f.file_field :document, class: 'form-control' %>
<%= f.submit 'Upload Menu', class: 'btn btn-primary' %>
</div>
<% end %>
routes.rb
resources: pubs do
resources :menus
end
menus_controller.rb
class MenusController < ApplicationController
def index
#menus = Menu.order('created_at')
end
def new
#menu = Menu.new
end
def create
#pub = Pub.find(params[:pub_id])
input = menu_params.merge(pub: #pub)
#menu = current_user.menus.build(input)
if #menu.save
flash[:success] = "Successfully added new menu!"
redirect_to root_path
else
flash[:alert] = "Error adding new menu!"
render :new
end
end
private
def menu_params
params.require(:menu).permit(:title, :document)
end
end
Button for the new page to upload a file
<%= link_to "Upload menu", new_pub_menu_path(#pub), class: 'btn btn-primary' %>
So when I click the button, I get to the new_pub_menu_path(#pub) generated link, but I have an error ..
error
ActionView::Template::Error (undefined method `menus_path' for #<#<Class:0x007f652ce54550>:0x007f652c90c9a8>
Did you mean? user_path):
1:
2: <%= form_for ([#pub, #menu]), html: { multipart: true } do |f| %>
3: <%= render 'shared/error_messages', object: f.object %>
4:
5: <div class="form-group">
What should I do? I tried to use the nested routes so to have in the url the id pub, but when the new.html.file is rendered it gives me that error. I don't know what method menus_path is.
Thanks!

undefined method `menus_path' for
You didn't defined #pub in new method of menus_controller, so #pub is nil in new.html.erb, so is the error. Define it to resolve the issue.
def new
#menu = Menu.new
#pub = Pub.find(params[:pub_id])
end

Related

NameError in Roles#new , undefined local variable or method `permissions'

i'm doing role and permission. I want to add a permission checkbox to role create page, so when admin create role can tick the permission checkbox then store at role_permission.
I want the checkbox can connect with the permission_id because when i create one permission it will also show at the role create page.
Now i want to show the checkbox at the role create page but it give me some error.
role controller
def new
#role = Role.new
#role.company_id = params[:company_id]
#permission = Permission.all
end
def create
#role = Role.new(role_params)
#company_id = Company.find(params[:role][:company_id])
#permission_id = Permission.all
if #role.save
flash[:success] = "Succesful create!"
redirect_to #role
else
render 'new'
end
end
private
def role_params
params.require(:role).permit(:name, :company_id)
end
new.html.erb
<% provide(:title, "Create Roles") %>
<h1>Create Role</h1>
<div class="row">
<div class="col-md-6 col-md-offset-3">
<%= form_with(model: #role, local: true) do |f| %>
<%= permissions.each do |permission|%>
<%= render 'shared/error_messages', object: f.object %>
<%= f.label :name %>
<%= f.text_field :name, class: 'form-control' %>
<%= f.label :permission_id %>
<%= f.check_box_tag 'permission_ids[]', permission.id, false%>
<%= f.hidden_field :company_id , value: 2%>
<%= f.submit "Create Role", class: "btn btn-primary" %>
<% end %>
<% end %>
</div>
error show in website
error show in console
Update
error show after update
In a controller, the variable name should be plural as its array/multiple records.
def new
...
...
#permissions = Permission.all
end
And in a view we can use the same as below:
<%= #permissions.each do |permission|%>
<%= render 'shared/error_messages', object: f.object %>
Checkbox seems ok, but if you want to dig more, then can have a look at here: https://apidock.com/rails/v6.0.0/ActionView/Helpers/FormTagHelper/check_box_tag

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!

rails 4 - param is missing or the value is empty: projecttype

A newby to rails (I am building an app to learn rails) and run in to an issue I can't find a solution to (while following the getting started guide). I have studied the guides and similar questions
This is my code:
class ProjecttypesController < ApplicationController
def index
#projecttypes = Projecttype.all
end
def show
#projecttype = Projecttype.find(params[:id])
end
def new
end
def create
#projecttype = Projecttype.new(projecttype_params)
#projecttype.save
redirect_to #projecttype
end
private
def projecttype_params
params.require(:projecttype).permit(:name, :image, :url)
end
end
The form:
<%= form_for :projecttypes, url: projecttypes_path do |f| %>
<p>
<%= f.label 'Project type' %>
<%= f.text_field :projecttype %>
</p>
<p>
<%= f.label :name %>
<%= f.text_field :name %>
</p>
<p>
<%= f.label :image %>
<%= f.file_field :image %>
</p>
<p>
<%= f.label :url %>
<%= f.url_field :url %>
</p>
<p>
<%= f.submit %>
</p>
<% end %>
What am I doing wrong?
Perhaps important... when I use this...
def create
render plain: params[:projecttype].inspect
end
It returns 'nil'.
Thanks for your help
Your code should be like this
def new
#projecttype = Projecttype.new
end
def create
#projecttype = Projecttype.create(projecttype_params)
redirect_to #projecttype
end
and use this for form
<%= form_for #projecttype do |f| %>
In your
controller file
def new
#projecttype = Projecttype.new
end
and then in your form
<%= form_for #projecttype do |f| %>

Ruby on Rails won't render edit page without id

For some reason the edit action won't render i get this error and is using show action instead of edit but the same form works for the render :new action
do not focus on the params[:preview], i am talking about the last render :edit
ActionController::UrlGenerationError in Admin::Blog::Posts#update
No route matches {:action=>"show", :controller=>"admin/blog/posts", :id=>""} missing required keys: [:id]
def edit
#post = Post.find_by_permalink(params[:id])
end
def update
#post = Post.find_by_permalink(params[:id])
if params[:publish]
#post.publish
elsif params[:draft]
#post.draft
end
if params[:preview]
if #post.published?
#post.draft
end
if #post.update(blog_post_params)
flash[:success] = "some text "
redirect_to blog_post_url(#post)
else
render :edit
end
end
if #post.update(blog_post_params)
flash[:success] = "Post was successfully updated."
redirect_to edit_admin_blog_post_url(#post)
else
render :edit
end
end
form
<%= form_for [:admin,:blog, #post] do |f| %>
<%= render 'shared/error_messages', object: f.object %>
<div class="large-12 columns">
<div class="field panel">
<%= f.label :title %><br>
<%= f.text_field :title %>
</div>
<div class="field panel">
<%= f.label :description %><br>
<%= f.text_field :description %>
</div>
<div class="actions panel text-right">
<% if #post.published? %>
<%= f.submit "Save Changes",name: "publish", class: "tiny button radius success" %>
<% else %>
<%= f.submit "Publish",name: "publish", class: "tiny button radius success" %>
<% end %>
<%= f.submit 'Mark as Draft', name: "draft", class: "tiny button radius " %>
<% if #post.created_at %>
<%= f.submit 'Preview', name: "preview", class: "tiny button radius warning" %>
<% end %>
<%= link_to 'Back', admin_blog_posts_path, class: "tiny button radius secondary" %>
</div>
<div class="field panel">
<%= f.label :body %><br>
<%= f.cktext_area :body, :height => '800px', :id => 'sometext' %>
</div>
</div>
<% end %>
relevant routes
namespace :admin do
namespace :blog do
get '', to: 'welcome#index', as: '/'
resources :posts
end
end
post model
class Post < ActiveRecord::Base
has_many :tags
has_many :comments
before_validation :generate_permalink
validates :permalink, uniqueness: true
validates :title, presence: true
validates :description, presence: true
def generate_permalink
self.permalink = title.parameterize
end
def to_param
permalink
end
end
I guess i know why you get this error.
In the edit action you use Post.find_by_permalink(params[:id]) to find your post, which returns nil if nothing was found. And since you may change the title attribute, your permalink is updated (i guess), and your post is not found. The controller still renders the action, with nil #post, and cannot generate the url for the form.
Try using Post.find_by_permalink!(params[:id]) instead, and you will get a 404.
I would actually suggest you to use regular find in the admin area, since the permalink might change.

undefined method path with simple form

I have albums and pictures where albums hasmany pictures
This is my routes.rb
resources :albums do
resources :photos
end
Instead of photos_path my path is album_photos_path
In my photos/new.html.erb I'm getting this error:
undefined method photos_path' for #<#<Class:0x5232b40>:0x3cd55a0>
How I can do to instead of photos_path simple form write album_photos_path ?
My new.html.erb
<%= simple_form_for([#album, #photo]) do |f| %>
<%= f.error_notification %>
<div class="form-inputs">
<%= f.input :title %>
<%= f.input :description %>
</div>
<div class="form-actions">
<%= f.button :submit %>
</div>
<% end %>
You can specify url in your form. Like this:
<%= simple_form_for #photo, url: album_photos_path do |f| %>
<%= f.error_notification %>
<div class="form-inputs">
<%= f.input :title %>
<%= f.input :description %>
</div>
<div class="form-actions">
<%= f.button :submit %>
</div>
<% end %>
But your code should also work. In your new action did you initialize both #album and #photo, something like:
def new
#album = Album.find params[:album_id]
#photo = #album.pictures.build
end
P.S above code is just a sample code and if both variables(#album and #photo) are initialized properly then rails will automatically generate correct url.
You need to set the parent resource.
class PhotosController < ApplicationController
before_action :set_album
# GET /albums/1/photos/new
def new
#photo = #album.photos.new
end
# POST /albums/1/photos
def create
#photo = #album.photos.new(photo_params)
# ...
end
private
# ...
def set_album
#album = Album.find(params[:album_id])
end
end
The reason rails is trying to call photos_path is that the polymorphic route helpers which turn an array of models into a route helper method compact the array. url_for([nil, Photo.new]) will result in the same result as url_for(Photo.new) - photos_path.

Resources