I created a form to create articles, but I can only see the published articles on the index page, and, I'm unable to see individual articles.
Every time I click on 'show' for an individual article on the index, it opens a blank page with a URL like localhost:3000/articles.1, instead of localhost:3000/articles/1.
I don't know what's wrong with the code, it's similar to the code I have for creating and editing articles as admin and it works there, but I keep getting this error.
Here's the code:
views/articles/show.html.erb:
<h1><%= #article.name %></h1>
<%= #article.content %>
<%= image_tag #article.photo.url(:small) %>
<p>Tags: <%= raw article.tag_list.map { |t| link_to t, tag_path(t) }.join(', ') %></p>
<%= link_to 'Back', noticias_path %>
views/articles/index.html.erb:
<% #articles.each do |article| %>
<div>
<h2><%= article.name %></h2>
<%= article.content %>
<p><%= link_to 'Show', noticias_path(article) %></p>
<p>Tags: <%= raw article.tag_list.map { |t| link_to t, tag_path(t) }.join(', ') %></p>
</div>
<% end %>
articles_controller.rb:
# GET /articles/1
# GET /articles/1.json
def show
#article = Article.find(params[:id])
end
routes.rb:
Blog::Application.routes.draw do
root to: 'welcome#index'
get 'tags/:tag', to: 'noticias#index', as: :tag
get "noticias/index"
get "dashboard/index"
get "/sitemap" => "sitemap#index", :as => :sitemap, :defaults => {:format => :xml}
match '/noticias', to: 'noticias#index', via: 'get'
get 'login', to: 'sessions#new', as: 'login'
get 'logout', to: 'sessions#destroy', as: 'logout'
resources :users
resources :sessions
namespace :admin do
get '', to: 'dashboard#index', as: '/'
resources :noticias
end
end
It's more a problem with noticias_path, consider verify your routes with rake routes, but I think to change noticias_path to noticia_path, may can fixed it.
Based on your routes file, it looks like the problem is indeed incorrect routing. Presently, you are manually creating routes for RESTful resources, when you should simply let rails handle that for you properly.
Remove the manual get and match lines:
get "noticias/index"
match '/noticias', to: 'noticias#index', via: 'get'
And replace them with this:
resources :noticias
If noticias should be pointing to the ArticlesController (or any other controller), then simply do this:
resources :noticias, to: 'articles'
Also, Matheus Caceres was correct that the URL helper should in fact be noticia_path for the show action. The noticias_path points to the index action. Rails tries to be "helpful" by making routes, helpers, functions, etc, sound proper if read in English, but might not necessarily make sense for words in another language. I don't know if "noticia" makes any sense in Portuguese though.
Another quick side note, the two manual routing lines I indicated above are redundant; they would in fact both match a GET request and route them to noticias#index. However, keep in mind that routes are matched in the order they appear in the routing file, so the match line would never have been called, since the route would have matched on that get line.
Related
Working on versions:
Ruby: 3.0.2
Rails 6.1.4
I'm trying to put a button in my View template for "Users" that will set the :mod attribute to false, with the button just being "Demote User".
I had it working SOMEHOW using a helper method, demote_user, and some variation of
<% if logged_in? && current_user.admin? %>
<%= link_to "Demote User", user_path(#user), onclick: demote_user(#user), class: "btn btn-info" %>
<% end %>
I messed up however it was working when trying to move this method into a controller for best practice. I'm not sure what format worked out, but I've tried many such as
:onclick => demote_user(#user)
onclick: 'demote_user(#user)'
onclick=demote_user(#user)
onclick='demote_user(#user)
and etc. Somehow, it did eventually work but I busted it. Now, every time I load the User's page, it's just executing demote_user(#user) without even needing to click the button, so refreshing a User's page is demoting them.
I am now trying to do this properly by creating a demote method in the UserController, but I have NO IDEA how to make the route, or make it work properly. Up until now, all my routes have been working using resources, and the basic new, create, destroy, etc.
I've been trying many different routes, and view formatting, with no luck and usually ending up with just: Routing Error
No route matches [GET] "/demote.3"
I'd like to be able to avoid using the Javascript onClick functionality and do it properly with the controller even if I could remember how to make it work, but I think my route, or view page, or controller is incorrect. Here are the contents of each file:
Controller
def demote
byebug
#user = User.find(params[:id])
#user.mod = false
redirect_to user_path(#user)
end
View
div class="container text-center mt-4">
<% if logged_in? && current_user.admin? %>
<%= link_to "Demote User", demote_path(#user), class: "btn btn-info" %>
<% end %>
</div>
Routes
Rails.application.routes.draw do
root 'pages#home'
get 'about', to: 'pages#about'
resources :articles
get 'signup', to: 'users#new'
resources :users, except: [:new]
get 'login', to: 'sessions#new'
post 'login', to: 'sessions#create'
delete 'logout', to: 'sessions#destroy'
resources :categories
post 'demote', to: 'users#demote'
end
Up until now, I've been following a course, and I've nailed everything in it and have added some of my own functionality, but I'm still not quite sure how to make sense of routes, or what paths it creates.
I'd like to make other similar custom controller functions beyond show, index, create, delete, update which are all I really understand how to build. I'm not even sure if POST is the correct call in the route.
I would just setup an additional RESTful action for the resource:
resources :users do
patch :demote
end
<% if logged_in? && current_user.admin? %>
<%= button_to "Demote User", demote_user_path(#user), method: :patch %>
<% end %>
You can use link_to instead of button_to but you need to use the correct method: :patch or data: { turbo_method: :patch } option depending on your version of Rails to get the javascript driver to do its trickery.
I want to create a text field that accepts input and when you press the button next to it, it will save these changes to the database. It will be a PUT request, updating the value in the database for this specific user (not the logged in user, this is a page for admins to update values for users).
This is what the structure should be, (code to follow below):
1) Create text field and button for this in show.html.erb
2) Create a function called set_wistia_project_ID for this in users_controller.rb, set button equal to this :action
3) Create a helper function called set_project_id in user.rb that is called by set_wistia_project_ID, which actually updates the database. I decided to split it up into two functions because I noticed a lot of Rails projects tend to separate and break up functionality into the controller and model.
4) Edit my routes.rb to include some strange code, which I'll be honest, have no idea what it actually does. But without it, the entire app crashes on Heroku. So I leave it there. Found from a StackOverflow post.
My show.html.erb:
<% provide(:title, #user.name) %>
<div class="row">
<aside class="col-md-4">
<section class="user_info">
<h1>
<%= gravatar_for #user %>
<%= #user.name %>
<br>
<%= #user.email %>
<br>
<div class="row">
<div class="col-md-6 col-md-offset-3">
<%= form_for(#user) do |f| %>
<%= render 'shared/error_messages' %>
<%= f.label :wistia_project_id %>
<%= f.text_field :wistia_project_id, class: 'form-control' %>
<%= button_to "Save", :action => "set_wistia_project_ID", :method => :put, :form_class => "form-control" %>
</div>
</div>
</h1>
</section>
</aside>
</div>
My users_controller.rb:
# Sets wistia_project_ID.
def set_wistia_project_ID
#user = User.find(params[:id])
#user.set_project_id
end
My user.rb:
# Sets the wistia_project_ID.
def set_project_id
self.wistia_project_ID # HOW TO SET EQUAL TO INPUT?
end
My routes.rb:
Rails.application.routes.draw do
root 'static_pages#home'
get 'password_resets/new'
get 'password_resets/edit'
get 'sessions/new'
get '/help', to: 'static_pages#help'
get '/about', to: 'static_pages#about'
get '/contact', to: 'static_pages#contact'
get '/signup', to: 'users#new'
post '/signup', to: 'users#create'
get '/login', to: 'sessions#new'
post '/login', to: 'sessions#create'
delete '/logout', to: 'sessions#destroy'
resources :users do
member do
put 'set_wistia_project_ID'
end
end
resources :account_activations, only: [:edit]
resources :password_resets, only: [:new, :create, :edit, :update]
end
But the problem I am having is that when I try to go to show.html.erb, my Heroku app crashes :(
The reason:
F, [2019-06-25T19:53:20.706881 #8] FATAL -- : [b2ed08bb-de52-417f-9ba8-8ec85629dce8]
app/views/users/show.html.erb:30:
syntax error, unexpected end-of-input, expecting end
But it looks fine to me?
The syntax error is that you are missing <% end %> for the <%= form_for(#user) do |f| %> block.
To answer your question about how to access the param in the model's method - you should pass it as an argument:
#user.set_project_id(params[:wistia_project_ID])
And change the method to accept an argument. Note, I am assuming you want to actually persist this to the database, so I'm adding a save call. You could alternatively call update which assigns the new value and saves in one go.
def set_project_id(val)
self.wistia_project_ID = val # self is necessary here
save # or self.save, but the self is unnecessary here
end
However, calling save does always succesfully save the record, there is still the possibility of an error if a model-level validation failed. You can handle this using flash: https://guides.rubyonrails.org/action_controller_overview.html#flash-now
or, if you don't need to redirect, can just use an instance variable to store the errors:
#user = User.find(params[:id])
#user.set_project_id(params[:wistia_project_ID])
unless #user.valid?
#errors = #user.errors.full_messages
render :show
end
and in the show view:
<% if #errors %>
<p>THE FORM COULD NOT BE SAVED </p>
<ul id='errors'>
<% #errors.each do |error| %>
<li><%= error %></li>
<% end %>
</ul>
<% end %>
Also note, I would probably rename your set_project_id method to set_project_id! (added a bang), to signify that it mutates the input (changes its internal state).
i am a newbie to rail and try to build my first site but face an issue with a link_to in an index page. The link redirect to /recipes.1 instead of /recipes/1.
The show page work when i try /recipes/1.
Index.html.erb
<% provide(:title, "Recipe") %>
<% #recipes.each do |recipe| %>
<%= link_to recipe.label, recipe%>
<%end%>
route.db
get 'recipe' => 'recipes#show'
get 'recipe' => 'recipes#new'
post 'recipe' => 'recipes#create'
resources :users
resources :recipes
recipes_controller.rb
def index
#recipes = Recipe.all
end
def show
#recipe = Recipe.find(params[:id])
end
Remove the following routes from routes.rb:
get 'recipe' => 'recipes#show'
get 'recipe' => 'recipes#new'
post 'recipe' => 'recipes#create'
The above routes are not required since resources :recipes generate all these routes for you.
Hope it helps!
Try this code
<% #recipes.each do |recipe| %>
<%= link_to recipe.label, recipe_url(recipe) %>
<%end%>
Use
<%=link_to recipe.label, recipe_path(recipe)%>
Instead of
<%= link_to recipe.label, recipe%>
you have defined show path twice.
1. in manual defined path
get 'recipe' => 'recipes#show'
2. Through
resources :recipes
If you do rake routes, then you will first option create routes for get method with /recipe url and appends parameter to it which result in /recipes.1 path.
Also rails read routes file in top to bottom approach. As uses first routes for show method.
I have a rails 3 app, and when I click the link to my terms page, it routes to a completely different controller, than what the routes should use. Stranger still, the route works when I'm not logged in, and I'm using devise.
I get this error when clicking the link when I'm logged in.
No route matches {:action=>"edit", :controller=>"users", :id=>nil}
<%= link_to "Terms", terms_path %>
Routes (in the order they appear in routes.rb):
devise_for :users, :controllers => {:registrations => "registrations"}
resources :users do
member do
get :following, :followers
post :accept
end
end
match '/terms', to: 'static_pages#user_agreement'
Static Pages Controller
def user_agreement
end
Rake Routes
terms /terms(.:format) static_pages#user_agreement
This also happens for every other action that I've routed this way to the staticpages controller, but not for any other actions that route to different controller.
Update: Terms Page
Header:
<%= link_to "Follow", users_path %>
<%= link_to current_user.name, current_user %>
<%= link_to "Sign out", destroy_user_session_path, :method => :delete %>
Footer:
<%= link_to "Welcome", welcome_path %>
<%= link_to "Settings", edit_user_path(#user) %>
<%= link_to "Terms", terms_path %>
All the content is pure html.
Thanks in advance
You have a link to edit_user_path with no #user as hinted in the comments.
You should almost certainly be using current_user anyway.
Noob here.
Trying to figure out how to display a method in my controller into my index page. Here is what I have thus far.
Controller -
class SammichesController < ApplicationController
def index
#sammiches = Sammich.all
end
def create
#sammich = Sammich.find_by_name(params[:sammich][:name])
end
def random
#sammichy = Sammich.rand(params[:sammich][:name])
end
end
Routes-
Sammiches::Application.routes.draw do
resources :sammiches do
get "random"
end
root :to => 'sammiches#index'
Index-
<h1>All my Sammiches</h1>
<%= form_for Sammich.new do |f| %>
<%= f.label :sammich %>
<%= f.text_field :name %>
<%= f.submit 'Find Sammich', :id => 'sammich_submit' %>
<% end %>
<%= link_to "Random sandwich", sammich_random_path %>
routes-
sammich_random GET /sammiches/:sammich_id/random(.:format) sammiches#random
sammiches GET /sammiches(.:format) sammiches#index
POST /sammiches(.:format) sammiches#create
new_sammich GET /sammiches/new(.:format) sammiches#new
edit_sammich GET /sammiches/:id/edit(.:format) sammiches#edit
sammich GET /sammiches/:id(.:format) sammiches#show
PUT /sammiches/:id(.:format) sammiches#update
DELETE /sammiches/:id(.:format) sammiches#destroy
root / sammiches#index
Error-
localhost:3000 - Routing Error
No route matches {:action=>"random", :controller=>"sammiches"}
Try running rake routes for more information on available routes.
Any assistance would be much appreciated.
Thanks!
If you look at your route it has :sammic_id in there as well:
sammich_random GET /sammiches/:sammich_id/random(.:format) sammiches#random
Which means you need to pass an id to your URL helper sammich_random_path which you haven't.
Update your routes to this:
resources :sammiches do
collection do
get "random"
end
end
After adding that your route would be just /sammiches/random