Displaying data from multiple models on home page? - ruby-on-rails

I'd like to display a summary of data from various models on my home page. There's a HomeController and a home/home.html.erb but no model. I was hoping it would be as simple as placing something like this for each model in the HomeController and then view, but nope, that doesn't work!
Controller:
def load_tracks
#tracks = Track.all
end
View:
<% #tracks.each do |track| %>
<%= track.name %> - <%= track.isrc %>
<% end %>
Any pointers would be really appreciated!

Your controller will have to look like this:
class HomeController < ApplicationController
def home
#tracks = Track.all # or this could come from a method
end
end
And your view can be the same now. When rails sees a request it looks for the action with that name. So when you tried to go to /homes/home it went in to the Homes controller to find a home action and couldn't find it, so that's probably why it didn't work.
EDIT You shouldn't really have a "HomesController" anyways. A "PagesController" might make more sense. Check out Michael Hartl's RoR tutorial book on the subject.

Let's say you have two models, Track and Playlist and you want to display information about them on the Home controller's index page. In app/view/controllers/home_controller.rb
def index
#tracks = Track.all
#playlists = Playlist.all
end
then in the view, app/view/home/index.html.erb
<h1>Tracks and Playlists R Us</h1>
<p><%= "We have #{#tracks.count} tracks and #{#playlist.count} playlists." %></p>

You migh also want to take a look at Presenter. It's a good and clean way to grab data from different models.
Here: http://railscasts.com/episodes?utf8=%E2%9C%93&search=presenter
and http://railscasts.com/episodes?utf8=%E2%9C%93&search=draper

Related

Render results on #show without storing data in ActiveStorage

I'm learning RoR by building my first app (yay!). I gotta a question thought as rails guides do not cover this topic:
How to render unique results on #show to a user without storing any data in a model?
Steps I want to take:
Create a basic index view with a form_tag that will allow user to submit a link (string) and click submit button
Write Service Objects that will allow me to parse that link and create a response I want user to see
I want to write a #show method in a separate controller that will allow me to display all the data. (I also want to parse my params[:link] in that method using Service Objects.
I want to finally display this data in a table in #show view (probably I need to create a unique #show/[:id] for each user?
Here's what my app looks like at the moment (more or less):
Static Controller (just to render index.html.erb with a form)
class StaticController < ApplicationController
def index
end
end
Static Index view (yup, parsing imgur link here)
<h1>Hello Rails!</h1>
<%= form_tag("/images", method: "post") do %>
<p>
<%= label_tag(:imgur_link) %><br>
<%= text_field_tag(:imgur) %>
</p>
<p>
<%= submit_tag("Get my cards") %>
</p>
<% end %>
Images Controller (where all the magic SHOULD happen)
class ImagesController < ApplicationController
def show
#collection = params[:imgur_link]
#service1 = service1.new(*args).call
#service2 = service2.new(*args).call
...
end
end
Images Show view
Empty as I'm stuck with the Images controller at the moment.
Any help would be more than appreciated.
Thanks!
There is no reason you should put something into storage just in order to display it. If you get to a point when you have the results in your controller, you could just pass them to view in some #variable
As I see, you have set up the form for step 1. If you also have routes.rb call 'images#show' for POST /images, then you will have params[:imgur_link] available in your show action. This should do:
# config/routes.rb
YourApplication.routes.draw do
# ...
post '/images' => 'images#show'
end
Now you have to somehow process that link. Since I don't know what your results should be, I'm going to assume that you have two classes, Service1 and Service2, both of which accept an URL and return collection of results, and both collections hold the elements of the same class. Then you can leave only unique results for your show view, like this:
# app/controllers/images_controller.rb
class ImagesController < ApplicationController
def show
link = params[:imgur_link]
results1 = Service1.new(link).results
results2 = Service2.new(link).results
#results = (results1 + results2).uniq
end
end
Then you can do something with #results in your show view. E.g.
# app/views/images/show.html.erb
<% #results.each do |result| %>
<%= result.inspect %>
<% end %>

Using Thumbs_up to display users who voted on a post

