Rails how to pass id to custom controller - ruby-on-rails

I am new to rails and trying to figure out how to pass id from view to controller. I have create below routes.rb file i didnt want resources here just to have better understanding of how to pass params
Rails.application.routes.draw do
get 'sites/edit/:id', to: 'sites#edit'
get 'sites/main'
devise_for :users
root 'sites#main'
# For details on the DSL available within this file, see http://guides.rubyonrails.org/routing.html
end
below is my controller
class SitesController < ApplicationController
def main
#site = Site.all
end
def edit
#site = Site.find(params[:id])
end
private
def site_params
params.require(:site).permit(:title, :subtitle,:name)
end
end
and i have two views for my site controller. In main.html.erb
<h1>Sites#main</h1>
<p><%= current_user.email %> user is signned in </p>
<%= #site.each do |temp| %>
<p><%= temp.name %></p>
<p></p>
<p></p>
<%= link_to "Edit Site", sites_edit_path(#temp) %>
<% end %>
I am not able to link it to correct controller.

First: your edit routes should not be
get 'sites/edit/:id', to: 'sites#edit'
Instead it should be get 'sites/:id/edit' => 'sites#edit'
Second: your link to method should not be
<%= link_to "Edit Site", sites_edit_path(#temp) %>
instead it should be <%= link_to "Edit Site", sites_edit_path(temp) %>
You can get to know about your routes from terminal by doing rake routes or If you want a browser view then
http://localhost:3000/rails/info/routes

You need to replace
<%= link_to "Edit Site", sites_edit_path(#temp) %>
to
<%= link_to "Edit Site", sites_edit_path(temp) %>
You have the variable temp not #temp
Also, As sarcastic suggested you need to change the route entry to
get 'sites/edit/:id', to: 'sites#edit', as: :sites_edit

Related

Param is missing or the value is empty - update method ruby on rails

I am working on an app for rockhounds that will allow them to track the rocks they have found. I am trying to finish a method that will allow users to update rocks. The method itself works if you go to the '/edit' page where you enter a url, but when trying to reach that page via a link from the show page for the rock I get an error:
Param is missing or the value is empty: rock
Its coming from line 43 in my rocks controller, inside the method rock_params. The parameters for this request are:
{"_method"=>"patch", "authenticity_token"=>"tiQQjQCMi6lbDPOxQ2X7fNTamWEZ3EAandGQ1Tv4NJKxieVIUnnWcKh3efd9F2LIRZWBYeC5M3RuEr0/FHQnww==", "id"=>"6"}
Here is my controller code
before_action :find_rock, only: [:show, :edit, :update, :destroy]
def index
#rocks = Rock.all
end
def show
#rock = Rock.find_by(id: params[:id])
end
def new
#rock = Rock.new
end
def create
#rock = Rock.new(rock_params)
if #rock.save
redirect_to #rock
else
render :new
end
end
def update
if #rock.update(rock_params)
redirect_to #rock
else
render :edit
end
end
def destroy
#rock = Rock.find(params[:id])
#rock.destroy
redirect_to rocks_path
end
private
def rock_params
params.require(:rock).permit(:id, :nick_name, :category, :minerals, :outcrop)
end
def find_rock
#rock = Rock.find(params[:id])
end
end ```
Here is the view code for the show page:
`<h1> Rock: </h1>
<h2> Rock Name: <%= #rock.nick_name %></h2>
<h2> Rock Type: <%= #rock.category %></h2>
<h2> Major Minerals: <%= #rock.minerals %></h2>
<h2> Outcrop? : <%= #rock.outcrop %></h2>
<%= link_to "Edit this rock", edit_rock_path(#rock), method: :patch %>
<%= link_to "Delete this rock", rock_path(#rock), method: :delete %> `
and the edit page:
```<%= form_for :rock do |f| %>
Name: <%= f.text_field :nick_name %><br>
Category: <%= f.select :category, ['Igneous', 'Sedimentary', 'Metamorphic'] %><br>
Major Minerals <%= f.text_area :minerals %><br>
Outcrop or Boulder? <%= f.select :outcrop, ['Outcrop', 'Boulder'] %><br>
<%= f.submit %>
<% end %> ```
and here are my routes:
```resources :rocks
resources :users
resources :locations
post '/users/new', to:"users#create"
get '/signup', to:"users#new", as: "signup"
post '/rocks/new', to:"rocks#create"
get '/rocks/:id/edit', to:"rocks#edit"
patch '/rocks/:id/edit', to:"rocks#update"
post '/rocks/:id/destroy', to:"rocks#destroy"
root to: "rocks#index"
get '/login', to: "auth#login", as: "login"
post '/login', to: "auth#authenticate"
get '/logout', to: "auth#logout"```
So the question is **How do I fix the empty param error that occurs when clicking the link to edit a rock from the show page for that rock?**
#toodles from the rails documentation here, edit paths are of the HTTP verb GET.
You need to change this line <%= link_to "Edit this rock", edit_rock_path(#rock), method: :patch %>, remove method: :patch which applies a PUT HTTP verb
It should look like this <%= link_to "Edit this rock", edit_rock_path(#rock) %> as rails applies the GET verb if the method is not specified.
You'll be able to see this when you inspect your link in a browser
Also, since you defined the resource :rocks, you don't need to redefine the other rock routes below it. You can see the generated routes with the rails routes command in your terminal.
You can also add an edit action to your controller, that returns #rock, which you use in the edit page. This section of the getting started with Rails article shows it clearly.

Rails route to a resource

I'm building a Rails app that is a podcast directory. I have Podcasts and Episodes. Episode belongs to Podcast and Podcast has many Episodes. On the home page I want to show the last 5 episodes that have been created and link to them.
I have it working with this, though this is obviously not the way to do it:
<% #episodes.each do |episode| %>
<%# link_to episode do %>
<%= episode.title %>
<%# end %>
<% end %>
The link_to is commented out because that's part of my problem.
Here is the index controller:
def index
#podcasts = Podcast.where.not(thumbnail_file_name: nil).reverse.last(5)
#episodes = Episode.where.not(episode_thumbnail_file_name: nil).reverse.last(5)
end
Here is the routes file:
Rails.application.routes.draw do
devise_for :podcasts
resources :podcasts, only: [:index, :show] do
resources :episodes
end
authenticated :podcast do
root 'podcasts#dashboard', as: "authenticated_root"
end
root 'welcome#index'
end
Results of rake routes | grep episode:
podcast_episodes GET /podcasts/:podcast_id/episodes(.:format) episodes#index
POST /podcasts/:podcast_id/episodes(.:format) episodes#create
new_podcast_episode GET /podcasts/:podcast_id/episodes/new(.:format) episodes#new
edit_podcast_episode GET /podcasts/:podcast_id/episodes/:id/edit(.:format) episodes#edit
podcast_episode GET /podcasts/:podcast_id/episodes/:id(.:format) episodes#show
PATCH /podcasts/:podcast_id/episodes/:id(.:format) episodes#update
PUT /podcasts/:podcast_id/episodes/:id(.:format) episodes#update
DELETE /podcasts/:podcast_id/episodes/:id(.:format) episodes#destroy
How can I correctly create a text link of the title using a link_to that links directly to the episode? Thanks!
When you're using link_to with a block, the only thing you need to pass into the block is the text of the link, so you should be able to do this (assuming your routes are setup properly):
<% #episodes.each do |episode| %>
<%= link_to episode, class="tt-case-title c-h5" do %>
<%= episode.title %>
<% end %>
<% end %>
UPDATE
You really don't even need to use a block here. This should work fine for you and be a little more succinct.
<% #episodes.each do |episode| %>
<%= link_to episode.title, episode, class="tt-case-title c-h5" %>
<% end %>
UPDATE #2
Thanks for including your route info. Try this:
<% #episodes.each do |episode| %>
<%= link_to episode.title, podcast_episode_path(episode.podcast, episode), class="tt-case-title c-h5" %>
<% end %>

link to last post - rails

Im trying to link_to the show action for a post.
In my controller I have:
#post = Post.all
In my view I'm trying to link it to the last post like this:
<%= link_to #post.last do %>
<%= #post.last.title %>
<% end %>
But it does not take me to the show page for that post?
Post.all loads all posts, but does not guarantee an order. You might want to use the id or the created_at value to order your list of posts:
# in your controller
#posts = Post.order(:id)
# in the view:
<%= link_to #posts.last.title, #posts.last %>
Or - if you don't need the other posts in the view - just load the lastest post:
# in the controller:
#latest_post = Post.order(:id).last
# in the view:
<%= link_to #latest_post.title, #latest_post %>
Try with below code,
<%= link_to post_path(#post.last) do %>
<%= #post.last.title %>
<% end %>
If this code not work then please find route with fire rake routes in your terminal and replace post_path with your routes
Hope this will work.

How to use one layout by two different actions in rails 4

I'm building a micropost rails app where users can create posts, I created a route and an action to display posts that belong to the signed-in user, happens that the general index layout for posts is exactly the same as the "myposts" layout so instead of duplicating code I would like to use just one layout with different parameters.
This is what I have until now:
routes.rb
resources :posts
get '/myposts', to: 'posts#my_posts', as: 'myposts'
posts_controller.rb
def index
#posts = Post.all
end
def my_posts
#myposts= Post.where(user_id: current_user.id)
end
index.html.erb
<% #posts.each do |post| %>
<div>
<h1><%= link_to post.title, post %></h1>
<%= link_to image_tag(post.meme_url(:thumb)), post, :target => "_blank" %>
</div>
<% end %>
my_posts.html.erb
<% #myposts.each do |post| %>
<div>
<h1><%= link_to post.title, post %></h1>
<%= link_to image_tag(post.meme_url(:thumb)), post, :target => "_blank" %>
</div>
<% end %>
Thanks in advance!
You can use 'render' on 'my_posts' action - http://guides.rubyonrails.org/layouts_and_rendering.html#using-render
Add before 'end' in my_posts action:
render :index

Why am I seeing "No route matches :action=>"show"" when my show action is defined for that controller?

I have a "Category" resource, and am trying to link to Categories#show in its index.html.erb file using the link_to method and the _path routes. When I view the index in my browser I see the following error:
Routing Error No route matches {:action=>"show", :controller=>"categories"}
But I do have a show action defined in my Categories controller, and removing the URI part of link_to causes the index to display normally without having an exception thrown! I can't figure out where I'm going wrong with the URI.
Here's /categories/index.html.erb:
<h1>My Links</h1>
<% #categories.each do |c| %>
<h2><%= link_to "#{c.category}", category_path %></h2>
<p><%= c.description %></p>
<% end %>
<%= link_to "Add new category", new_category_path %>
Here's /categories/show.html.erb:
<h1><%= #category.category %></h1>
<p><%= #category.description %></p>
<p><%= link_to "Back to index", root_path %></p>
Here's /config/routes.rb:
LinkManager::Application.routes.draw do
resources :categories do
resources :links
end
root :to => 'categories#index'
Here's part of /controllers/categories_controller.rb:
class CategoriesController < ApplicationController
def index
respond_with(#categories = Category.all)
end
def show
#category = Category.find(params[:id])
end
And here's the result of running rake routes (put it on pastebin since I couldn't figure out how to format it nicely here): rake routes
Can anyone spot what's wrong? I've looked at many other similar routing questions here but couldn't get a solution from them. Thank you.
Try to replace:
<h2><%= link_to "#{c.category}", category_path %></h2>
with:
<h2><%= link_to "#{c.category}", category_path(c) %></h2>
See? You have to provide a category for category_path.
Or just use the magic:
<h2><%= link_to "#{c.category}", c %></h2>
And by the way, what's the purpose of interpolation here: "#{c.category}"? Wouldn't simply c.category be enough?
Well, i think if you add other route to action show it works, do this:
do this in your browser:
localhost:3000/categories/show
and in your routes.rb:
match "/categories/show/:id" => categories#show
what is the version of our ruby and the version of rails?

Resources