Rails routing causing error? - ruby-on-rails

I'm super new to Ruby/Rails and need help with an assignment I'm working on. I'm supposed to add native advertising to Bloccit (project i'm working on for class) in the form of sponsored links. Any help would be very appreciated :)
What needs to be done:
1) Create a new model called Advertisement. It should have the following attributes: title:string, copy:text, price:integer.
2) Generate a controller for the new advertisement model with index and show actions. Should the controller class and file names have a singular (advertisement) or plural (advertisements) prefix? Be consistent with the naming pattern used for the posts controller class and file generated earlier.
3) Update routes.rb to use resourceful routing for Advertisement.
4) Complete the index and show actions in AdvertisementsController.
5) Update the Advertisement index and show views.
This is what I've got:
First thing, create model like so
rails g model Advertisements title:string, copy:text, price:integer
Then, create controller like so
rails g controller Advertisements index show
Resourceful routing:
Rails.application.routes.draw do
resources :advertisement
resources :posts
get 'about' => 'welcome#about'
root to: 'welcome#index'
end
Index and show actions:
class AdvertisementController < ApplicationController
def index
#advertisements = Advertisement.all
end
def show
#advertisements = Advertisement.find(params[:id])
end
end
Index view:
<h1>Advertisements</h1>
<% #advertisements.each do |advertisement| %>
<% end %>
Show view:
<h1><%= #advertisements.title %></h1>
<p><%= #advertisements.copy %></p>
<p><%= #advertisements.price %></p>
When I go to localhost:3000/advertisement I see a blank page page with "Advertisements" at the top. When I go to to localhost:3000/advertisement/index I see an error message:
Couldn't find Advertisement with 'id'=index
def show
#advertisements = Advertisement.find(params[:id]) #second line highlighted in red
end
end
Why I can't I view an individual advertisement or see an index of all advertisements like I'm supposed to?

You are seeing an index of all the Advertisements when you see the page with just Advertisements at the top, it isn't repeating & printing any because none exist.
Not being able to see just one is because the route defaults to
localhost:3000/advertisements/:id
So it's trying to lookup an Advertisement with the :id of "index", which most likely doesn't exist.
Try to create an advertisement

You don't appear to be outputting anything for each advertisement in your index view and are just looping through the advertisements:
<h1>Advertisements</h1>
<% #advertisements.each do |advertisement| %>
<% end %>
Inside the loop, you will need to add mark up and ERB that you wish to see for each advertisement.
You can seed your database or create advertisements through the Rails console to test. As Alfred implies, you should be able to see id=1 at:
localhost:3000/advertisements/1
Minor point, for show action and view, #advertisement (singular) makes more sense semantically (you are showing a single advertisement).

You will find that rails is your friend when creating the Routes, Controllers and views you are looking for. Here is the simpliest way to solve you problem:
In terminal cd into your rails program and then:
rails g scaffold advertisement title:string, copy:text, price:integer
press enter and then rake db:migrate.
When you go to localhost:3000/advertisements you on on the index for advertisements localhost:3000/advertisements/[some :id] is the show page for a particular advertisement
additionally in your index view you have to use the block variable you are creating which in this case is advertisement to call the attributes you want on the page:
<%#advertisements.each do |advertisement|%>
(Which is all the advertisement being looped)
<%= advertisement.title %>
<%= advertisement.copy %>
<%= advertisement.price %>
<% end%>
And you will see a display of individual advertisements with their respective elements

You forgot to Seed some Data.
In you file: db/seeds.rb add:
# Create Advertisements
10.times do
Advertisement.create!(
title: Faker::Internet.domain_name,
copy: Faker::Company.catch_phrase,
price: 0
)
end
Then enter this to your terminal: rake db:seed
In case you didn't do it, rake db:migrate
It should be working now.

Related

Rails does not navigate to controller method

