Rails controller view bug - ruby-on-rails

Alright total noob, tried to find out what was happening but I haven't seen this come up with anyone else as far as I could find.
I'm going through a very basic blog tutorial with rails for the second time. made the home controller and the index view for it. all good. Next i made the 'posts' controller with basic classes and then views for index, edit, new, and show.
class PostsController < ApplicationController
def index
end
def new
end
def create
end
def edit
end
def update
end
def show
end
def destroy
end
end
The html for the views in their respective files
<h1>New Posts</h1>
<h1>Edit Posts</h1>
<h1>Show Posts</h1>
PROBLEM: In the browser when I go to localhost:3000/posts/edit it displays "Show Posts" instead of "Edit Posts". /show also displays "Show Posts". /new works fine and displays "New Posts".
I checked and it looks like localhost:3000/posts/literallyanything will display "Show posts".
I know this is potato level but I thought it was really odd and can't figure out why that would happen

Assuming you have a resource route for posts defined in your routing file like this:
resources :posts
you need to hit
localhost:3000/posts/<post id>/edit
More docs on routing here:
http://guides.rubyonrails.org/routing.html
You can always run rake:routes from your terminal to find out what route you need to hit for any given controller action.

Related

Differentiating between links to have one page change based on the selected link

I am new to Ruby on rails and am making a web application with a show page that should just simply display the data in my database based on the link clicked. I want to make it where I can just have one page that changes based on which recipe I select but I cant figure out how to differentiate between the links.
This is a basic restful route to go to the show action of a controller.
# config/routes.rb
Rails.application.routes.draw do
get '/recipes/:recipe_id', to: 'recipes_controller#show'
end
So your links could be something like: http://example.com/recipes/2
Which should load a page showing the information of the recipe with id 2
Now this is supposing you have a controller recipes_controller.rb with the show action to give you the info on that recipe
# app/controllers/recipes_controller.rb
class RecipesController < ApplicationController
...
def show
#recipe = Recipe.find(params[:recipe_id])
render 'show'
end
end
Now in the views/recipes/show.html.erb template or whatever view you render in the show action, you will have access to a <%= #recipe %> containing the values of your object.

Creating a dynamic root route in rails

I have a rails app where I am wanting to make the landing page dynamic so that every time the user goes to it it changes.
I have cafe's in my app, and each cafe has its own show page. I want each show page to be dynamic. The url's are based off of the cafe's id, so I figured I'd have to use those IDs as the focal point for creating the dynamic work i'm looking for.
In my cafe's controller I have
class CafesController < ApplicationController
def root
array = Cafe.pluck(:id)
array.sample
end
end
in my routes file I have
root 'cafes#root'
The error I'm getting is
`CafesController#root is missing a template for this request format and variant. `
Would anyone know what I am missing with this one? Much appreciated.
I image you could do something like:
class CafeController < ApplicationController
def root
redirect_to Cafe.all.sample
end
end
By the way, this approach has the benefits of letting you keep and use all your normal routes in the conventional manner.
Also, you might consider calling this action something a little more descriptive. Perhaps something like random_cafe. IMO, root 'cafes#random_cafe' is a bit more understandable.
missing a template error because you have to specify a template to render, I'm imagining that array.sample will return something like /cafes/firstsampe.html.erb where firstsampe.html.erb persists inside cafes views folder so you can use it like this redirect_to :template => array.sample.
Hope it helps.
I don't have any idea about what your data looks like, but there are two approaches you can take here:
Show a random cafe when the user hits your home page (root)
Redirect a user to a cafe's page randomly when they hit the home page
In scenario 1:
Controller:
class CafesController < ApplicationController
def index
#cafe = Cafe.order("RANDOM()").first
end
end
Routing:
root 'cafes#index'
Views:
app/views/cafes/index.html.erb
<p><%= #cafe.name %></p>
In scenario 2:
Controller:
class CafesController < ApplicationController
def index
redirect_to cafe_path(Cafe.order("RANDOM()").first)
end
def show
#cafe = Cafe.find(params[:id])
end
end
Routing:
root 'cafes#index'
resources :cafes, only: [:show]
Views:
app/views/cafes/show.html.erb
<p><%= #cafe.name %></p>

Rails 4 - Couldn't find User without an ID

