Rails 4 - Render controller variable - ruby-on-rails

I'm a Rails newbie and this seems like a trivial thing, but I can't figure out how to render this.
I have a form that takes in a string input:
<%= form_for #idea do |f| %>
<div>
<%= f.label :idea_list %>
<%= f.text_field :idea_list %>
</div>
<%= f.submit %>
<% end %>
And a controller:
class IdeasController < ApplicationController
def index
end
def new
#idea = Idea.new
end
def create
#idea = Idea.new(idea_params)
if #idea.save
render :index
else
render 'new'
end
end
private
def idea_params
params.require(:idea).permit(:idea_list)
end
end
I then want to render the idea_list parameter in index.html.erb, but cannot figure out how to do so. I've tried:
<p><%= #idea %></p>
but I get an output of #<Idea:0x007f8b16d98638>.
<% #idea do |idea| %>
<p><%= idea.idea_list %></p>
<% end %>
I've tried many variations of this but keep getting various errors.
Please help.

So #idea is an instance of an object. idea_list is an attribute. So you need to call #idea.idea_list. Any time you want to reference an instance of an object / model from a controller it's going to #instance.attribute.
In your case, it's going to be
<p><%= #idea.idea_list %></p>
If you want to show them from a list of the all, in your view it's
<%#ideas.each do |idea| %>
<p><% idea.idea_list%></p>
<% end%>
And in your controller it's
def index
#ideas = Idea.all
end

Related

Comments not displaying from rendered form

