How to render polymorphic comment partial in feed? - ruby-on-rails

I created a feed following http://railscasts.com/episodes/406-public-activity?view=asciicast.
In that feed I'd like it to say,
"User Name" added/updated value "Value Name" with the comment "Comment Content".
This partial creates the "Value Name" part:
views/public_activity/comment/_create.html.erb
added value
<% if activity.trackable %>
<b><%= link_to activity.trackable.name, activity.trackable %></b>
<% else %>
which has since been removed
<% end %>
This partial creates the "Comment Content" part:
views/public_activity/valuation/_create.html.erb
with the comment
<% if activity.trackable %>
<%= link_to activity.trackable.content %>
<% else %>
which has since been removed
<% end %>
If I add name or content to either one of the partials I am given an undefined method error message. What code would I need to add to their controllers or application controller to make something like this work?
Ideally, with the comment "Comment Content". would only be generated in instances where a comment is created so that, with the comment, wouldn't be left hanging.
class CommentsController < ApplicationController
before_action :load_commentable
before_action :set_comment, only: [:show, :edit, :update, :destroy]
before_action :logged_in_user, only: [:create, :destroy]
def index
#comments = #commentable.comments
end
def new
#comment = #commentable.comments.new
end
def create
#comment = #commentable.comments.new(comment_params)
if #comment.save
#comment.create_activity :create, owner: current_user
redirect_to #commentable, notice: "comment created."
else
render :new
end
end
def edit
#comment = current_user.comments.find(params[:id])
end
def update
#comment = current_user.comments.find(params[:id])
if #comment.update_attributes(comment_params)
redirect_to #commentable, notice: "Comment was updated."
else
render :edit
end
end
def destroy
#comment = current_user.comments.find(params[:id])
#comment.destroy
#comment.create_activity :destroy, owner: current_user
redirect_to #commentable, notice: "comment destroyed."
end
private
def set_comment
#comment = Comment.find(params[:id])
end
def load_commentable
resource, id = request.path.split('/')[1, 2]
#commentable = resource.singularize.classify.constantize.find(id)
end
def comment_params
params.require(:comment).permit(:content, :commentable)
end
end
class ValuationsController < ApplicationController
before_action :set_valuation, only: [:show, :edit, :update, :destroy]
before_action :logged_in_user, only: [:create, :destroy]
def index
if params[:tag]
#valuations = Valuation.tagged_with(params[:tag])
else
#valuations = Valuation.order('RANDOM()')
end
end
def show
#valuation = Valuation.find(params[:id])
#commentable = #valuation
#comments = #commentable.comments
#comment = Comment.new
end
def new
#valuation = current_user.valuations.build
end
def edit
end
def create
#valuation = current_user.valuations.build(valuation_params)
if #valuation.save
redirect_to #valuation, notice: 'Value was successfully created'
else
#feed_items = []
render 'pages/home'
end
end
def update
if #valuation.update(valuation_params)
redirect_to #valuation, notice: 'Value was successfully updated'
else
render action: 'edit'
end
end
def destroy
#valuation.destroy
redirect_to valuations_url
end
private
def set_valuation
#valuation = Valuation.find(params[:id])
end
def correct_user
#valuation = current_user.valuations.find_by(id: params[:id])
redirect_to valuations_path, notice: "Not authorized to edit this valuation" if #valuation.nil?
end
def valuation_params
params.require(:valuation).permit(:name, :private_submit, :tag_list, :content, :commentable, :comment)
end
end
class ApplicationController < ActionController::Base
include PublicActivity::StoreController
#before_action :load_todays_habits
before_action :set_top_3_goals
before_action :randomize_value
before_action :set_stats
protect_from_forgery with: :exception
include SessionsHelper
def set_top_3_goals
#top_3_goals = current_user.goals.unaccomplished.top_3 if current_user
end
def randomize_value
#sidebarvaluations = current_user.valuations.randomize if current_user
end
def set_stats
#quantifieds = Quantified.joins(:results).all
#averaged_quantifieds = current_user.quantifieds.averaged if current_user
#instance_quantifieds = current_user.quantifieds.instance if current_user
end
hide_action :current_user
private
#def load_todays_habits
# #user_tags = current_user.habits.committed_for_today.tag_counts if current_user
# #all_tags = Habit.committed_for_today.tag_counts if current_user
#end
# Confirms a logged-in user.
def logged_in_user
unless logged_in?
store_location
flash[:danger] = "Please log in."
redirect_to login_url
end
end
end
Thank you so much for your time.

Related

Rails: uninitialized constant class name