I'm new to rails, so any explanation & advise would much appreciated.
i have a webpage in which i would like any user to view that page not just the current_user, but i am unsure how to correctly define the instance variable #user in my controller
in my static_pages_controller.rb i have the below action recruiterpg
static_pages_controller.rb
def recruiterpg
#user = User.find(params[:user_id])
#adverts = #user.adverts
#applications = #user.forms
end
in my controller, i have defined user as #user = User.find(params[:user_id]) but this breaks my code in the views; views/static_pages/recruiterpg.html.erb
when i define user as #user = current_user my code in the views works perfectly fine
what am trying to do is: for my views, the recruiterpg.html.erb, i would like
any user to be able to view the page not only the current_user to
view the page. Could one kindly advise me and explain to me how to
define #user correctly in my status_pages_controller.rb. i also
tried #user = User.find(params[:id]) but my code still breaks in the
views - i get the error message
Couldn't find User without an ID
You need to make sure you are passing a user_id to the recruiterpg action. For example, try this url in your browser (set user_id to a known id in the users table):
http://localhost:3000/dashboard?user_id=1
A suggested modification to your action:
def recruiterpg
#user = User.find params.require(:user_id)
#adverts = #user.adverts
#applications = #user.forms
end
If params[:user_id] isn't defined, you want to find a way to make visible what is being defined.
If you throw the following statements into your controller...
def recruiterpg
...
puts params
...
end
...you should see something like the following get spit out in your console when you load the page...
{"controller"=>"static_pages", "action"=>"recruiterpg", "id"=>"49"}
Take a look at the Rails guide for parameters. They can get defined in one of three ways.
One: As a query string similar to Sean's answer above.
Two: Routing parameters. See section 4.3 in the Rails guide. In your case, that would mean you should have something like the following in routes.rb:
get '/dashboard/:user_id' => 'staticpages#recruiterpg'
Note that there's nothing magic about :user_id in that string.
Three: From a form which it doesn't seem like applies here, since a user isn't submitting data.
Since you're new, here is some information for you:
User Story
Firstly, the best way to resolve errors is to identify your user story.
A "user story" is a software principle in which you put the "user's perspective" first -- explaining how the software should work in conditions defined from how the user engages with it.
One of the main issues you have with your question is your user story is very weak; it's hard to decifer what you're trying to achieve.
Next time you ask a question, you should try your hardest to describe how the user should see your app, before providing code snippets :)
Controller
Your main issue is an antipattern.
An antipattern is basically a "hack" which will likely break another part of your app in future. Kind of like duct tape for software):
#app/controllers/static_pages_controller.rb
class StaticPagesController < ApplicationController
def recruiterpg
#user = User.find(params[:user_id])
#adverts = #user.adverts
#applications = #user.forms
end
end
So you're showing a static page but yet you want to populate it with data?
Hmm...
What you should be doing is something like the following:
#config/routes.rb
resources :users do
resources :recruiters, only: :index #-> url.com/users/:user_id/recruiters
end
#app/controllers/recruiters_controller.rb
class RecruitersController < ApplicationController
def index
#user = User.find params[:user_id]
#adverts = #user.adverts
#applications = #user.forms
end
end
This will allow you to populate the following view:
#app/views/recruiters/index.html.erb
<%= #adverts %>
--
It's important to note the structure of the controller / routes here.
The issue you have is that you're calling a "static page" and expecting to have params available to find a User. This can only happen if you have params available...
Params
Rails is not magic, and as such if you want to look up a user, you have to provide the parameters to do so.
This is why you're able to look up current_user -- the params are already set for this user.
As such, you'll need to use something called nested routes in order to attain a user ID other than that of current_user:
#config/routes.rb
resources :users do
resources :recruiters #-> url.com/users/:user_id/recruiters
end

Accessing specific pages in a controller/view on Rails App

