Why is this rails simple form not working? - ruby-on-rails

I am making a rails application. After a user has registered (I have already created user registration with devise), they can fill out this form that will contain their profile information. I have done this several times, and i can't find what is wrong. Here is the model:
class Information < ActiveRecord::Base
belongs_to :user
end
Here is the controller:
class InformationsController < ApplicationController
def new
#information = Information.new
end
def create
#information = Information.create(params[:information])
redirect_to student_path
end
def index
end
end
And here is the view for the new action.
<div class="span6 offset3 text-center">
<h1>Edit your information</h1>
<%= simple_form_for #information do |f| %>
<%= f.input :skills %>
<%= f.input :looking_for, :label => 'What help do you need?' %>
<%= f.input :my_idea %>
<%= submit_tag "Save", :class => "btn btn-primary btn-large" %>
<% end %>
</div>
Here is the line in the routes file:
resources :informations
I get the following errors which make no sense to me:
undefined method `information_index_path' for #<#:0x007f9c00c7b3e0>
Does anyone know how to fix this? Thanks.
UPDATE:
When I did rake routes, For informations#create, which is what the form should be going to, it has a blank path. There is also informations#index, which is what I guess its going to now. How do I get it to go to informations#create if the path is blank?

Please try yanking out the comments (# signs) in lines 6 and 9 of your view. They might be messing up the ERB processing.

Can you try informations_path? See here.

The problem was with naming the resource information. As information is the same plural as it is singular, it was confusing rails. I renamed the model description and the controller descriptions_controller, and it worked.

Related

"No route matches [POST]" despite Resources in my Routes file

I am creating a Rails app, and I need a form to function in one of my views and submit data to a table without the use of a scaffold (like I usually do).
Now, the place where this comment form is going to appear is in one view within the blog folder. It will need to allow the user to put in their comment, save it to the table, and then return to the same page.
While this is a pretty commonplace error, I am confused because I am specifying two things that seem critical: creating resources in my routes file for the form, and second, using a create method in my controller.
In the blog.html.erb, this happens in this form:
<%= form_for :cements do |f| %>
<div class="form-group">
<div class="field">
<%= f.label :post %><br>
<%= f.text_area :post, class: "form-control" %>
</div>
</div>
<h5 id="username">Username</h5>
<div class="form-group">
<div class="field">
<%= f.text_field :username, class: "form-control" %>
</div>
</div>
<%= f.hidden_field :slug, :id => "hiddenPicker"%>
<div class="actions">
<%= f.submit "Save", class: "btn btn-success-outline" %>
</div>
<% end %>
Then, in my controller, I have a create method that should redirect back to the original page, as I wanted.
blogs_controller.rb
class BlogsController < ActionController::Base
def index
#posts = Post.order('updated_at DESC').all
#comments = Cement.all
end
def blog
#posts = Post.where(slug: params[:id]).all
#comments = Cement.all
end
def create
#cements= Cement.new(story_params)
#cements.save
redirect_to(:back)
end
private
def story_params
params.require(:cements).permit(:username, :post, :slug)
end
end
Good news: the comment form renders in the view. Bad news: when I submit, I am getting this error: No route matches [POST] "/blog".
My expectation is this will be an issue with my Routes file; however, I have a resources method already in there:
Rails.application.routes.draw do
resources :posts
resources :cements
resources :blogs
The naming convention is the same as my controller file, so I am confused why this error is happening. Any ideas?
:cement is not an object it is just a symbol, so how rails will determine where to POST form? If you inspect your form you will see form action as /blog (current page url).
You should either do
<%= form_for :cements, url: cements_path do |f| %>
or
<%= form_for Cement.new do |f| %>
Both of above will generate form action as /cements, which will submit to CementsController create action, But I see in your case you want to submit it to BlogsController so use the appropriate routes(blogs_path). You can use url in second version also.

Rails NoMethodError

I'm having an issue very similar to the one asked in this question here: NoMethodError / undefined method `foobar_path' when using form_for However the answer there confuses me.
I went through Michael Hartel's Ruby on Rails tutorial before developing the application I'm working on at the moment, I tried to copy exactly what he did when he created a user model as I created my model. My application is designed to be a database for university professors, so the model I'm using is called "professor" but it's the same concept as "user".
Here is the code for my New.html.erb where is where users go to create a new professor:
<%provide(:title, 'Add a professor') %>
<div class="jumbotron">
<h2> New Professor</h2>
<div class="row">
<div class="col-md-6 col-md-offset-3">
<%= form_for (#professor) do |f| %>
<%= f.label "First Name" %>
<%= f.text_field :fname %>
<%= f.label "Last Name" %>
<%= f.text_field :lname %>
<%= f.label "School" %>
<%= f.text_field :school %>
<%= f.submit "Add this professor", class: "btn btn-primary" %>
<% end %>
</div>
</div>
</div>
And then here is the code from the Professor_controller.rb
class ProfessorController < ApplicationController
def show
#professor = Professor.find(params[:id])
end
def new
#professor = Professor.new
end
end
When I replace
<%= form_for (#professor) do |f| %>
In new.html.erb with:
<%= form_for (:professor) do |f| %>
It works. The thread I mentioned above said something about adding a route for the controller. My routes.rb looks like this:
Rails.application.routes.draw do
root 'static_pages#home'
get 'about' => 'static_pages#about'
get 'newprof' => 'professor#new'
resources :professor
And I don't believe that in Michael Hartel's book he does anything differently. I'm still very new to Rails so forgive me if this is a bit of an easy question, I've been stuck on it for a few days and I've tried numerous work arounds, using the instance of :professor works but #professor does not and I don't know why.
Within the Rails environment it's very important to be aware of the pluralization requirements of various names. Be sure to declare your resources as plural:
resources :professors
Declaring it in the singular may mess up the automatically generated routes, you'll get thing like professor_path instead of professors_path. You can check what these are with:
rake routes
If you get errors about x_path being missing, check that there's a route with the name x in your routes listing. The most common case is it's mislabeled, a typo, or you've failed to pluralize it properly.

Rails Undefined method

I already know there is a lot of undefined method questions, But I can't see whats wrong with mine so I need some help!
heres my form that i have
<% title("Home Page") %>
<h1><i class="fa fa-home"></i> Add Event <small>views/pages/home.html.erb</small></h1>
<div class="row">
<%= simple_form_for Newevent.new do |f| %>
<%= f.input :eventname, required: true %>
<%= f.input :eventdesc %>
<%= f.input :eventdate %>
<%= f.input :eventimage %>
<div class="col s6">
<%= f.input :stubhublink %>
<%= f.input :seatwavelink %>
<%= f.input :viagogolink %>
</div>
<%= f.button :submit %>
<% end %>
</div>
I also have this in the controller
def create
create_params = params[:newevent].permit(:eventname, :eventdesc, :eventdate, :eventimage, :viagogolink, :seatwavelink, :stubhublink)
#newevent = Newevent.new(create_params)
byebug
#newevent.save!
end
and this in the model
class Newevent < ActiveRecord::Base
def params
params.require(:newevent).permit(:eventname, :eventdesc, :eventdate, :eventimage, :viagogolink, :seatwavelink, :stubhublink )
end
end
It was working fine with 3 (which were eventname, eventdate and eventimage) however after adding the other 4 in it now doesn't work. Any ideas?
Sorry heres the error!
NoMethodError in Newevents#new
Showing /Users/samroberts/Desktop/admitme/app/views/newevents/new.html.erb where line #6 raised:
undefined method `eventdesc` for #<Newevent:0x007fcaeee41f68>
Sam
Several problems here buddy:
1. eventdesc Missing
The simple explanation for your error is that your eventdesc attribute is missing from your NewEvent model's table.
Since we don't have your table - or migrations - to observe, I'll have to give you a simple test:
<%= simple_form_for Newevent.new do |f| %>
<%= f.input :eventname, required: true %>
<%= f.input :eventdesc %> #-> remove this line
...
Remove that, refresh the page and see if it works. If the error persists, it may mean another attribute is missing. If it disappears, it means this attribute is missing from your db, and as such you should use rails g migration to create a new one:
$ rails g migration AddEventDesc
#db/migrate/add_event_desc_xxxxxxxx.rb
class AddEventDesc
def change
add_column :new_events, :eventdesc, :string
end
end
2. Params
Part of Rails 4's infrastructure is to use strong params to pass data from your controller to model.
As such, you need the following syntax:
#app/controllers/new_events_controller.rb
class NewEventsController < ApplicationController
def new
#newevent = NewEvent.new
end
def create
#newevent = NewEvent.new new_event_params
#newevent.save
end
private
def new_event_params #-> you can call this whatever you like
params.require(:newevent).permit(:eventname, :eventdesc, :eventdate, :eventimage, :viagogolink, :seatwavelink, :stubhublink )
end
end
You need to keep your strong params function in your controller, not your model.
3. Model Name
Finally, this won't do much for you directly, but in the long run will help you massively; your model name.
Your model is NewEvent.
If this is what you want to call it, that is good. However, I have found the best way forward with model names is to keep them simple, preferably to one word.
I'd strongly recommend calling your model Event, so you can call #event = Event.new etc -- it just flows better.

The better way to pass the foreign_key value to the Rails controller

It's been almost a week since I've began to dig deeper in forms , associations , hashes , symbols... But it seems I cannot solve the puzzle without your help .
I am working on a project for displaying different galleries content . The basic idea is when the user sees the names of galleries (names are links ) to be able to click on chosen one. Then all the images ,that belong to this gallery , are displayed . On the bottom there should be a link "Add image in this gallery" .
My models :
class Gallery < ActiveRecord::Base
attr_accessible :name
has_many :pictures
end
class Picture < ActiveRecord::Base
attr_accessible :image
belongs_to :gallery
end
I have created index on gallery_id for the 'pictures' table .
My big problem appears here , how to pass the gallery_id to the controller's action 'new' . As I've seen in "Agile web development with Rails" it could be :
<%= link_to 'Add a picture here...',new_picture_path(:gallery_id=>#gallery.id) %>
As it seems in this case the foreign_key :gallery_id is exposed in the URL bar of the browser . The second problem is that :gallery_id is available for the controller 'new' function , but "disappears" for the 'create' function (causing an error " Couldn't find Gallery without an ID ") .
The problem is gone when I add a hidden field in the _form for pictures , in my case :
<%= form_for(#picture) do |f| %>
<div class="field">
<%= f.hidden_field :gallery_id , :value=>params[:gallery_id] %>
<%= f.label :image %><br />
<%= f.file_field :image %>
</div>
<div class="actions">
<%= f.submit "Create" %>
</div>
<% end %>
Here are my definitions in the 'pictures' controller :
def new
#gallery=Gallery.find(params[:gallery_id])
#picture=#gallery.pictures.build
end
def create
#gallery = Gallery.find(params[:gallery_id])
#picture = #gallery.pictures.new(params[:picture])
if #picture.save
redirect_to(#picture, :notice => 'Picture was successfully created.')
else
redirect_to(galleries ,:notice => 'Picture was NOT created.')
end
end
And finaly the link_to definition in show.html.erb for galleries:
<% for picture in selpics(#gallery) %>
<div id= "thumb" >
<%= image_tag picture.image %>
</div>
<% end %>
<%= link_to 'Add a picture here...',new_picture_path(:gallery_id=>#gallery.id) %>
Here is the debug output before submitting the image :
--- !map:ActiveSupport::HashWithIndifferentAccess
gallery_id: "6"
action: new
controller: pictures
and after submitting the 'create' button (with exception raised ) :
{"utf8"=>"✓",
"authenticity_token"=>"IGI4MfDgbavBShO7R2PXIiK8fGjkgHDPbI117tcfxmc=",
"picture"=>{"image"=>"wilsonblx.png"},
"commit"=>"Create"}
As you see , there is nothing like "gallery_id" in the "pictures" hash .
Summarizing my questions to you :
Is there a way to pass the foreign_key without hidden_field ?
Could I hide somehow passing the foreign key form showing in the URL bar ?
Is there an alternative on passing arguments using 'link_to' ?
Thank you .
You may want to consider reading the Rails Guide on nested resources:
http://guides.rubyonrails.org/routing.html#nested-resources
In a nutshell:
routes.rb
resources :galleries do
resources :pictures do
end
# Generates the routes: /galleries/:gallery_id/pictures
pictures_controller.rb
def new
#gallery = Gallery.find(params[:gallery_id])
#picture = Picture.new
end
def create
#gallery = Gallery.find(params[:gallery_id]) # gallery_id is passed in the URL
#picture = #gallery.build(params[:picture])
if #picture.save
# success
else
# fail
end
end
pictures/new.html.erb
<%= form_for [#gallery, #picture] do |f| %>
<div class="field">
<%= f.hidden_field :gallery_id , :value=>params[:gallery_id] %>
<%= f.label :image %><br />
<%= f.file_field :image %>
</div>
<div class="actions">
<%= f.submit "Create" %>
</div>
<% end %>
Ok, so the gallery_id is still passed through the URL, but I don't really see anything wrong with that. You have to pass it somewhere, right? You really only have 3 sane choices on where to pass it: a hidden field, as a querystring parameter, or tucked away inside the URL (nested resource). Of the 3, the latter is IMHO the cleanest method.
If you want to make things even easier on yourself, I highly recommend looking into Jose Valim's Inherited Resources gem that takes care of a lot of this boilerplate nastiness for you:
https://github.com/josevalim/inherited_resources
You need not use the numeric ID's in your RESTful routes. Look at permalink_fu, and use the :permalink field rather than the :id to refer to each gallery resource.
/galleries/louvre
/galleries/moma/382
And
... new_picture_path(:gallery_id => #gallery.permalink)
The key here is using a symbolic, unique key that's not the ID, permalink's are pretty good for that.
You can choose to pass the permalink in as :id and update your controller actions to expect that.

Why is the form posting to the wrong url?

My form looks like:
<%= form_for [:admin, #post] do |f|%>
<div style="width:660px;">
<%= f.text_field :title, :size => 150 %>
<br/>
<%= f.text_area :body, :id => "body", :rows => 15 %>
<br/>
<%= f.submit %>
</div>
<% end %>
the url currently is:
http://localhost:3000/admin/posts/21/edit
my rake routes for the admin post edit is:
edit_admin_post GET /admin/posts/:id/edit(.:format)
for some reason the edit_admin_post_path is returning:
/admin/post/the-post-title/edit
so I manually changed the post title to the id.
when I perform the update, i redirect:
if #post.update_attributes(params[:post])
redirect_to edit_admin_post_path #post
end
But again it is redirecting with the 'post-title' instead of the id.
why is this?
this is rails 3
NOTE:
For the show url, I wanted /post/my-post-title and not /post/234 so I'm not sure where I changed that b/c I see no reference for it in my code!
It sounds like you have something along these lines defined in your post model:
class Post < ActiveRecord::Base
def to_param
#{name}"
end
This will cause it to return just the name instead of the ID. Remove any to_params you have defined in your post model and see if that resolves it.
Change it to something like this:
def to_param
"#{id}-#{name}".downcase.gsub(/\W+/, "-").gsub(/^[-]+|[-]$/,"").strip
end
This will give you fairly clean URLs, such as: http://localhost:3000/admin/posts/21-my-post-title/edit and Post.find(21-my-post-title) works the same, essentially, as Post.find(21).

Resources