I am new to Ruby and I am trying to display comments on my show page but when I create a comment it does not display. I have rendered a partial on my show page in order to display the comments but they do not appear.
The strange thing is that the create action works but it takes me to this page: http://localhost:3000/hairstyles/2/comments which has nothing on it (in my app this page is under views>comments>create.html.erb) instead i'd like it to go to the view page for the hairstyle and display the comment..........
If anyone can help and see if there are any errors in my code I'd be grateful. Thanks in advance.
Comments Controller:
class CommentsController < ApplicationController
def new
#hairstyle = Hairstyle.find(params[:hairstyle_id])
#comment = Comment.new
end
def create
#comment = Comment.new(comment_params)
#hairstyle = Hairstyle.find(params[:hairstyle_id])
#comment.save
end
def destroy
end
end
private
def comment_params
params.require(:comment).permit(:content)
end
Hairstyle view page where I want to display the comments:
<div class="container">
<div>
<%= cl_image_tag #hairstyle.photo, width: 300, height: 200, crop: :fill %>
<h1><%= #hairstyle.name %></h1>
<p><%= #hairstyle.description%></p>
<p><%= #hairstyle.category%></p>
<p><%= #hairstyle.video_url %></p>
</div>
</div>
<div>
<%= link_to 'Back', hairstyles_path %>
</div>
<h6>Comments for: <%= #hairstyle.name %> <small><%= %></small></h6>
<h2>
<%= pluralize #hairstyle.comments.size, "comment" %>
</h2>
<div id="comments">
<% if #hairstyle.comments.blank? %>
Be the first to leave a comment for <%= #hairstyle.name %>
<% else %>
<% #hairstyle.comments.each do |comment| %>
<%= render 'comments/show', comment: comment %>
<% end %>
<% end %>
</div>
<%= render 'comments/form', comment: #comment %>
Comments form i am rendering which does work and is displayed:
views>comments>_form.html.erb
<div class="flex-box">
<%= simple_form_for([ #hairstyle, comment ]) do |form| %>
<%= form.input :content, as: :text %>
<%= form.button :submit %>
<% end %>
</div>
Comments content that I am rendering that does not display once I have added a comment to my hairstyle on the show page:
views>comments>_show.html.erb
<p><%= comment.content %></p>
The default behavior of rails controllers is it will redirect to the index page after the create method. that's why you are redirected to that path.
you can simply use redirec_to in your create method in your comment controller like below
def create
#comment = Comment.new(comment_params)
#hairstyle = Hairstyle.find(params[:hairstyle_id])
#comment.save
redirect_to hairstyle_path(#comment.hairstyle)
end
You never link your comment to your hairstyle, your hairstyle_id from your comment is nil this is why #hairstyle.comments returns an empty array
def create
#hairstyle = Hairstyle.find(params[:hairstyle_id])
#comment = #hairstyle.comments.build(comment_params)
# equivalent to:
# comment = Comment.new(comment_params)
# comment.hairstyle = #hairstyle
if comment.save
redirect_to hairstyle_path(#hairstyle)
else
# handle errors
end
end

Rails - nested loops inside view

I'm taking up rails as a hobby but I'm still fairly new so apologies if this sounds ridiculous. I'm creating a board that can have many statuses. And each status can have many notes. However, this error comes up once I added the notes loop into the status loop on the view:
undefined method `notes' for nil:NilClass
Snippet of the boards/show.html.erb file:
<% #board.statuses.each do |status| %>
<div>
<h2><%= link_to status.name, status_url(status)%></h2>
<% #status.notes.each do |note| %>
<h2><%= link_to notes.content, note_url(note)%></h2>
<% end %>
<%= link_to 'New notes', new_note_path(#note) %>
</div>
<% end %>
I'm not sure if I'm doing something wrong within the controllers or the view though. I've been having a hard time figuring it out. I appreciate any help though!
notes_controller:
class NotesController < ApplicationController
def new
#note = Note.new
end
def create
Note.create(note_params.merge(status_id: current_user.id))
redirect_to boards_url
end
def delete
Note.find(params[:id]).destroy(note_params)
end
def update
Note.find(params[:id]).update(note_params)
end
def note_params
params.require(:note).permit(:status_id, :content)
end
end
statuses_controller:
class StatusesController < ApplicationController
def new
#status = Status.new
end
def create
Status.create(status_params.merge(board_id: current_user.id))
redirect_to :root
end
def delete
Status.find(params[:id]).destroy(status_params)
end
def update
Status.find(params[:id]).update(status_params)
end
def show
#status = Status.find(params[:id])
end
def status_params
params.require(:status).permit(:board_id, :name)
end
end
Any more information required then let me know. Thank you. :)
I'm thinking it should look more like:
<% #board.statuses.each do |status| %>
<div>
<h2><%= link_to status.name, status_url(status)%></h2>
<% status.notes.each do |note| %>
<h2><%= link_to notes.content, note_url(note)%></h2>
<% end %>
<%= link_to 'New notes', new_note_path(#note) %>
</div>
<% end %>
So that you're using the notes from the status in a given loop.
The error you're getting is because in this line <% #status.notes.each do |note| %> the view is expecting to be passed #status object from the show action in the board's controller. Since you aren't passing that #status, it's nil and nil doesn't have the method notes.
As #jvillian pointed out, it should be <% status.notes.each do |note| %> because you want to get the notes from the statuses you're iterating over with each in this line: <% #board.statuses.each do |status| %>

how to hide database information on view?

when I attempt to run my code, I got the error above.
As you can see on the following image, the page posts/index leaves appear some information before the footer of the page :
I don't understand where it may come, because it's the only page where it appeared.
Here's my view :
<%= #post.each do |post| %>
<h1 class="Blog_post_title"><%= link_to post.title, post %></h1>
<p class="date"><%= post.created_at.strftime("%B, %d, %Y") %></p>
<p><%= image_tag post.landing_image.url , class: "landing_image_blog" %></p>
<p><%= post.body %></p>
<%= link_to post do %>
<div class="button12">Continuer la lecture</div>
<% end %>
<div class="border_grey_blog"></div>
<% end %>
</div>
<%= render "footer" %>
my posts_controller.rb:
class PostsController < ApplicationController
def index
#post = Post.all.order('created_at DESC')
end
def new
#post = Post.new
end
def show
#post = Post.find(params[:id])
end
def edit
#post = Post.find(params[:id])
end
def update
#post = Post.find(params[:id])
if #post.update(params[:post].permit(:title,:title2,:title3,:title4,:title5,:title6,:title7,:title8,:title9, :body, :image,:image1,:image2,:image3,:image4,:image5,:image6,:image7,:image8, :landing_image, :some_text1, :some_text2, :some_text3, :some_text4, :some_text5, :some_text6, :some_text7, :some_text8, :some_text9, :some_text0))
redirect_to #post
else
render 'edit'
end
end
def create
#post = Post.new(post_params)
if #post.save
redirect_to #post
else
render 'new'
end
end
def destroy
#post = Post.find(params[:id])
#post.destroy
redirect_to "/posts"
end
private
def post_params
params.require(:post).permit(:title, :body, :image,:image1,:image2,:image3,:image4,:image5,:image6,:image7,:image8, :landing_image, :some_text1, :some_text2, :some_text3, :some_text4, :some_text5, :some_text6, :some_text7, :some_text8, :some_text9, :some_text0, :title2,:title3,:title4,:title5,:title6,:title7,:title8,:title9)
end
end
Any idea ?
Your mistake is in the very first line of the view:
<%= #post.each do |post| %>
should be
<% #post.each do |post| %>
since <%= opens an expression tag that will display its content.
It looks like your outputting the result of #posts.each. Notice how you did this in your view:
<%= #post.each do |post| %>
# other code
<% end %>
This will actually output all the data in the array as a ruby object. If you want to change this to not output everything, you need to change it to
<% #post.each do |post| %>
# other code
<% end %>
This will now not return the #post.each in the html.

Rails: If my Quiz model should be created on completing the quiz, how does form_for know what to refer to?

I've been told that I should not create my Quiz object before my quiz is completed; A user could go to the quiz page, not complete it, and there would be an 'unused' quiz sitting on the database. I can see the logic of that.
I CAN'T see how my quiz is supposed to work without being passed a #quiz object. Here's my QuizzesController, which, when the quiz is needed, gets routed to the 'new' action:
class QuizzesController < ApplicationController
def index
end
def new
#user = current_user
#quiz = Quiz.create(user_id: current_user.id)
end
def create
#results = Quiz.where(user_id: current_user.id).last
redirect_to results_path
end
end
At the moment, you can see that I'm coding the actions as simply as possible. Later, in the 'new' action, I'll add a test to see if the current_user has done the quiz and, if so, redirect to results_path.
Here is my form partial which is rendered as part of quizzes/new.html.erb:
<%= form_for(#quiz) do |f| %>
<p>
<%= f.check_box(:answer1) %>
<%= f.check_box(:answer2) %>
<%= f.check_box(:answer3) %>
<%= f.check_box(:answer4) %>
<%= f.check_box(:answer5) %>
<%= f.check_box(:answer6) %>
<%= f.check_box(:answer7) %>
<%= f.check_box(:answer8) %>
</p>
<p>
<%= f.submit("Get my results!") %>
</p>
<% end %>
Once again, the quiz is very simple while I figure out what's going on.
But I'd like to know, if the #quiz object is not created in the 'new' action, what would I pass into form_for to build the form?
You can instantiate a Quiz object without saving it to the database:
def new
#user = current_user
#quiz = Quiz.new(user_id: current_user.id)
end
The generally used sequence of requests/actions is the following:
The new action just initializes the model's instance with default values, and renders the record with empty fields, usually in a edit view.
def new
#quiz = Quiz.new(user_id: current_user.id)
render :edit
end
create action create the record, and after the create action you should render either the view of the newly created record by redirection to show action with the same view, or to redirect to a new action, in case you are creating a sequence of the same instances of a model.
def create
#quiz = Quiz.create(params)
render :show # or redirect_to :new
end
edit action is to prepare edit fields, is it renders edit view with filled-in fields.
def edit
#quiz = Quiz.where(id: params[:id]).first
end
update action updates the record with values set in edit view, then it renders the show view on the current record.
def update
#quiz = Quiz.update(params)
render :show
end
show action just shows the model's found out with stored in the DB values, then it renders show view with filled-in fields.
def show
#quiz = Quiz.where(id: params[:id]).first
end
So in your show.erb view you get rendering the newly built, or found out instance of Quiz:
<%= form_for #quiz, url: {action: "create"} do |f| %>
<p>
<%= f.check_box(:answer1) %>
<%# ... %>
</p>
<p>
<%= f.submit "Create Quiz" %>
</p>
<% end %>
But I prefer simple-form gem:
<%= simple_form_for #quiz do |f| %>
<%= f.input :answer1, as: :boolean, checked_value: true, unchecked_value: false %>
<%= f.button :submit %>
<% end %>

Error: param is missing or the value is empty: thing

I'm using rails 4.0.8. I added a comment section to a model called 'Things', but I keep getting the same error "param is missing or the value is empty: thing" when I press the submit comment button. It says the error is in the Things#Controller. What am I doing wrong?
UPDATE: I removed the url path from the form, but a new error returns "Couldn't find Thing without an ID". The error is in Comments#Controller.
VIEW FOR THING/SHOW
<div id= "thing">
<h1>
<%= #thing.name %>
</h1>
<br>
<div id= "commentsection">
Comments
<div id= "comments">
<br>
<% #thing.comments.each do |c| %>
<%= c.username %>
<br>
<%= c.text %>
<% end %>
<%= form_for #comment, :url => thing_path do |f| %>
<%= f.label :username %>
<%= f.text_field :username %>
<%= f.label :comment %>
<%= f.text_field :text %>
<%= f.submit "Enter", class: "btn btn-small btn-primary" %>
<% end %>
</div>
</div>
</div>
THINGS CONTROLLER
class ThingsController < ApplicationController
def show
#thing = Thing.find(params[:id])
#thing.comments.build
#comment = Comment.new
end
def index
end
def new
#thing = Thing.new
#things = Thing.all
end
def create
#thing = Thing.new(thing_params)
if #thing.save
redirect_to #thing
else
render 'new'
end
end
private
def thing_params
params.require(:thing).permit(:name, :avatar)
end
end
COMMENTS CONTROLLER (I put asterisks around the line where the error is)
class CommentsController < ApplicationController
def show
#comment = Comment.find(params[:id])
end
def new
#comment = Comment.new
#comments = Comment.all
end
def create
****#thing = Thing.find(params[:thing_id])****
#comment = #thing.comments.create(comment_params)
redirect_to thing_path(#thing)
end
end
private
def comment_params
params.require(:comment).permit(:user, :text, :upvotes, :downvotes, :thing_id)
end
end
ROUTES
Website::Application.routes.draw do
get "comments/new"
get "comments/show"
get "things/new"
root 'home_page#home'
get "all/things/new" => 'things#new'
get "all/allthings"
resources :things
resources :good_comments
get "things/show"
get "things/results"
end
You are posting the #comment form to post '/things' path.
<%= form_for #comment, :url => thing_path do |f| %>
It should just be <%= form_for #comment do %> (Rails is smart enough to plug in the comments_path) or if you feel like being more explicit (even though it's not necessary)
<%= form_for #comment, url: :comments_path do %>
Another note though, if you want that Comment to be tied to that specific Thing then in your models it should be
Class Thing
has_many :comments
end
Class Comment
belongs_to :thing
end
Then make sure in your database comment has a thing_id foreign_key field and then your form for comment should actually look like
<%= form_for #thing, #comment do %>
<% end %>

Resources