find a post against its description using rails - ruby-on-rails

Friends I just want to show a single post against its description.
On my home page I have all the descriptions and when a user clicks any description then user should be redirected to its respective post.
I have two models one for Post and Descrip.
Descrip belongs_to Post
and
Post has_one Descrip
I just want to know that if user clicks on any description then on next page a post should appear related to that description.
Kindly help or suggest me how i can do that. At this time I just get all the posts when user click a description link. Any help will be highly appreciated. I have partial file which i render to my home page.This partila file have a link button as below
<% #post.reverse_each do |post| %>
<li>
<p>
<%= descrip.description %>
</p>
<%=link_to 'APPLY TO THIS JOB', descriptions_view_path, :class => 'read_more pull_rigt' %>
<% end %>
View.html.erb where i render my partial file look like this
<%= render partial: 'posts/post', locals: { post: Post.all} %>
and posts controller have two methods
def show
redirect_to post_path(Post.all) and return
end
def index
#posts = Post.all(:order => "created_at DESC")
end
and description controller have a view method
def view
#descrip = Descrip.find_by_id(params[:post_id])
#post = Post.all
end

Do this:
#config/routes.rb
root to: "descriptions#index"
resources :descriptions
#app/controllers/descriptions_controller.rb
def index
#descriptions = Description.all
end
def show
#description = Description.find params[:id]
end
#app/models/description.rb
Class Description < ActiveRecord::Base
has_one :post
end
#app/views/descriptions/index.html.erb
<% for description in #descriptions do %>
<%= link_to description.title, description_path(description.id) %>
<% end %>
#app/views/descriptions/show.html.erb
<%= #description.post %>

Related

How to refer back to associated index with link_to