I'm getting this problem:
uninitialized constant QuestionsController::Question
def index
#Question
#preguntas = Question.all
#project_id = request.original_url.split('.').last
set_current_project(#project_id)
if(#project_id.include? "http")
On my QuestionController randomly after changing nothing from my application, any idea what may be causing it? here's the complete .rb file:
class QuestionsController < ApplicationController
before_action :require_user
before_action :require_project
before_action :require_user, except: [:new, :create]
before_action :current_project, only: [:index]
def index
#preguntas = Question.all
#project_id = request.original_url.split('.').last
set_current_project(#project_id)
if(#project_id.include? "http")
#project_id = "0"
end
if(#project_id != "0")
#proyecto = Project.find(#project_id)
end
end
def show
#pregunta = Question.find(params[:id])
end
def new
#pregunta = Question.new
end
def create
#pregunta = Question.new(pregunta_params)
if #pregunta.save
redirect_to #pregunta
else
render 'new'
end
end
def edit
#pregunta = Question.find(params[:id])
end
def update
#pregunta = Question.find(params[:id])
if #pregunta.update(pregunta_params)
redirect_to #pregunta
else
render 'edit'
end
end
def destroy
#pregunta = Question.find(params[:id])
#pregunta.destroy
flash[:danger] = "Se ha borrado la pregunta"
redirect_to questions_path
end
def require_same_user
set_project
if current_user != #project.user && !#current_user.admin?
flash[:danger] = "Solo puedes editar tus artículos"
redirect_to root_path
end
end
def require_project
if current_user.projects.count <1 && !current_user.admin?
redirect_to root_path
end
end
private
def pregunta_params
params.require(:question).permit(:question, :value, :phase, :area, :input)
end
end
Ensure that the Question model is defined in a file named app/models/question.rb like this:
class Question < ApplicationRecord
# methods...
end

Displaying all microposts in a select box

The following code creates a select box
<%= select_tag "microposts", options_from_collection_for_select(#microposts, "id", "name"), { :prompt => 'All microposts' } %>
I want to show all the microposts in a select box, but i get the following error
NoMethodError in Managments#edit
undefined method `map' for nil:NilClass
Did you mean? tap
Can someone explain to me how to display all the microposts in a select box?
controller
class ManagmentsController < ApplicationController
before_action :logged_in_user, only: [:create, :destroy]
before_action :correct_user, only: :destroy
def index
#managments = current_user.managments
#micropost = current_user.microposts.build
end
def show
#microposts = Micropost.paginate(page: params[:page])
#managment = Managment.find_by(id: params[:id])
if !#managment
raise ActionController::RoutingError.new('Not Found')
end
#user = #managment.user
end
def new
#user = User.new
#managment = Managment.new
end
def edit
#managment = Managment.find(params[:id])
end
def create
#managment = current_user.managments.build(managment_params)
if #managment.save
flash[:success] = "Managment created!"
redirect_to #managment
else
#feed_items = current_user.feed.paginate(page: params[:page])
render 'new'
end
end
def update
#managment = Managment.find(params[:id])
if #managment.update(managment_params)
redirect_to #managment
else
render 'edit'
end
end
def destroy
#managment.destroy
flash[:success] = "Managment deleted"
redirect_to managments_path
end
private
def managment_params
params.require(:managment).permit(
:title, :budget,
:procent1, :procent2, :procent3, :procent4,
:procent5, :procent6, :procent7,
:procent8, :procent9, :procent10,
:procent11, :procent12, :result1,
:result2, :result3, :objectivesname1,
:objectivesname2, :objectivesname3,
:lowprocent1, :lowprocent2, :lowprocent3,
:medprocent1, :medprocent2, :medprocent3,
:highprocent1, :highprocent2, :highprocent3,
:lowobjectives1, :lowobjectives2, :lowobjectives3,
:medobjectives1, :medobjectives2, :medobjectives3,
:highobjectives1, :highobjectives2, :highobjectives3
)
end
def correct_user
#managment = current_user.managments.find_by(id: params[:id])
redirect_to managments_path if #managment.nil?
end
end
The Answer to the question can be find in the comments
def edit
#managment = Managment.find(params[:id])
#microposts = Micropost.paginate(page: params[:page])
end

How to link_to index of another user?

In the goals show page:
<%= link_to goals_path, class: "btn" do %>
<span class="glyphicon glyphicon-list"></span> Goals
<% end %>
but instead of being taken to my own goals_path I want to be taken to the goals_path of whichever user's goal show page I'm looking at.
goals_controller
class GoalsController < ApplicationController
before_action :set_goal, only: [:show, :edit, :update, :destroy, :like]
before_action :logged_in_user, only: [:create, :destroy]
before_action :correct_user, only: [:edit, :update, :destroy]
def index
if params[:tag]
#goals = Goal.tagged_with(params[:tag])
else
#accomplished_goals = current_user.goals.accomplished.order("deadline")
#unaccomplished_goals = current_user.goals.unaccomplished.order("deadline")
end
end
def show
#goal = Goal.find(params[:id])
#commentable = #goal
#comments = #commentable.comments
#comment = Comment.new
#notable = #goal
#notes = #notable.notes
#note = Note.new
#correct_user = current_user.goals.find_by(id: params[:id])
end
def new
#goal = current_user.goals.build
end
def edit
end
def create
#goal = current_user.goals.build(goal_params)
if (params[:commit] == 'conceal')
#goal.conceal = true
#goal.save
redirect_to #goal, notice: 'Goal was successfully created'
elsif
#goal.save
track_activity #goal
redirect_to #goal, notice: 'Goal was successfully created'
else
flash.now[:danger] = 'Required Field: "Enter Goal"'
render 'new'
end
end
def update
if #goal.update(goal_params)
redirect_to goals_url, notice: 'Goal was successfully updated'
else
render action: 'edit'
end
end
def destroy
#goal.destroy
redirect_to goals_url
end
def like
#goal = Goal.find(params[:id])
#goal_like = current_user.goal_likes.build(goal: #goal)
if #goal_like.save
#goal.increment!(:likes)
flash[:success] = 'Thanks for liking!'
else
flash[:error] = 'Two many likes'
end
redirect_to(:back)
end
private
def set_goal
#goal = Goal.find(params[:id])
end
def correct_user
#goal = current_user.goals.find_by(id: params[:id])
redirect_to root_url, notice: "Not authorized to edit this goal" if #goal.nil?
end
def goal_params
params.require(:goal).permit(:name, :like, :deadline, :accomplished, :tag_list, :comment, :private_submit)
end
end
Please let me know if you need further explanation or code to help you help me :-]
If you have a target user defined (or have a way to access a user's id), you can do something like:
<% link_to goals_path(user_id: #goal.user_id) do %>
<span class="glyphicon glyphicon-list"></span> Goals
<% end %>
Then you can modify your index method to handle a user_id param:
def index
if params[:tag]
#goals = Goal.tagged_with(params[:tag])
elsif params[:user_id]
#goals = User.find(params[:user_id]).goals
else
#accomplished_goals = current_user.goals.accomplished.order("deadline")
#unaccomplished_goals = current_user.goals.unaccomplished.order("deadline")
end
end
This should render a particular user's goals if their id is passed in as a param. Hope this helps!
You could also just take a completely different route, and be a little more REST-ful about grabbing users/:user_id/goals, and add it as a route in your routes.rb
get "/users/:user_id/goals", to: "goals#user_goals", as: "user_goals"
and update your button to have
<% link_to user_goals_path(#goal_user) ... %>
and then add the goals#user_goals method
def user_goals
#goals = Goal.find_by({user_id: params[:user_id]})
render :index # or some other view
end

Using a Partial, How to Create a Multi Controller ROOT ROUTE?

How can we make the root route provide: habits, valuations, goals, quantifieds (not just valuations as it currently is)?
And to make matters more difficult how can we only show #unaccomplished_goals and not #accomplished_goals when including the goals controller in the root route?
The root route would show this in 1 view:
Habits Table
Valuations Table
Unaccomplished Goals Table
Quantifieds Table
I was told I need to use a partial to share code across the application. How can we do this so that the root route could lead to something like "home"?
routes
Rails.application.routes.draw do
resources :habits
resources :goals
resources :valuations
resources :quantifieds
resources :results
devise_for :users
root 'valuations#index'
get "about" => "pages#about"
get 'tags/:tag', to: 'valuations#index', as: :tag
end
controllers
class HabitsController < ApplicationController
before_action :set_habit, only: [:show, :edit, :update, :destroy]
before_action :correct_user, only: [:edit, :update, :destroy]
before_action :authenticate_user!, except: [:index, :show]
def index
#habits = Habit.all.order("date_started DESC")
#habits = current_user.habits
end
def show
end
def new
#habit = current_user.habits.build
end
def edit
end
def create
#habit = current_user.habits.build(habit_params)
if #habit.save
redirect_to #habit, notice: 'Habit was successfully created.'
else
render action: 'new'
end
end
def update
if #habit.update(habit_params)
redirect_to #habit, notice: 'Habit was successfully updated.'
else
render action: 'edit'
end
end
def destroy
#habit.destroy
redirect_to habits_url
end
private
def set_habit
#habit = Habit.find(params[:id])
end
def correct_user
#habit = current_user.habits.find_by(id: params[:id])
redirect_to habits_path, notice: "Not authorized to edit this habit" if #habit.nil?
end
def habit_params
params.require(:habit).permit(:missed, :left, :level, :date_started, :trigger, :action, :target, :positive, :negative, :committed => [])
end
end
class ValuationsController < ApplicationController
before_action :set_valuation, only: [:show, :edit, :update, :destroy]
before_action :authenticate_user!, except: [:index, :show]
def index
if params[:tag]
#valuations = Valuation.tagged_with(params[:tag])
else
#valuations = Valuation.order('RANDOM()')
end
end
def show
end
def new
#valuation = current_user.valuations.build
end
def edit
end
def create
#valuation = current_user.valuations.build(valuation_params)
if #valuation.save
redirect_to #valuation, notice: 'Value was successfully created'
else
render action: 'new'
end
end
def update
if #valuation.update(valuation_params)
redirect_to #valuation, notice: 'Value was successfully updated'
else
render action: 'edit'
end
end
def destroy
#valuation.destroy
redirect_to valuations_url
end
private
def set_valuation
#valuation = Valuation.find(params[:id])
end
def correct_user
#valuation = current_user.valuations.find_by(id: params[:id])
redirect_to valuations_path, notice: "Not authorized to edit this valuation" if #valuation.nil?
end
def valuation_params
params.require(:valuation).permit(:name, :tag_list)
end
end
class GoalsController < ApplicationController
before_action :set_goal, only: [:show, :edit, :update, :destroy]
before_action :authenticate_user!, except: [:index, :show]
def index
#goals = Goal.all.order("deadline")
#accomplished_goals = current_user.goals.accomplished
#unaccomplished_goals = current_user.goals.unaccomplished
end
def show
end
def new
#goal = current_user.goals.build
end
def edit
end
def create
#goal = current_user.goals.build(goal_params)
if #goal.save
redirect_to goals_url, notice: 'Goal was successfully created'
else
render action: 'new'
end
end
def update
if #goal.update(goal_params)
redirect_to goals_url, notice: 'Goal was successfully updated'
else
render action: 'edit'
end
end
def destroy
#goal.destroy
redirect_to goals_url
end
private
def set_goal
#goal = Goal.find(params[:id])
end
def correct_user
#goal = current_user.goals.find_by(id: params[:id])
redirect_to goals_path, notice: "Not authorized to edit this goal" if #goal.nil?
end
def goal_params
params.require(:goal).permit(:name, :deadline, :accomplished)
end
end
class QuantifiedsController < ApplicationController
before_action :set_quantified, only: [:show, :edit, :update, :destroy]
before_action :authenticate_user!, except: [:index, :show]
def index
#quantifieds = Quantified.joins(:results).all
#averaged_quantifieds = current_user.quantifieds.averaged
#instance_quantifieds = current_user.quantifieds.instance
end
def show
end
def new
#quantified = current_user.quantifieds.build
end
def edit
end
def create
#quantified = current_user.quantifieds.build(quantified_params)
if #quantified.save
redirect_to quantifieds_url, notice: 'Quantified was successfully created'
else
render action: 'new'
end
end
def update
if #quantified.update(quantified_params)
redirect_to quantifieds_url, notice: 'Goal was successfully updated'
else
render action: 'edit'
end
end
def destroy
#quantified.destroy
redirect_to quantifieds_url
end
private
def set_quantified
#quantified = Quantified.find(params[:id])
end
def correct_user
#quantified = current_user.quantifieds.find_by(id: params[:id])
redirect_to quantifieds_path, notice: "Not authorized to edit this goal" if #quantified.nil?
end
def quantified_params
params.require(:quantified).permit(:categories, :name, :metric, :result, :date, results_attributes: [:id, :result_value, :date_value, :_destroy])
end
end
If we need to work with other files:
Github: https://github.com/RallyWithGalli/ruletoday
Or I could add them here.
Thanks for your expertise =]

Attaching User to Comments

I have a working commenting system that is polymorphic so that comments can be added to users and posts. However, I am unable to figure out how to attach the logged in user (commenter) to the comment.
comments_controller.rb:
class CommentsController < ApplicationController
before_filter :authenticate_user!, :only => [:create, :destroy]
def index
#commentable = find_commentable
#comments = #commentable.comments
end
def new
#commentable = find_commentable
end
def create
#commentable = find_commentable
#comment = #commentable.comments.build(params[:comment])
if #comment.save
flash[:notice] = "Successfully created comment."
redirect_to get_master
else
render :action => 'new'
end
end
def destroy
#comment = Comment.find(params[:id])
#comment.destroy
respond_to do |format|
format.html { redirect_to comments_url }
format.json { head :no_content }
end
end
protected
def find_commentable
params.each do |name, value|
if name =~ /(.+)_id$/
return $1.classify.constantize.find(value)
end
end
nil
end
def get_master
#parent = #comment.commentable
if #parent.respond_to?('commentable_type')
#comment = #parent
get_master
else
return #parent
end
end
end
Isn't it as simple as adding it before the save?
#comment.commenter = current_user
You can also add it in your view:
f.hidden_field :commenter_id, value: current_user.id
I think I'd prefer setting it in the view.

Resources