I am trying to set individual Meta Descriptions and Titles to individual pages in a Ruby on Rails App. It was a previous developers App, that I have been given the task to edit. Also, I am new to Rails and Ruby.
The app has a controllers/pages_controller.rb where I was am able to set unique variables for #descriptionX and #title on some pages (mission and disclaimer), but not for others, such as pet_planning.
class PagesController < ApplicationController
def index
#title = params[:page].humanize
render params[:page]
end
def pet_planning
#descriptionX = 'pet planning'
#title = 'pet planning title'
render :pet_planning
end
def mission
#title = 'Our Mission Statement'
#descriptionX = 'Mission Description'
render :mission
end
def disclaimer
#title = 'Our Disclaimer'
render :disclaimer
end
end
I think that the render params[:page] is where I am getting lost. I'm not 100% sure of what this is doing, or how to use it.
I don't understand why I would be able to control the #title and #description of mission but not pet_planning when their views are both in the same /views/pages/ directory. And I can't seem to find any distinction between the two anywhere else in the app.
Also, tried to add = #title = 'Pet Planning' in the /views/pages/pet_planning.html.haml file. It does change the title, however it also displays at the top of the page content unexpectedly.
Any help would be appreciate. Thanks.
I'd recommend having a read of the ActionController guide, which explains how Rails turns a request from the user into a page to render.
Basically, when you send a request, for example
GET http://www.example.com/pages/?page=pet_planning
then Rails works out what to do with it using the router (the routing guide explains this in more detail). I would imagine that your app is set up so that the /pages route matches to the PagesController#index action. You can have a look in your config/routes.rb file and/or type rake routes at the terminal to see how your routes are set up.
The bit after the question mark in the request is the "query string", and Rails turns this into a params hash which, for my example above, would look like {:page => "pet_planning"}. Your index action looks at that to get the name of the page to render - that's what render params[:page] is doing.
I guess that the reason you can modify the variables for some of your pages and not others is that some of them have their own routes - /pages/mission uses the PagesController#mission action, for example - while certain pages are accessed via the index action using the page param - /pages/?page=pet_planning or possibly /pages/index.html?page=pet_planning.
Update: Your existing route
match 'practice_areas/:page' => 'pages#index', :as => :pages
could be broken up into
match 'practice_areas/pet_planning' => 'pages#pet_planning' :as => :pet_planning
# etc ...
which would correspond to a controller that looks like this
class PagesController < ApplicationController
def pet_planning
#title = "Pet planning!"
#description = "Whatever..."
end
end
Your suggestion is close, but because the route format is "controller_name#action_name", you would require multiple controllers that looked like this
class PetPlanningController < ApplicationController
def index
#title = "Pet planning!"
#description = "..."
end
end
and you would have to move your views from app/views/pages/pet_planning.html.haml to app/views/pet_planning/index.html.haml. So it's probably not quite what you want.
Note that there might be a better way to tackle the problem than splitting everything up into separate actions, if all you are doing differently in each one is customising the title and description. For example, you could use a hash that maps your page name to its corresponding information:
class PagesController < ApplicationController
PAGE_INFO = {
"pet_planning" => ["Pet planning!", "Whatever..."],
"other_page" => ["Title", "Description"],
# ...
}
def index
page_name = params[:page]
#title, #description = PAGE_INFO[page_name]
render page_name
end
end
The render calls in pet_planning, mission, and disclaimer do the same as default behavior, so those calls can be removed. They are telling rails to use the pages with the given file names. For the index method, this is rendering a page based on a parameter.
The title and description are likely set in the layout. Look in /views/layouts/application.html.haml or /views/layouts/pages.html.haml.

two controllers in one view in Rails

I have two controllers, one for the users and one for the microposts.
What I'm trying to do, is to put on the same view, the users informations and the microposts form.
The issue is the url of this page is www.mywebsite.com/users/18 so I have only access to the users controller.
I tried to do:
render :file => '/posts/new' but it doesn't work.
The only solution I found is to put everything on one controller but it will be a mess.
I really want a separate controllers for each.
So I don't know how to do this. Any idea?
What I'm trying to do, is to put on the same view, the users informations and the microposts form
I think you are trying to create a new micropost inside the user show view. If so, you can include the below:
<%= form_tag(controller: :microposts, action: :create) do %>
...
<% end %>
When you submit the form, it will call the action create in the microposts controller.
Are you working through Hartl's tutorial? Well, anyway, all you have to do is initialize all instance variables you need in the view in the controller action:
users/18 is probably pointing to users#show, thus you need to add something like
class UsersController < ApplicationController
...
def show
#micropost = current_user.microposts.build
...
end
...
end
in controllers/users_controller.rb (or something that fits your model) to initialize a new micropost for the micro post form, or just
#micropost = Micropost.new
if you don't have/need an association to the user. (Michael Hartl is doing it on the home page, though.)

Resources