How to display a resource from a different controller? - ruby-on-rails

I'm creating a mostly static home page for a website, except for one little container that needs to pull web links from a model database. The home page view is sitting in home_controller which I created earlier in development. I've now created the link resource and links_controller.
I don't know much about rails and what I've been doing up to now is displaying resources in the index view for their designated controller. However, i need to display this resource in the index view for the home_controller.
Can someone guide me in the right direction towards doing this?

Do a query to fetch the required link objects in the index action of home_controller and display it in the view, as you want:
# HomeController
def index
# other code
# #links = Link.all # or any other query you may want to do
end
# in the view index.html.erb
<% #links.each do |link| %>
<%= link.url %> <br/>
<% end %>
Customize it as per your needs.

Related

Trying to get two actions to have different views, but the same URL

I have an app with shepherds (i.e. the users) and each shepherd has a set of animals. I am trying to make it so that if the logged in shepherd tries to view one of their animals it takes them to a view controlled by the edit action. Alternatively, if the shepherd tries to view another shepherd's animals it gives them a view controlled by the show action. I'd prefer to not have URLs with */edit - I want them to look the same for edit and show. In my routes.rb file I have this...
get '/shepherds/:username/:eartag', to: 'animals#show', as: :shepherd_animal_show
get '/shepherds/:username/:eartag', to: 'animals#edit', as: :shepherd_animal_edit
In the shepherd's show view I create a link to their animals like this...
<% if animal.shepherd == current_shepherd %>
<a href="<%= shepherd_animal_edit_path(username: animal.shepherd.username, eartag: animal.eartag) %>"
<% else %>
<a href="<%= shepherd_animal_show_path(username: animal.shepherd.username, eartag: animal.eartag) %>"
<% end %>
I can see that when I'm logged in and try to access my animals, it goes into the block with the shepherd_animal_edit_path, but it directs me to the show view rather than the edit view. Here's part of the output of the routes...
shepherd_animal_show GET /shepherds/:username/:eartag(.:format) animals#show
shepherd_animal_edit GET /shepherds/:username/:eartag(.:format) animals#edit
I'm a bit of a beginner at Rails and would really appreciate any help people can offer.
I think you should be using the show action for both, and just rendering a different template depending on the animal ownership. I.e.:
def show
...
render 'edit' if animal.shepherd == current_shepherd
# the show template will be rendered automatically if `render` wasn't explicitly called
end
Then in your view, you can unconditionally link to the show action, and the controller will take care of deciding which view template to render.
Also, FWIW, I would probably define the routes as follows:
resources :shepherds, shallow: true do
resources :animals
end
And then use the link_to helper in the view instead of hard-coding HTML tags:
<%= link_to animal_path(animal) %>
But that would then allow you to do other things like:
link_to shepherd_animals_path(#shepherd) # link to the `index` action of `AnimalsController`, with `params[:shepherd_id]` set to `#shepherd.id`.
That would then allow you to render (or not render) other controls for the shepherd to manage his/her own flock if current_shepherd.id == params[:shepherd_id] (or current_shepherd == Shepherd.find(params[:shepherd_id])).

Display navbar on all pages except home page

I want to show two different navbars. One will be displayed, on all pages except home page, when you're logged in. While the other navbar will be displayed just on my landing page.
I am thinking that I will probably need to write an if statement.
If (current user is not logged in) or maybe (current user is viewing home page) do
<nav>Second navbar</nav>
else
<nav>First navbar</nav>
end
I am very new to rails, so I could be wrong. (And yes, I know that's not how to correctly write an if statement in Ruby)
Home page is located at:
home/index.html.erb
I normally do following setup:
create partial shared/_nav_menu.html.erb
inside partial I put logic like:
<% if current_user %>
// nav bar for logged in user
<% else %>
// nav bar for non logged in users
<% end %>
Then inside application.html.erb file I render the partial like this:
<%= render :partial => 'shared/_nav_menu' if show_menu? %>
Inside my application_controller I put logic like this:
def show_menu?
true
end
helper method: show_menu?
If I don't want to show the menu for static_pages then inside static_pages_controller I overwrite show_menu? method to return false.
class StaticPagesController < ApplicationController
def show_menu?
false
end
helper_method: show_menu?
end
You don't have to use exactly this setup but I like this setup because my nav menu logic is kept seperate in partial. All logic required to nav menu lives in this file.
This approach don't bloat my application.html.erb file with lots of if..else.
In the case of two menus, but leaving yourself open to more, I would use a similar-but-slightly-different approach than Reboot's answer.
In the layout:
<%= render :partial => #nav_bar_partial %>
Then in my application controller, define the default nav:
def standard_nav
#nav_bar_partial = "path/to/standard/nav/partial"
end
From there, you can override that nav partial any time you need to (with any partial you want) from your controller
#nav_bar_partial = "path/to/new/nav/partial" if condition_that_requires_a_different_nav
That way, you have a little more flexibility. If for some reason you want to add a third nav bar for some other condition, you can just override the partial elsewhere without changing any of the above code.
You can prepare two layouts, one for the landing page and another for rest of the pages. Take a look at the official documentation: http://guides.rubyonrails.org/layouts_and_rendering.html.

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

how to detect in which page we are Rails [duplicate]

This question already has answers here:
Best way to highlight current page in Rails 3? -- apply a css class to links conditionally
(8 answers)
Closed 9 years ago.
I am new to Rails.
In my appliction.html.erb, i am using a render partial: to use a html_css shared file.
This shared file contains buttons that can be used by different pages.
For example, for the pages /posts and /answers a search field with a suubmit button taken from the shared filed is displayed.
I would like to make this button work for both pages. When we are in the /posts page, we search in the posts and when we are in the /answers page, we search in the answers.
So, i need to call the right controller each time. For that, i need a helper or a trick that enables me to know in which page i am (which controller#index did i call?).
Does rails contain a method or a helper enabling this?
thanks :)
Use the helper functions: controller_name and action_name.
If you have a controller:
class UsersController < ApplicationController
def my_action
# stuff
end
end
In the view, you can do:
Controller name: <%= controller_name %> <br/> # => users
Action name: <%= action_name %> <br/> # => my_action
See: http://guides.rubyonrails.org/action_controller_overview.html#routing-parameters
Action and controller are in the params already. I imagine you would rather do stuff with that information rather than just display it with controller_name/action_name
for instance to display a footer only in the about page assuming the controller is called about_controller you could
<% if params[:controller] == about %>
<%= render partial: 'footer' %>
<% end %>
params[:action] will contain the action.

How to call a ruby on rails controller when view is loaded?

I am pretty new to Rails, basically what I want to do is pretty simple, when the view is loaded I want it to call a controller that executes a ruby script and render the image generated by this script on my view, is this possible? Or should I call the script before the view is loaded and just retrieve the generated image?
First of all what i would suggest you to go and learn here a link for your help
ruby on rails tutorial
Answer to your problem
In rails controllers are loaded first, each view is associated to some controller action, forexample if you have users controller(app/controllers/users_controller.rb) and in show you want to display the users image as a profile picture, what you can do is
def show
#user = User.find(params[:id])
end
and in its corresponding view(app/views/show.html.erb)
<img src = <%= #user.image_path %> />
I would retrieve the image on load of the page, hide it with css and load it anytime you want with javascript. I don't see a big reason for not calling it on the load of the page.
In RoR a controller action is rendering the view, so you can set it at the initial load itself.
For example, you have the Users controller and you need to show all users images in the index view.
controllers/users_controller.rb
def index
#users = User.all
end
views/users/index.hrml.erb
<% #users.each do |user| %>
<img src=<%= user.image_path %>> </img>
<% end %>

Resources