I'm a beginner at rails and thus far interplating data in views has been pretty straight forward. I've been introduced to something slightly new as far as how the controllers are setup and as a result I'm not sure how one would go about getting the data to present in the view.
First controller
class PagesController < ApplicationController
def index
#guestbook_entry = GuestbookEntry.new
render "welcome"
end
end
Second controller
class GuestbookEntriesController < ApplicationController
def create
GuestbookEntry.create(guestbook_entry_params)
redirect_to root_path, notice: "Thank you for your entry."
end
private
def guestbook_entry_params
params.require(:guestbook_entry).permit(:body)
end
end
And here is the welcome.html.erb
<h1>Welcome to My Guestbook</h1>
<br>
<%= image_tag("under_construction.gif") %>
<div id="guestbook-entries">
<p>Guestbook Entries:</p>
<ul>
</ul>
</div>
<%= form_for #guestbook_entry do |f| %>
<%= f.label :body, "Guestbook Entry:" %>
<%= f.text_area :body %>
<%= f.submit "Submit" %>
<% end %>
So it wants me to iterate through all the entries and display them on a welcome page that's located in view/pages/welcome.html.erb.
Up to this point I guess I've only been doing basic simple rails applications where the view corresponded with the controller, and followed the typical CRUD setup, where index would hold the #xxx = Xxxx.all and new/create would handle #xxx = Xxxx.new/create/build. I thought I could simply move the PageController's index action to create/new and do
def index
#guestbook_entry = GuestbookEntry.all
render "welcome"
end
To satisfy the test (it looks for render welcome in the index action)
This seems weird but again I admit, I'm a beginner.
If you want to list all the guest book entries on your root page you would do something like:
class PagesController < ApplicationController
def index
#guestbook_entry = GuestbookEntry.new
#guestbook_entries = GuestbookEntry.limit(10).all
render "welcome"
end
end
And in your view you would list them like:
<% if #guestbook_entries.any? %>
<div id="guestbook-entries">
<p>Guestbook Entries:</p>
<% #guestbook_entries.each do |entry| %>
<ul>
<li class="entry"><%= h(entry.body) %></li>
</ul>
<% end %>
</div>
<% end %>
The rest of you application is correct - you should be creating entries in GuestbookEntriesController#create. In many real life applications then the functionality of the standard new and edit actions can actually be a totally different controller.
Related
Hello I'm still fairly new to Rails but, currently I have been working on a Rails project for bit now and my last issue with it is when someone clicks on a specific recipe it only shows the very first one a user ever created. I've accessed my database through my console to see if these recipes are saving and they are but when I click on any of the links to a specific recipe it still shows the incorrect one and it won't show the recipe name either.
Here's my recipe controller
class RecipesController < ApplicationController
before_action :require_login
def show
#recipe=Recipe.find_by(params[:name])
binding.pry
end
def index
#recipes =Recipe.all
#binding.pry
end
def new
#recipe = Recipe.new
#recipe.ingredients.build(name: "name")
end
def create
#recipe = Recipe.new(recipe_params)
#recipe.save
#binding.pry
redirect_to recipes_path
end
private
def recipe_params
params.require(:recipe).permit(:id,:name,:content, ingredients_attributes: [
:recipe_id,
:user_id,
:name,
:quantity
]
)
end
end
Index Page
<h1>All Recipes</h1>
<ul>
<% #recipes.each do |recipes| %>
<li><%= link_to recipes.name, recipes %></li>
<% end %>
</ul>
Show Page
<% #recipe.name do |r| %>
<h2> <%= r.name %></h2>
<h2> <%= r.content %></h2>
<%end%>
<h3>Ingredients</h3>
<ul>
<% #recipe.ingredients.each do |ingredient| %>
<li><%= "#{ingredient.name} X #{ingredient.quantity}" %></li>
<% end %>
</ul>
Any help would be appreciated
Thank you!
In your show method it's either one of those
Recipe.find_by(name: params[:name])
# or ...
Recipe.find(params[:id])
...depending on what setup you got going in your routes, the second one is the usual Rails way of doing things.
There are a few issues with your code. In your RecipesController, change the show action code to this:
def show
#recipe = Recipe.find(params[:id])
end
In your index.html.erb view, change the code that iterates through your recipes to this:
<% #recipes.each do |recipe| %>
<li><%= link_to recipes.name, recipe %></li>
<% end %>
And finally, in your show.html.erb view, change the code to this:
<h2><%= #recipe.name %></h2>
<h2><%= #recipe.content %></h>
<h3>Ingredients</h3>
<ul>
<% #recipe.ingredients.each do |ingredient| %>
<li><%= ingredient.name %> X <%= ingredient.quantity %></li>
<% end %>
</ul>
Summary of the changes
In the show action of the RecipesController, you search for the recipe by the id passed in from the view. That id comes from this line:
<%= link_to recipe.name, recipe %>
recipe gets to_param called on it, which returns the id of that particular recipe which you then use in the show action of the RecipesController to find the correct recipe.
In the index.html.erb view, you iterate through all of the recipes, via the #recipes variable, and output each recipe. Since you are outputting each recipe, you normally use recipe instead of recipes as the block variable.
In the show.html.erb view, you don't need to iterate through all recipes because you only have one recipe from the show action of the RecipesController. That recipe is stored in the #recipe variable, so you can use that variable directly in the view.
I'm having trouble with using link_to in Ruby on Rails. I'm making a blog like application which displays a feed of all user posts and allows users to click posts to view/edit them.
This is my _feed partial, which is used to render all the posts of a user.
<% if #feed_items.any? %>
<% #feed_items.in_groups_of(3, false).each do |feeds| %>
<div class="row">
<% feeds.each do |feed| %>
<div class="col-md-4">
<ol class="posts">
<%= link_to render feed , edit_post_path(feed) %>
</ol>
</div>
<% end %>
</div>
<% end %>
<% end %>
The line <%= link_to render feed , edit_post_path(feed) %> is what is throwing errors. I'm just not 100% certain how to write a link_to which also renders the feed. I've tried a lot of variations and nothing works. The error I get as it is currently written is: undefined method `keys' for "/posts/160/edit":String
This is my Posts controller, which I wrote after this error occurred in an attempt to fix it. I'm not sure if any of this is even necessary:
class PostsController < ApplicationController
before_action :find_note, only: [:show, :edit]
def edit
end
def show
end
private
def find_note
#post = Post.find(params[:id])
end
I'm sure my problem is super basic but I'm having trouble figuring out how to solve it. Any help is appreciated!
Use block to render a partial inside of a link:
<%= link_to edit_post_path(feed) do %>
<%= render feed %>
<% end %>
My form gets passed a 'new' Quiz (not saved to the database). My form partial looks like this:
<%= 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 %>
Here is my QuizzesController#create action:
def create
#results = Quiz.create(post_params) #from private method
if #results.save
redirect_to results_path
else
#error handle here
end
end
...which gets triggered when the user clicks 'get my results' on my quiz form. And the post_params method looks like this:
def post_params
params.require(:quiz).permit(:id, :user_id, :answer1, :answer2, :answer3, :answer4, :answer5, :answer6, :answer7, :answer8) #add other attributes here
end
My results/index.html.erb looks like this:
<div class="container">
<!-- Example row of columns -->
<div class="row">
<h1>Results</h1>
<p><%= #results.inspect %></p>
</div>
</div>
But that 'inspected' Quiz instance returns 'nil' for all the answers1, answers2 etc attributes. Any idea why that would be? Is there something I'm NOT doing to save the user's answers to the database?
The reason it shows nil is because you are not setting the variable.
After creating and saving, you redirect to results_path and the variable #results does not persist during a redirect. Without seeing the full code, I'll have to guess at your naming conventions but there are two ways to do this.
1) If you want to redirect to the index then in the code for your index action, you can set the variable:
#results = Quiz.last
This is easy to work with in development because you are the only user and this will always return the last quiz you created. Not so great in production.
2) The alternative is to redirect to the show action for that quiz.
def create
#results = Quiz.new(post_params)
if #results.save
redirect_to result_path(#results)
else
# error handle here
end
end
Again, I have had to guess that result_path is the correct path. Without seeing the full routes file, I cannot be sure but you can rename accordingly if necessary.
I am not sure if this is possible but I want to display a flash message to the user when they come onto on of the pages automatically. I kind of played around with it but no luck. Does anyone know how to do that if so any help would be greatly appreciated!
CODE FOR CONTROLLER
class BookinController < ApplicationController
def flash
flash.now[:notice] = "Test"
render :action => :new
end
def bookin
#alert = "Successfully saved!"
end
def bookout
#customer_list = Customer.all
#customer_name = params[:customer_name_in]
#r = Customer.find_by_last(#customer_name)
end
end
CODE FOR VIEW
<h2>The Maintenance Functions are restricted to authorized users.
Please login below</h2>
<%= form_tag(bookin_bookout_path, :method => "post") do %>
<div class="field">
Name
<%= text_field_tag :customer_name_in %>
</div>
<br>
Password
<%= text_field_tag :customer_name_in %>
</div>
<br>
<div class="actions">
<br>
<%= submit_tag "Submit Customer Name" %>
</div>
<% end %>
<h2> Main Menu</td> </h2>
You could try the bootbox-rails gem.
In a nutshell:
Add it to your Gemfile,
Add it to your app/assets/javascripts/applications.js
Put something like this in your view:
<script>
<%= raw #alerts %>
</script>
Put something like this in your controller:
#alerts = "bootbox.alert('Some kind of alert!');"
Flash
You'll want to set the flash message in the action, so it's there when the user hits the page
The flash is basically a session variable which will only persist per one action, meaning if you set it on your action, the next one will not have the same message
You can set the flash, as you've already done, like this:
def action
flash[:notice] = "Welcome to our website"
end
Code
As RSB has queried, you've not provided us with the most specific code. So instead, I'll show you a simple example and look out for some comments to come back with updates:
#app/controllers/bookin_controller.rb
class BookinController < ApplicationController
def index
flash[:notice] = "Welcome To Our Page!"
end
end
#app/views/bookin/index.html.erb
<%= flash[:notice] %>
This will display your message for the rendered action. You don't need any specific methods - just set the flash var value in the action you're rendering
I have the following in my view (index.html.erb) code:
<% #projects.each do |project| %>
<%= link_to (#project) do %>
<div id="tombstone">
...Some HTML here...
</div>
<% end %>
<% end %>
The goal is to have each project's synopsis displayed inside the tombstone DIV and have the entire DIV act as the link to the project's details page (show.html.erb).
My Controller has the following:
def show
#project = Project.find(params[:id])
end
and the routes has the following:
resources :projects do
...
resources :updates
end
The #project in the <%= link_to %> points back to the projects (index.html.erb) page, not to the project details page (show.html.erb) that the controller defines. I can only guess that the ID parameter isn't getting passed, but I can't figure out why.
<%= link_to(project) do %> # not #project
Technically you've been sent to index because #project probably new record. #project == Project.new, so link_to(Project.new) with GET request renders path to index action.