I am trying to add a new controller method. I also created a corresponding view for the same. All I am trying to do is create a variable called #x and printing it in the view. I am doing this just to verify if my application is going into the method. However, I do not see the value getting printed on the view. Please help.
This is my controller named submitted_content_controller.rb
class SubmittedContentController < ApplicationController
def begin_planning
#x = 1
end
end
This is my view called begin_planning.html.erb
<%= form_tag url_for(:action => :revision_planning), method: "post" %>
<%= text_field 'questionnaire', 'name', class: "form-control width-250" %>
<p><%= #x %></p>
<button>Create</button>
This is the routes I added:
get :begin_planning
When I am in the begin_planning html page, I see the text field and create button but I don't see the value of #x getting printed. It will be a huge help. Thank you.
This is my routes output:
begin_planning_submitted_content_index GET /submitted_content/begin_planning(.:format) submitted_content_controller#begin_planning
there are other routes to which I didn't add, because this controller has many other methods which I did not add since it's a huge file.
You may be rendering the view without going through the action.
If Rails finds a view file with a name that matches a route, but doesn't find a corresponding action for that route, it will still
render the view.
https://guides.rubyonrails.org/layouts_and_rendering.html#rendering-by-default-convention-over-configuration-in-action
So, you successfully render the form in the view, but Rails
doesn't know what #x means.
In your routes file, try adding the following outside of any namespaces:
get '/begin_planning', to: 'submitted_content#begin_planning'
Your rake routes should include the following:
begin_planning GET /begin_planning(.:format) submitted_content#begin_planning
And navigate to http://localhost:3000/begin_planning
Or,
if you'd like to namespace, you can add the following to your routes file instead:
namespace :submitted_content do
get :begin_planning
end
And your 'rake routes' should include the following:
submitted_content_begin_planning GET
/submitted_content/begin_planning(.:format)
submitted_content#begin_planning
And navigate to http://localhost:3000/submitted_content/begin_planning

Ruby On Rails adding new page after scaffolding

I made a scaffold named b_page and I created a migration for bio I added a biopage.html.erb
In controller:
def biopage
#b_pages = BPage.all
end
in routes.rb
resources :b_pages do
collection do
get 'biopage'
end
end
in bio.html.erb:
<div class="jumbotron">
<h1>Bio of :</h1>
<h2><b><%= #b_page.Bpage_name %></b></h2>
<h3><%= #b_page.user.email %></h3>
</div>
<%= #b_page.bio %>
but i still get the error:
ActiveRecord::RecordNotFound in BPagesController#show
Couldn't find BPage with 'id'=biopage
highlighting:
#b_page = BPage.find(params[:id])
First of all, this seems a bit odd to me:
resources :b_pages do
collection do
get 'biopage'
end
end
as it will result in a route like: /b_pages/biopage. You might want to just do something like:
resources :b_pages, except: :show
get '/biopage/:id', to: 'b_pages#show'
This way, your biopage route will go to the show controller method and you will still have the other b_pages routes to work with.
You are seeing the ActiveRecord::RecordNotFound error message because you have no BPage object to show, so the show method is complaining. Notice how the route I wrote above uses :id - this is because the show action normally takes an id of some record to display on the front end. If you want to use biopage and link it to the show method, you should be returning an object to actually show. Otherwise you should probably create a completely different controller method for biopage that does not interfere with the b_pages resources. Something like this in the routes:
resources :b_pages
get '/biopage/:id', to: 'b_pages#your_method'
and in the controller you'd have
class BPages < ApplicationController
# index, show, destroy, etc. here
def your_method
# Get whatever object you want returned here
end
end

using rails how do i only show the id submitted via a text box from a table

