Rails Two Views With One Controller#Action - ruby-on-rails

I created a rails association "user has many follows" currently have lists of user's followers and followings. I want to have 2 links onusers#show to display lists of followers and followings. I know I can render two different views in my follows#index using if else statement but I'm not sure how to go about it. My initial thought was to have rails check which link was clicked (either 'Followers' or 'Followings') but I couldn't find an exact answer. I also thought of creating two different tables (Followers, Followings) but adding 2 same values for 1 action seemed redundant and waste of space.
Here is my FollowsController:
class FollowsController < ApplicationController
def index
#follows = Follow.all
render :index
end
def create
#follow = Follow.create(follow_params)
redirect_to user_url(#follow.user_id)
end
def destroy
#follow = Follow.find(params[:id])
#follower_id = #follow.user_id
#follow.destroy!
redirect_to user_url(#follower_id)
end
private
def follow_params
params.require(:follow).permit(:follower_id, :user_id)
end
end
What would be the best approach?

Example:
def index
#follows = Follow.all
if #follows.present?
render 'show_with_followers'
else
render 'show_without_followings'
end
end
views
app/views/follows/_show_with_followers.html.erb
app/views/follows/_show_without_followings.html.erb

Here is an answer I found so far. I will be using in my view
<%= link_to 'Followers', follows_path(:follows => 'followers') %>
<%= link_to 'Followings', follows_path(:follows => 'followings') %>
and use
def index
if params["follows"] == 'followers'
#render followers
else
#render followings
end
end
end

Related

Render different show pages with category in ruby on rails

I need render different show pages for my blog posts.
I have 3 different categories : themes, snippets, projects.
Each blog post must related with those three categories.
If anyone click post(assume related category is snippets), it display in different show...etc... It is same for other categories.
How it is possible with conditional statements.
you can make routes like:
resources :posts, except:[:show]
get 'posts/:id/cat/:category' , to:'posts#show', as: :show
you have to create partial for categories as follows:
app/views/posts/_themes.html.erb
app/views/posts/_snippets.html.erb
app/views/posts/_projects.html.erb
then in controller's show action.
controllers/posts_controller.rb
def show
#post = Post.find(params[:id])
#category = params[:category]
...
end
Then render that category in show page.
views/posts/show.html.erb
...
<%= render '#{#category}'%>
Just one show method and you can render different views conditionally and simple render works for you, you can use below code:
Just render with HTML file name if file is in same controller's view
if #post.theme?
render 'themes'
elsif #post.snippet?
render 'snippets'
else
render 'projects'
end
I would start with this, then refactor for avoiding repetition
categories_controller.rb
def themes
##posts = Post.where(category_id: 1)
...
render layout: themes
end
def snippets
##posts = Post.where(category_id: 2)
...
render layout: snippets
end
def projects
##posts = Post.where(category_id: 3)
...
render layout: snippets
end
You can do something like this:
models/post.rb
def category
#category ||= ... #returns category name
end
controllers/post_controller.rb
def show
#post = Post.find(id)
#category = #post.category
...
end
views/posts/show.html.erb
...
<%= render "types/#{#category}" %>
...
Also you can render specified template from controller if you don't have any common parts for categories
You can use rails partial to achieve this:
to know more about partial refer Rails Partial
you can create partial for categories as follows:
app/views/categories/_themes.html.erb
app/views/categories/_snippets.html.erb
app/views/categories/_projects.html.erb
in show page of categories you can modify the show page as follows
class CategoriesController < ApplicationController
...
def show
...
render params[:category]
end
...
end
Now when you call show page pass a param category which denotes the type of category which you want to show
if you want to show category snippets then the params will be params[:category] = 'snippets' this will look for partial inside categories view.

Rails Create article with other user not current_user

I would like to create an article with other user not current_user and for that I'm saving in a session the id to the other user and I recover this id with a collection in the view to this point everything work fine but when I'm trying to use my helper :selected_user into my articles controller with a if sentence doesn't work here is my code:
def new
if selected_user.present?
#article = selected_user.articles.build state: :step1
render_wizard
else
#article = current_user.articles.build state: :step1
render_wizard
end
end
so, I'm asking if the selected_user.present? I would like to create the article with this user_id but else I would like to create it with the current_user
my create method is:
def create
if selected_user.present?
step = :step1
#article = selected_user.articles.build article_params_step1
#article.state = step.to_s
if #article.save
redirect_to wizard_path(next_step, article_id: #article)
else
render_wizard
end
else
step = :step1
#article = current_user.articles.build article_params_step1
#article.state = step.to_s
if #article.save
redirect_to wizard_path(next_step, article_id: #article)
else
render_wizard
end
end
end
so, yeah when I run my view the controller jump to the else section.
just for clarify my selected_user not return nil but here is the implementation:
selections_controller.rb:
class SelectionsController < ApplicationController
before_action :authenticate_user!
def create
session[:selected_user_id] = params[:user][ :user_id]
redirect_to root_path
end
end
and in my application_controller.rb:
helper_method :selected_user
def selected_user
#selected_user ||= User.find(session[:selected_user_id])
end
and in the view:
<%= form_tag( { :controller => "selections", :action => "create" } , :class => "navbar-form navbar-left") do %>
<%= collection_select(:user, :user_id, User.all, :id, :name, prompt: "Escoge cliente")%>
<%= submit_tag 'Enviar' %>
<% end %>
if I try create an article without select an user from my collection appear this error:
Couldn't find User with 'id'=
but when I select my user from the collection everything works fine. so just I want when I don't select nothing create with the current_user.
Thanks for your time !
Regards !
The reason why you were seeing the error
Couldn't find User with 'id'=
when you haven't selected a user was that the session[:selected_user_id] was nil and your old selected_user with following code was throwing the error.
def selected_user
#selected_user ||= User.find(session[:selected_user_id])
end
User.find method expects either a single id or an array of ids. If you give a single id and if it finds the relevant record in the database then it will returns that instance. If you give an array of ids and if it finds those relevant records in the database, then it will return array of those instances. But if you pass nil to it, then it will through the error Couldn't find User with 'id'= as it won't find a relevant record.
But your updated selected_user implementation:
def selected_user
#selected_user ||= session[:selected_user_id] && User.find_by_id(session[:selected_user_id])
end
is working because, first you are checking for the existence of session[:selected_user_id] value and second you are using User.find_by_id instead of User.find.
User.find_by_id either returns a single instance of the record if it finds it in the database or will return nil if it doesn't find the record. It will never through an error.
Refer to ActiveRecord#find and ActiveRecord#find_by for more info.
I'm not sure why is working and what is the different but my solution for the problem it was to add this to my selected_user method:
def selected_user
#selected_user ||= session[:selected_user_id] && User.find_by_id(session[:selected_user_id])
end
and with that I don't have the nil error and entry to the if statement without errors.

Could find Addict without an ID

I'm trying to put a new form that creates new "Addicts" in a modal in my home page.
It's a simple form with 2 inputs, that when clicking on New, a modal pops up with that form in my index page.
I can't get it to work because it keeps saying "Couldnt find Addict without an ID".
My Pages Controller
class PagesController < ApplicationController
def home
#addict = Addict.find(params[:id])
#lanzaderas = Lanzadera.all
render 'index'
end
end
My Addict Controller
class AddictsController < ApplicationController
def index
#posts = Addict.all
end
def show
#addict = Addict.find(params[:id])
end
def new
#addict = Addict.new(params[:addict])
end
def create
#addict = Addict.new(params[:addict])
if #addict.save
redirect_to posts_path, :notice => "Your Addict was saved"
else
render "new"
end
end
def edit
end
def update
end
def destroy
end
end
end
My form in my modal
<%= form_for #addict do |f| %>
<%= f.input :name %>
<%= f.input :surname %>
<%= f.input :postal %>
<%= f.submit %>
<% end %>
I know it has something to do with the variable / id not being passed correctly in my Controller, but it's an error I get lots of times and don't know why I happens.
Thanks!
In def home in your PagesController you have this code:
#addict = Addict.find(params[:id])
I suspect, that you don't have the id for 'addict' in your parameters, when you visit your home action.
Do you want to display one particular addict in your 'home' page? If not, you can remove this line.
Update:
Change this in your AddictsController:
def new
#addict = Addict.new
end
In the new action you only "prepare" a new addict object. Using the find method is not possible, since the record hasn't been created yet.
If you're using Rails 4 you also have to permit your parameters (for security reasons; more info here: Railsguides: Strong Parameters)
In your case you have to do 2 things:
First: add this at the bottom of your AddictsController:
private
def addict_params
params.require(:addict).permit(:name, :surname, :postal)
end
Second: use this method in your create action instead of params[:addict]:
def create
#addict = Addict.new(addict_params)
if #addict.save
redirect_to posts_path, :notice => "Your Addict was saved"
else
render "new"
end
end

How can I restrict the number of records (reviews) added by a user?

How can I go about restricting the number of reviews a user can write for a venue to just one?
I would also like a flash message prompt if they try to review a venue twice.
I'm not too sure what code I should to include in my question but heres the create review method:
Review controller
def create
#review = current_user.reviews.create!(params[:review])
#review.venue = #venue
if #review.save
flash[:notice] = 'Thank you for reviewing this venue!'
respond_to do |format|
format.html { redirect_to venue_path(#venue) }
format.js
end
else
render :action => :new
end
end
Thanks for any help its much appreciated!
edit
I've added this helper method into the venues controller:
def reviewed?
if current_user.reviews.for_venue(#venue).empty?
true
else
false
end
end
and wrapped my form in:
<% if reviewed? %>
form
<% end %>
but this just returns undefined method `reviews' for VenuesController
It would be better if you could prevent the user from reviewing the venue in the first place. In your view(or create a helper) do a check if the venue was already reviewed by the user(many ways to do this). If it was, don't show the review form. Easy. If you're pretty OC, that's when you check in the controller.
Maybe you should use a before_validation callback, so that you can check if the venue has been already reviewed by the user. You can include the venue in the create line:
current_user.reviews.create!({:venue_id => #venue.id}.merge(params[:review]))
And for the validation, use something like this:
before_validation :check_if_already_reviewed
def check_if_already_reviewed
if (check if already reviewed)
return false
else
return true
end
end

Camping: Return user to recent entries, but keep errors

Users can view a specific entry in my webapp with a URL. /entry/8, for example. If an entry doesn't exist, "Entry not found" gets appended to #messages and I render an error page.
I'd like to show some arbitrary query instead of a blank page, but I can't figure out a good way to keep the error message around to be displayed. There are other actions that need to take place in the arbitrary query's controller, so I can't just duplicate the query and render :posts.
Some example code:
module MyApp::Controllers
class ComplexQuery < R '/query'
def get
#entries = Entries.all(:conditions => someComplexConditions)
until #entries.complexEnough? then #entries.makeMoreComplex! end
end
end
class SingleEntry < R '/entry/(\d+)'
def get(id)
#entries = Entries.find_all_by_id(id)
unless #entries.nil?
render :posts
else
#messages = ["That entry does not exist."]
render :blank # I want to run Controllers::ComplexQuery, instead of rendering a blank page.
end
end
end
end
Something like this?
def get(id)
#entries = Entries.find_all_by_id(id)
unless #entries.nil?
render :posts
else
r *MyApp.get(:ComplexQuery)
end
end
See Camping.method_missing.
But I would also recommend moving ComplexQuery into a helper method:
module MyApp::Helpers
def complex_query(conditions); end
end
Then you can complex_query(something) in both SingleEntry and ComplexQuery.
Try this:
#entry = Entry.find_by_id(params[:id]) # returns nil when not found
if #entry.nil?
flash[:notice] = "Entry not found"
render :action => "recent"
end

Resources