Doing nested routes for the first time and I cannot figure out the link_to paths for the nested routes that I have. Using rails scaffold for each
resources :venues do
resources :events
end
I edited to have the following in the index.html.erb of the venue model
<%= link_to 'Events', venue_events_path(venue) %>
Which brings me to the correct index.html.erb of the events model (venues/1/events)
But I just can't seem to figure out the correct link_to path on the show page of event to bring me back to venues/1/events
With the default scaffold, its
<%= link_to 'Back', events_path %>
I have tried different paths like venue_events_path(venue) but rails keeps saying that it cannot find venue without an ID.
I am assuming that is because clicking on the default show link brings me to localhost:3000/events/1 instead of localhost:3000/venues/1/events/1
What would be the correct paths for nested attributes besides the difficulty that I am facing?
For nested routes I would use the following setup:
# routes.rb
resources :venues do
resources :events
end
# venues controller
class VenuesController < ApplicationController
def index
#venues = Venue.all
end
def show
#venue = Venue.find(params[:id])
end
end
# venues index.html.erb
<% #venues.each do |venue| %>
<%= link_to 'Venue', venue_path(venue) %>
<% end %>
# venues show.html.erb
# link to the events index page from the current venue
<%= link_to 'Events', venue_events_path(#venue) %>
# link to each individual event from the current venue
<% #venue.events.each do |event| %>
<%= link_to 'Event', venue_event_path(#venue, event)
<% end %>
# events controller
class EventsController < ApplicationController
def index
#venue = Venue.find(params[:venue_id])
#events = #venue.events
end
def show
#event = Event.find(params[:id])
end
end
# events index.html.erb
# link back to venue
<%= link_to 'Venue', venue_path(#venue) %>
# link to each event
<% #events.each do |event| %>
<%= link_to 'Event', venue_event_path(event.venue, event) %>
<% end %>
# events show.html.erb
# link back to events index
<%= link_to 'Events', venue_events_path(#event.venue) %>
# link back to venue show
<%= link_to 'Venue', venue_path(#event.venue) %>
Keep in mind that this will only work if your events have an venue id. You said you have in your event model: belongs_to :venue, optional: true the optional true make the venue_id not required for an event. If that is what you want then nested routes doesn't really makes sense, because an NOT nested event is not going to be linked nested.

Multiple objects with one form and permitting parameters

My rails app has a games model, and each game has multiple players. When a game is created, a set number of players are created with a default name like so:
def create
#game = Game.new(game_params)
#game.player_number.times do
#game.players << Player.new(name: 'Santa')
end
if #game.save
redirect_to action: "players", id: #game.id
else
render 'new'
end
end
The redirect takes the user to a page that has a form with inputs for each player's name. The actions associated with this page are:
def players
#game = Game.find(params[:id])
end
def playersUpdate
#game = Game.find(params[:id])
puts player_params
if #game.players.update(player_params)
redirect_to #game
else
render 'players'
end
end
private
def player_params
params.require(players: [:name])
end
The editing page itself is:
<h2> Edit Players </h2>
<%= form_tag({:action => 'playersUpdate'},{:id => #game.id}) do %>
<%= #game.players.count %>
<% #game.players.each.with_index do |player,index| %>
<%= fields_for "players[#{index}]", player do |pl| %>
<div>
<%= pl.label :name %><br>
<%= pl.text_field :name %><br>
<%= pl.hidden_field :id %>
</div>
<% end %>
<% end %>
<div>
<%= submit_tag %>
</div>
<% end %>
Here's the routes.rb:
Rails.application.routes.draw do
get 'welcome/index'
resources :games do
collection do
match "/:id/players" => "games#players", :via => :get
match "/:id/players" => "games#playersUpdate", :via => :post
end
end
root 'welcome#index'
end
I get an error:
param is missing or the value is empty: {:players=>[:name]}
And I'm at a loss for what I could be missing. Any tips?
Here are the parameters being passed in, George is the name I'm trying to edit in, all others default to 'Santa':
Processing by GamesController#playersUpdate as HTML
Parameters: {"utf8"=>"✓", "authenticity_token"=>"wNwt9v2ckO/Bl8YGr/a2CDCjSsRec30E51VjZ/Qv2i5BgEnzVbH5M9DsrVfCxdLusS4Ue6Mq+aPSFOiA4K5jJg==", "players"=>{"0"=>{"name"=>"George", "id"=>"122"}, "1"=>{"name"=>"Santa", "id"=>"123"}, "2"=>{"name"=>"Santa", "id"=>"124"}, "3"=>{"name"=>"Santa", "id"=>"125"}}, "commit"=>"Save changes", "id"=>"22"}
You are not breaking any new ground here, and Rails has standard ways to do all of this. But it's easy to get "off the Rails" and make it harder than it needs to be.
Conceptually, stop thinking about updating a bunch of Players, and start thinking about updating a Game that happens to have some Players. The docs are surprisingly helpful here.
Let's go first to your Game model. You'll need to tell it that it's OK to update nested attributes for players, like this:
# models/game.rb
model Game < ApplicationRecord
has_many :players
accepts_nested_attributes_for :players
end
Your view is generating parameters that are not quite standard. Again, let Rails do the work for you. You don't need hidden fields or each_with_index. Since we're in Rails 5, let's use the new form_with helper, and we'll let fields_for do its job without our trying to tell it how to index:
# views/games/edit_players.html.erb
<h2> Edit Players </h2>
<%= form_with(model: game, local: true) do |form| %>
<div>
Game name: <%= form.text_field :name %>
</div>
<%= form.fields_for :players do |player_fields| %>
<div>
Player name: <%= player_fields.text_field :name %><br>
</div>
<% end %>
<div>
<%= form.submit %>
</div>
<% end %>
This will generate params that look something like this:
Parameters: {"game"=>
{"name"=>"Risk",
"players_attributes"=>
{"0"=>{"name"=>"Abel", "id"=>"1"},
"1"=>{"name"=>"Baker", "id"=>"2"},
"2"=>{"name"=>"Charlie", "id"=>"3"}}},
"commit"=>"Update Game",
"id"=>"1"}
Now you don't even need a custom update endpoint. Just use your standard GamesController#update action:
# controllers/games_controller.rb
class GamesController < ApplicationController
...
def edit_players
#game = Game.find(params[:id])
end
def update
#game = Game.find(params[:id])
if #game.update(game_params)
redirect_to #game
else
render :edit
end
end
private
def game_params
params.require(:game).permit(:name, players_attributes: [:id, :name])
end
end
Finally, your routes file is confusing because you are using collection (which doesn't expect an :id) instead of member. The routes file should look something like this:
# routes.rb
Rails.application.routes.draw do
resources :players
resources :games do
member { get :edit_players }
end
end

act_as_followers get all posts of user I'm following

Im trying to get all the Posts from the the Users. I'm following using the act_as_follower gem. The User follows a profile model, and Posts belong to a User.
My User model:
acts_as_follower
My Profile model the user follows:
belongs_to :user
acts_as_followable
Post model:
belongs_to :user
My Post Controller.rb:
def follow
#profile = Profile.find(params[:id])
current_user.follow(#profile)
redirect_to :back
end
def unfollow
#profile = Profile.find(params[:id])
current_user.stop_following(#profile)
redirect_to :back
end
Im trying to implement something like this using follows_by_type method provided:
#posts = current_user.follows_by_type('Post').order("created_at DESC")
But the thing is the User follows the Profile model, but here I'm looking for a type 'Post'.
EDIT
In my index controller i'v set up the following:
#favoritePost = Post.where(user_id: current_user.all_follows.pluck(:id))
And in the view iv implemented this:
<% if user_signed_in? %>
<%#favoritePost.each do |post| %>
<%= post.title %>
<% end %>
<% end %>
The gem lets you follow multiple models and follows_by_type('Post') filters the Posts you follow.
What you're looking to do is to return the posts from the users you follow.
Controller
#posts = Post.where(user_id: current_user.all_following.pluck(:id))
View
<% #posts.each do |post| %>
<%= post.title %>
<% end %>
I worked out this solution, might not be the best, but it works as required.
In my controller i set this up:
#following = current_user.all_following
#followposts = #following.each do |f|
f.user.id
end
And in my view I have set this up:
<% #followposts.each do |f| %>
<% f.user.posts.each do |g| %>
<%= g.title %>
<% end %>
<% end %>

How to show articles with special categories?

So I'm using has_and_belong_to_many association for two models (Article and Category). My header have link with dropdown menu where different categories appears. All my articles are on index page and I need to sort it depending what category it has so users could choose what they want to see. I guess I should do something in show action in category controller, but don't know what exactly. To solve this I played with different each iterations in my views and controller, but unfortunately it didn't help.
Any help will be appreciated
You can select articles with certain category with
selected_articles = Category.find_by_name("Name of category").articles
Or, if you don't know the name simply
selected_articles = Category.find(category_id).articles
Article.joins(:category).where(categories: {id: :your_category_id})
#config/routes.rb
resources :articles do
get ":category_id", action: :index, on: :collection #-> url.com/articles/:category_id
end
#app/controllers/articles_controller.rb
class ArticlesController < ApplicationController
def index
if params[:category_id]
#articles = Article.joins(:categories).where(category: {id: params[:category_id]})
else
#articles = Article.all
end
end
end
This will allow you to use:
#app/views/articles/index.html.erb
<%= form_tag articles_path do %>
<%= f.collection_select :category_id, Category.all, :id, :name %>
<%= f.submit %>
<% end %>
<% #articles.each do |article| %>
<%= article.title %>
<% end %>

problem with request.post

I have a controller that has the following index action :
def index
if request.post?
flash[:notice] = "Searching.."
redirect_to songs_path # where songs_path is this index page that i am on
end
end
in my application layout i have defined the flash section as such
<% if flash[:notice] %>
<div id='notice'><%= flash[:notice] %></div>
<% end %>
and on my pages_path i've got
<% form_for :search do |f| %>
<%= f.label :search_text %>
<%= f.text_field :search_text %>
<p>
<%= f.submit "Search" %>
</p>
<% end %>
The final result should be a search through a youtube api ( youtube-g) but now i would only wish to make that flash notification appear when i click on the "Search" button , and it doesn't .. any ideas why ?
index action ordinary is GET request. So, if in your routes.rb there is something like resources :searches then your code won't work.
try this:
def create
render :text => "Searching.."
end
because POST /searches will refer to create action
you should update your RESTful route to like this
resources :songs do
collection do
get 'search'
end
end
Then in your Controller
def search
# Perform Your search here like Youtube ..
flash[:notice] = "Searching.."
redirect_to songs_path # This should work now.
end

Resources