I've got a table full of information at the moment, Ideally i need the information from a database table to be viewed via a link.
I only have the controller and some standard html (the html is just a h1 tag at the moment)
The HTML will be standard throughout like a template.
The way i'm seeing what i want in my head is the users will get a link which would be events_prev/{{id from DB here}} and depending on the ID the information on the page will be populated from the corrisponsing DB Row
Heres my controller
class Events::EventsPrevController < ApplicationController
def index
#events = Event.where(id: id)
end
def show
render :nothing => true
end
end
Sorry if its super confusing.
Welcome to rails.
Ok, there's a couple of things that will get you in the right directions. Firstly, you REALLY need to do a little reading to understand how the controller and the routes and the views are linked together in rails, that'll help you tons.
But moving on to your specific issues:
Parameters:
All data passed via a url (get, post, put, doesn't matter the method) is available in the controller in an array object called params - So that means when want to access the data the user submitted, you'll use something like
#event = Event.where(id: params[:id])
Routes:
It looks like you're trying to use the index page. In rails index is a RESTful route which generally points to a collection of model objects. The show route will point to an individual object so you should instead make your link point to the show path instead of the index path.
You can view the routes available on a model on a command line using:
bundle exec rake routes
An example of what your routes might look like:
prev_events GET /prev_events(.:format) prev_events#index
POST /prev_events(.:format) prev_events#create
new_prev_event GET /prev_events/new(.:format) prev_events#new
edit_prev_event GET /prev_events/:id/edit(.:format) prev_events#edit
prev_event GET /prev_events/:id(.:format) prev_events#show
PATCH /prev_events/:id(.:format) prev_events#update
PUT /prev_events/:id(.:format) prev_events#update
DELETE /prev_events/:id(.:format) prev_events#destroy
Link
Based on the routing table, you now should see that the link you need your users to click on might look like this (given that event is your object:
<%= link_to event.title, event_path(event.id) %>
or shortcutted
<%= link_to event.title, event %>
View
For the view this is entirely dependent on the data in the Event model. Since the data is stored in #event you'll simple use the attributes on the event model to render the html however use like, e.g.
<h3><%= #event.title %></h3>
<span><%= #event.start_time %></span>
You should read up on Rails controllers: by default the action index is used to show all of the records and what you're talking about should belong to the show action. The default routes take care of the id passing to your show action.
Index action is mean to show list of items in view and Show action is used to show a single item.
what you are doing in index is actually mean to be in show action.
Reason:
#events = Event.where(id: id)
this line will give u a single record in every case it means it should be in Show action.
your code should look like:
def show
#event = Event.find(params[:id])
[your logic: what you want to do with that #event]
end

Ruby on Rails layouts and rendering

I'm new to RoR and I'm a little bit confused with Rails MWC. I feel like I misunderstand something.
For example, I want to have home page where I could render top 5 articles and top 5 products. Products and articles have no relations at all, it is totally separate data.
So what I try to do is, i crate 2 sacffolds products and articles, and 1 controller for home page. I root to homepage controller. Then in homepage template i try to render products and article template. I get an error that methods which are used in products and articles controllers are undefined.
I don't understand where is problem. Is this kind of template rendering one template inside another is not Rails convention. Or I have bugs in my code.
I don't see your code but in this case I'm quite sure you have bugs in it.
app/controllers/home_controller.rb
class HomeController < ApplicationController
def index
#products = Product.top5 # Your logic to fetch top 5
#articles = Article.top5
end
end
app/views/home/index.html.erb
<% #products.each do |product| %>
<%= product.name %>
<% end %>
<% #articles.each do |article| %>
<%= article.name %>
<% end %>
This is perfectly fine, I've done that multiple times. Consider that in Rails you don't have any relation between controller and models, there are convention but Rails controller is not bound at all to any model
First, you need to instantiate your variables #products and #articles (this is an example) on your controller method. Then you can render the view.
Pay attention to add an # before. Only variables with an # will be available on your rendering view.
By default, when you call a GET for /products you'll arrive on the index method. At the end of this method, if not any view is specified, Rails will render views/products/index. In this view, you'll access all variables instantiate with an # and do whatever you want with.
First, yes, a template rendering another controller's template (not a partial) is not within Rails conventions.
A scaffold is a "single-resource" controller: it takes your model definition and generates a basic controller for editing and displaying that particular model (i. e., Product).
What you really need to do is use the two models you've generated in the home page controller, kinda like this:
class HomePageController < ApplicationController
def index
#articles = Article.top_5
#products = Product.top_5
# Render the #articles and #products in the view.
end
end

Rails 4: gem 'impressionist' to count view on pins/show.html.erb

I have rails have where users can create pins. And I would like to render a number of views on the pin show page. Lets say that pins are profiles, I want to render the number of times a profile has been viewed.
So I installed the impressionist gem
And here is how I implemented it:
App/models/pin.rb
is_impressionable
App/controllers/pin_controller.rb
impressionist actions: [:show]
App/views/pins/show.html.erb
<%= #pin.impressionist_count %>
Unfortunately it doesn't render the number of views, it shows 0 instead. It is worth noticing that I don't care to get unique IP adress views, I want the number of views being updated every time a user click on the show action of a pin.
Any ideas to put me on track ?
UPDATE 1:
As I am using friendly ID on my pins model I removed the following line from my pin_controller:
impressionist actions: [:show]
And I updated the show view of the controller:
def show
#disable_nav = true
#pin.upvoted_users
impressionist(#pin)
#pin = Pin.friendly.find(params[:id])
#commentable = #pin
#comments = #commentable.comments
#comment = Comment.new
end
But now here is the error I have:
undefined method `impressions_count' for #
SOLUTION:
My bad... I forget to run the impressions_count to my model:
Rails generate migration add_impressions_count_to_pins impressions_count:integer
Rake db:migrate
Thanks :-)
In View
<%= #pin.impressionist_count %>
change above one to the below one
<%= #pin.impression_count %>
or you can do
<%= #pin.impressionist_count(:filter=>:ip_address) %>
As per README

Resources