I'm using Thumbs_Up gem to let users vote on a post(called Topic). I've done the voting part but now I want to display the users who voted on that particular post. I'm very new to Ruby On Rails, and I'm stuck at the view part.
Here's my controller: app/controllers/topics_controller.rb
def vote_who
#topic = Topic.find(params[:id])
#vote_list=#topic.voters_who_voted_for
end
In my index.html.erb, I want to display the names of there users who voted on that post. This should be right next to the vote button. Kind of like this,
But how do I send back information from the controller?
Or is this approach completely wrong?
IMHO, it's more preferable to show all voters in the 'show' view of the each particular Topic (imagine you have 100 voters for one topic, what this table in index view will look like?).
This way you don't need any distinct action (due to Rails conventions 1 action == 1 view (in general)). Just put in your show action:
def show
#topic = Topic.find(params [:id])
#vote_list = #topic.voters_who_voted_for
end
Then in your view (show.html.erb) you need to do something like this:
<% #vote_list.each do |voter| %>
<%= voter.email %> #or login, or name, or any user's attribute you want to display in your list
<% end %>
Or even try to simplify this: leave show action in your TopicsController as it is (don't create any #vote_list variable, only find right Topic), and call voters_who_voted_for method inside your show view, e.g.:
<%= #topic.title %>
<%= #topic.body %>
<%= #topic.voters_who_voted_for %>

Make a very simple CMS

I'm making an extremely simple CMS with rails that simply changes existing text and images on existing pages, nothing else. No changes to layout or anything crazy like that.
It's a bit like wordpress. Here's how it'll work:
If an admin is logged in, they have a special bar at the top of the
page that will enable them to edit the page.
Upon clicking, they go to the control panel, and all of the editable regions of viewable.
They can then edit the pages in the control panel, and save it.
What would be a good way to organize this flow?
I've made a start, and one thing that gets me is that all of the logic that populates a page' editable regions is occurring in the view:
splash/welcome.html.erb
<% #page = Page.find(name: 'welcome') %>
<% regions = #page.text_regions %>
<h1> <%= regions.where(name: 'title').text %> </h1> This returns the title (Welcome to my website)
<%= regions.where(name: 'welcometext').text %> This returns welcome text (This is my website bla bla)
I works fine, although the database has to be initially seeded with empty regions.
However, I don't like how there is logic in the view, so how could I populate a #regions instance variable in the application controller? Or is what I'm doing fine?
Maybe in the future I want users to be able to create pages, meaning I won't be able to have this logic in the view.
DRY
Looks like you'd be better using action_name (perhaps with a helper)
Without knowing the structure of what you're trying to do, this is just speculation, but you may be better doing something like this:
#app/models/region.rb
Class Region < ActiveRecord::Base
scope :title, -> { find_by name: "title" }
scope :welcome_text, -> { find_by name: "welcometext" }
end
#app/controllers/application_controller.rb
Class ApplicationController < ActionController::Base
before_action :set_page
private
def set_page
#page = Page.find_by name: action_name
#regions = #page.text_regions
end
end
#app/views/shared/_regions.html.erb
<h1><%= #regions.title.text %></h1>
<%= #regions.welcome_text %>
#app/views/static/welcome.html.erb
<%= render "shared/regions" %>
Hopefully this will give you some ideas as to how to achieve what you want?

Admin-editable views

There doesn't appear to be a gem for this, and I think a CMS is overkill as the client only wants to edit the welcome message on the home page!
Here's what I think I should do:
1) Create Page model:
rails g model Page name:string
2) Create Field model:
rails g model Field name:string content:string page_id:integer
3) Create relationship, Page h1:b2 Field
4) Create rake task to set up the message field that belongs to the welcome page:
namespace :seeder do
namespace :initial_seed do
task pages: :environment do
p = Page.create(name: "Welcome")
p.fields.create(name: "welcomemessage", content: "everything goes here. The long rambling welcome!")
end
end
end
5) Create a 'static' controller for the 'static'-ish pages. The home, the about us etc...
class Static < ApplicationController
def home
#fields = Page.where().fields
end
end
6) In the view, populate the welcome message from the database (I'll create a helper for this):
<% field = #fields.find {|x| x[:name] == 'welcomemessage' } %>
<%= field.content %>
So that's the reading done. Now onto the creation, updation and deletion:
6) Create a control panel controller:
class Panel < ApplicationController
def pages
#pages = Page.all
end
end
7) Display fields in the view at panel/pages.html.erb: (I'll use partials here)
<% #pages.each do |page| %>
Title: <%= page.name %>
<% page.fields.each do |field|%>
Field: <%= field.name %>
<% form_for(field) do |f| %>
<% f.text_area :content%>
<% f.submit %>
<%= end %>
<% end %>
<% end %>
Now this is just a rough run down of what I want to do. There are a few problems I want to query, though.
Is this sort of how you would do this?
How should I configure my routes? What is a clever way of populating the #fields variable (see step 5) with the fields for the page we're viewing?
If I do have a panel/pages.html.erb view, should it simply display all of the editable fields in text areas? How should it update these areas? Multiple submit buttons inside multiple forms? What if someone wants to edit many fields at once and submit them all at once?
Where should these forms go? Should I create multiple RESTful actions all inside the Panel controller like this?:
class Panel < ApplicationController
# new and create not present as the pages have to be created manually
# Enabling the user to create their own pages with their own layouts is a bit insane
def pages
#pages = Page.all
end
def pages_update
end
def pages_destroy
end
end
Multiple restful routes in one controller doesn't strike me as organised, but it would make it easier to lock down the panel controller with a before_action hook to redirect if not admin...
Also, I'm nearing the end of a big job, and all I need to do is add the ability to edit one field on one page and them I'm done and I really don't want to have to figure out alchemy_cms or whatever. In future, yes, but, please, please, please someone give me some small pointers here.
I would strongly advise against building your own CMS. It's fraught with difficulties, and it seems like you're running up against some of those now. You should go and check out something like AlchemyCMS.

Rails - Execute actions on post's index page

I have a model "Products" (which is a child model of parent model "Assortments") which can be liked by the user. Right now, you can only like the Product on the Products Show page because i'm able to find the products ID, which is what i need to like it
def like
#assortment = Assortment.find(params[:assortment_id])
begin
current_user.vote_for(#product = Product.find(params[:id]))
respond_with #product, :location => assortment_product_path
rescue ActiveRecord::RecordInvalid
redirect_to #product
end
end
I would also like user's to be able to like the product on the products index page. For example, if you go to Pinterest, you can like all the products on their fluid grid layout page as well as on each pictures respective page.
This is one of those things I have yet to learn how to do with Rails. How can i accomplish this??
Thanks in advance! Happy Holidays
Assuming your like action is in your ProductsController, and you have set #products equal to the products you want for your index page, and you're using erb, put something like this in your view:
<% #products.each do |product| %>
<%= link_to "Like", product_link_path(id: product.id) %>
<% end %>
Even if you have it set up differently, it can't be too far off from this.

Resources