Undefined Method `stringify_keys' for Model's Show Page - ruby-on-rails

In trying to access the show view for one of my models workouts#show I have been getting an error that says:
undefined method `stringify_keys' for "/workouts/abs-0002":String
It's calling it on a link in a _template.html.erb, which is being rendered in my workouts#show page (error called on the first line):
<%= link_to "Do this one!", workout_path(workout) do %>
<p class="cta">Pick me!</p>
<% end %>
My workouts controller is:
class WorkoutsController < ApplicationController
def index
#workouts = Workout.all
end
def show
#workout = Workout.friendly.find(params[:id])
#exercise = Exercise.new
#report = Report.new
end
def new
#workout = Workout.new
#workout.user_id = current_user
end
def create
#workout = Workout.new(workout_params)
#workout.user = current_user
if #workout.save
flash[:notice] = "Workout was saved successfully."
redirect_to #workout
else
flash.now[:alert] = "Error creating workout. Please try again."
render :new
end
end
def edit
#workout = Workout.friendly.find(params[:id])
#workout.user_id = current_user
end
def update
#workout = Workout.friendly.find(params[:id])
#workout.name = params[:workout][:name]
#workout.workout_type = params[:workout][:workout_type]
#workout.teaser = params[:workout][:teaser]
#workout.description = params[:workout][:description]
#workout.video = params[:workout][:video]
#workout.difficulty = params[:workout][:difficulty]
#workout.trainer = params[:workout][:trainer]
#workout.user_id = params[:workout][:user_id]
if #workout.save
flash[:notice] = "Workout was updated successfully."
redirect_to #workout
else
flash.now[:alert] = "Error saving workout. Please try again."
render :edit
end
end
def destroy
#workout = Workout.friendly.find(params[:id])
if #workout.destroy
flash[:notice] = "\"#{#workout.name}\" was deleted successfully."
redirect_to action: :index
else
flash.now[:alert] = "There was an error deleting the workout."
render :show
end
end
private
def workout_params
params.require(:workout).permit(:name, :workout_type, :teaser, :description, :video, :difficulty, :trainer, :user_id)
end
end
And my workout.rb model is:
class Workout < ActiveRecord::Base
extend FriendlyId
friendly_id :name, use: :slugged
belongs_to :user
has_many :exercises
has_many :reports
validates :user, presence: true
end
Can anyone help me see what's going wrong here?

according to http://api.rubyonrails.org/classes/ActionView/Helpers/UrlHelper.html#method-i-link_to, you need to remove the first param if you want to use a custom name for the link:
You can use a block as well if your link target is hard to fit into the name parameter. ERB example:
<%= link_to(#profile) do %>
<strong><%= #profile.name %></strong> -- <span>Check it out!</span>
<% end %>
# =>
<a href="/profiles/1">
<strong>David</strong> -- <span>Check it out!</span>
</a>

Related

How to give ID to other controller: no implicit conversion of Symbol into Integer error

I want to give an id of "paper model" to "schedules model" and create a note_id.
However an error message "no implicit conversion of Symbol into Integer" shows.
Can someone help me to solve this problem?
papers/index.html.erb
<%= link_to "Go to Schedule", new_schedule_path(id: paper.id) %>
routes.rb
get '/schedules/new/:id', to: 'schedules#new', as: :schedules_new
schedules_controller
class ActionsController < ApplicationController
before_action :authenticate_user!
before_action :set_schedule, only: [:edit, :update, :destroy]
def new
#schedule = Schedule.new
end
def create
#schedule = Schedule.new(schedule_params)
#schedule.user_id = current_user.id
#schedule.note_id = params[:id]
if #schedule.save
redirect_to schedules_path, notice: "A schedule was saved!"
end
end
def index
#schedules = Schedule.all
end
def update
end
def delete
end
Private
def schedule_params
params.require(:schedule).permit(:note_id, :user_id, :params[:id])
end
def set_schedule
#schedule = Schedule.find(params[:id])
end
end
params
=> "31", "controller"=>"schedules", "action"=>"new"} permitted: false>
You are not even using shedule_params values, as you override them afterwards ......
Then you could create empty Schedule object and then assign values ...
def create
#schedule = Schedule.new
#schedule.user_id = current_user.id
#schedule.note_id = params[:id]
if #schedule.save
redirect_to schedules_path, notice: "A schedule was saved!"
end
end
Or if I am correct with your relations, it could be also
def create
#schedule = current_user.schedules.new
#schedule.note_id = params[:id]
if #schedule.save
redirect_to schedules_path, notice: "A schedule was saved!"
end
end
I could solve this problem as follow.
Controller:
def new
#schedule = Schedule.new
#schedule.note_id = params[:id]
end
def create
#schedule = Schedule.new(schedule_params)
#schedule.user_id = current_user.id
if #schedule.save
redirect_to schedules_path, notice: "A schedule was saved!"
else
render 'new'
end
end
.
.
.
Private
def schedule_params
params.require(:schedule).permit(:note_id, :user_id)
end
Add into View
<%= f.hidden_field :id, :value => #schedule.note_id %>

Undefined Method Error in controller

models/collaborators.rb:
class Collaborator < ActiveRecord::Base
belongs_to :user
belongs_to :wiki
def wiki_collaborations
end
end
controllers/wikis_controller.rb:
class WikisController < ApplicationController
def index
#user = current_user
if #user.admin?
#wikis = Wiki.all
elsif #user.premium?
#wikis = Wiki.where(private: false) | #user.wiki_collaborations | #user.wikis
elsif #user.standard?
#wikis = Wiki.where(private: false) | #user.wiki_collaborations
else
#wikis = Wiki.where(private: false)
end
end
def show
#wiki = Wiki.find(params[:id])
authorize #wiki
end
def new
#wiki = Wiki.new
end
def create
#wiki = current_user.wikis.new(wiki_params)
if #wiki.save
flash[:notice] = "Wiki was saved."
redirect_to #wiki
else
flash.now[:alert] = "There was an error saving the wiki. Please try again."
render :new
end
end
def edit
#user = current_user
#wiki = Wiki.find(params[:id])
#user_emails = User.where.not(id: current_user.id || #wiki.users.pluck(:id)).map(&:email)
authorize #wiki
end
def update
#wiki = Wiki.find(params[:id])
authorize #wiki
if #wiki.update(wiki_params)
flash[:notice] = "Wiki was updated."
redirect_to #wiki
else
flash.now[:alert] = "There was an error saving the wiki page. Please try again."
render :edit
end
end
def destroy
#wiki = Wiki.find(params[:id])
if #wiki.destroy
flash[:notice] = "\"#{#wiki.title}\" was deleted successfully."
redirect_to wikis_path
else
flash.now[:alert] = "There was an error deleting the wiki page."
render :show
end
end
private
def wiki_params
params.require(:wiki).permit(:title, :body, :private)
end
end
I tried to access http://localhost:3000/wikis.
I get the following error.
Possibly you've not defined wiki_collaborations method for user.
You can delegate it to User like,
class User < ActiveRecord::Base
delegate :wiki_collaborations, to: :collaborator
end
Btw, be aware of | is not same as ||.

Ruby: If last variable was saved more than 3 hours ago

I have a ruby form to submit reports for an exercise on my app. An exercise has_many reports. I want to create an if statement that makes this form only appear if the last report from that exercise was saved more than 3 hours ago.
So far I have:
But this is creating a NoMethodError saying undefined method 'report' for #<Exercise:0x007f9c892f48b0>.
It's being displayed on my workouts#show page (a workout has_many exercises, in case it helps), so I believe this is the reigning controller:
class WorkoutsController < ApplicationController
def index
#workouts = Workout.all
end
def show
#workout = Workout.find(params[:id])
#exercise = Exercise.new
#report = Report.new
end
def new
#workout = Workout.new
#workout.user_id = current_user
end
def create
#workout = Workout.new(workout_params)
#workout.user = current_user
if #workout.save
flash[:notice] = "Workout was saved successfully."
redirect_to #workout
else
flash.now[:alert] = "Error creating workout. Please try again."
render :new
end
end
def edit
#workout = Workout.find(params[:id])
end
def update
#workout = Workout.find(params[:id])
#workout.name = params[:workout][:name]
#workout.workout_type = params[:workout][:workout_type]
#workout.teaser = params[:workout][:teaser]
#workout.description = params[:workout][:description]
#workout.video = params[:workout][:video]
#workout.difficulty = params[:workout][:difficulty]
#workout.trainer = params[:workout][:trainer]
#workout.user_id = params[:workout][:user_id]
if #workout.save
flash[:notice] = "Workout was updated successfully."
redirect_to #workout
else
flash.now[:alert] = "Error saving workout. Please try again."
render :edit
end
end
def destroy
#workout = Workout.find(params[:id])
if #workout.destroy
flash[:notice] = "\"#{#workout.name}\" was deleted successfully."
redirect_to action: :index
else
flash.now[:alert] = "There was an error deleting the workout."
render :show
end
end
private
def workout_params
params.require(:workout).permit(:name, :workout_type, :teaser, :description, :video, :difficulty, :trainer, :user_id)
end
end
Any ideas where I'm going wrong?
ADDITIONAL INFORMATION:
This bit is technically on my workouts#show page:
<% if #workout.exercises.count == 0 %>
<p>Looks like you get a freebie for this one! No score report today. Rest up and drink some water. It ain't always that easy...</p>
<% else %>
<% #workout.exercises.each do |exercise| %>
<%= render 'reports/form', report: #report, exercise: exercise %>
<% if current_user.admin? %>
<div class="text-center"><%= link_to "Delete #{exercise.name}", [exercise], method: :delete, data: { confirm: 'Are you sure?' } %></div>
<% end %>
<hr>
<% end %>
But here is the partial it renders, where the code in question actually lies:
<% if exercise.report.last != nil && exercise.report.last.created_at < ( DateTime.now - (3/24.0)) %>
<%= form_for report,
:url => { :controller => "reports",
:action => :create,
:exercise_id => exercise.id } do |f| %>
<div class="row">
...
It seems you calling singularized report instead of reports.
if exercise.report.last
If reports relates to exercise as has_many you need to call it with exercise.reports.last
Also, you mentioned results in your question, but calling reports in your view.
An exercise has_many results.
...
exercise.report.last
Please be sure you calling appropriate pluralize method reports or results

Ruby on Rails: :topic_id=>nil, I'm lost

So I am working on an assignment at the moment, where I am trying to display favorited posts. I currently have the favorited post displayed, but when I click it, it doesn't doesn't redirect me to anywhere.
Here is the code I currently have:
User#show where I am currently trying to display the favorited posts:
<div class="row">
<div class="col-md-8">
<div class="media">
<br />
<% avatar_url = #user.avatar_url(128) %>
<% if avatar_url %>
<div class="media-left">
<%= image_tag avatar_url, class: 'media-object' %>
</div>
<% end %>
<div class="media-body">
<h2 class="media-heading"><%= #user.name %></h2>
<small>
<%= pluralize(#user.posts.count, 'post') %>,
<%= pluralize(#user.comments.count, 'comment') %>
</small>
</div>
</div>
</div>
</div>
<h2>Posts</h2>
<%= posts_exists? %>
<%= render #user.posts %>
<h2>Comments</h2>
<%= comments_exists? %>
<%= render #user.comments %>
<h2>Favorites</h2>
<% #posts.each do |post| %>
<%= render partial: 'votes/voter', locals: { post: post } %>
<%= link_to post.title, topic_post_path(#topic, post) %>
<%= image_tag current_user.avatar_url(48), class: "gravatar" %>
<%= post.comments.count %> Comments
<% end %>
The error is occuring on the following line:
<%= link_to post.title, topic_post_path(#topic, post) %>
Here is the output from the error:
ActionView::Template::Error (No route matches {:action=>"show", :controller=>"posts", :id=>"54", :topic_id=>nil} missing required keys: [:topic_id]):
29: <h2>Favorites</h2>
30: <% #posts.each do |post| %>
31: <%= render partial: 'votes/voter', locals: { post: post } %>
32: <%= link_to post.title, topic_post_path(#topic, post) %>
33: <%= image_tag current_user.avatar_url(48), class: "gravatar" %>
34: <%= post.comments.count %> Comments
35: <% end %>
app/views/users/show.html.erb:32:in `block in _app_views_users_show_html_erb__1919900632491741904_70127642538380'
app/views/users/show.html.erb:30:in `_app_views_users_show_html_erb__1919900632491741904_70127642538380'
Obviously Topid.id is nil, but I can't figure out why. I'm going to provide you with everything I think you could need? I know this is probably a simple nooby issue, but I've been stuck on it for nearly an entire day already.
Here is my User#Controller:
class UsersController < ApplicationController
def new
#user = User.new
end
def create
#user = User.new
#user.name = params[:user][:name]
#user.email = params[:user][:email]
#user.password = params[:user][:password]
#user.password_confirmation = params[:user][:password_confirmation]
if #user.save
flash[:notice] = "Welcome to Bloccit #{#user.name}!"
create_session(#user)
redirect_to root_path
else
flash[:error] = "There was an error creating your account. Please try again."
render :new
end
end
def show
#user = User.find(params[:id])
#posts = #user.posts.visible_to(current_user)
#posts = Post.joins(:favorites).where('favorites.user_id = ?', #user.id)
#favorites = current_user.favorites
end
end
Here is my Post#Controller:
class PostsController < ApplicationController
before_action :require_sign_in, except: :show
before_action :authorize_user, except: [:show, :new, :create]
def show
#post = Post.find(params[:id])
end
def new
#topic = Topic.find(params[:topic_id])
#post = Post.new
end
def create
#topic = Topic.find(params[:topic_id])
#post = #topic.posts.build(post_params)
#post.user = current_user
if #post.save
#post.labels = Label.update_labels(params[:post][:labels])
flash[:notice] = "Post was saved."
redirect_to [#topic, #post]
else
flash[:error] = "There was an error saving the post. Please try again."
render :new
end
end
def edit
#post = Post.find(params[:id])
end
def update
#post = Post.find(params[:id])
#post.assign_attributes(post_params)
if #post.save
#post.labels = Label.update_labels(params[:post][:labels])
flash[:notice] = "Post was updated."
redirect_to [#post.topic, #post]
else
flash[:error] = "There was an error saving the post. Please try again."
render :edit
end
end
def destroy
#post = Post.find(params[:id])
if #post.destroy
flash[:notice] = "\"#{#post.title}\" was deleted successfully."
redirect_to #post.topic
else
flash[:error] = "There was an error deleting the post."
render :show
end
end
private
def post_params
params.require(:post).permit(:title, :body)
end
def authorize_user
post = Post.find(params[:id])
unless current_user == post.user || current_user.admin?
flash[:error] = "You must be an admin to do that."
redirect_to [post.topic, post]
end
end
end
Here is my Topics#Controller:
class TopicsController < ApplicationController
before_action :require_sign_in, except: [:index, :show]
before_action :authorize_user, except: [:index, :show]
def index
#topics = Topic.all
end
def show
#topic = Topic.find(params[:id])
end
def new
#topic = Topic.new
end
def create
#topic = Topic.new(topic_params)
if #topic.save
#topic.labels = Label.update_labels(params[:topic][:labels])
redirect_to #topic, notice: "Topic was saved successfully."
else
flash[:error] = "Error creating topic. Please try again."
render :new
end
end
def edit
#topic = Topic.find(params[:id])
end
def update
#topic = Topic.find(params[:id])
#topic.assign_attributes(topic_params)
if #topic.save
#topic.labels = Label.update_labels(params[:topic][:labels])
flash[:notice] = "Topic was updated."
redirect_to #topic
else
flash[:error] = "Error saving topic. Please try again."
render :edit
end
end
def destroy
#topic = Topic.find(params[:id])
if #topic.destroy
flash[:notice] = "\"#{#topic.name}\" was deleted successfully."
redirect_to action: :index
else
flash[:error] = "There was an error deleting the topic."
render :show
end
end
private
def topic_params
params.require(:topic).permit(:name, :description, :public)
end
def authorize_user
unless current_user.admin?
flash[:error] = "You must be an admin to do that."
redirect_to topics_path
end
end
end
Here is my User Model:
class User < ActiveRecord::Base
has_many :posts, dependent: :destroy
has_many :comments, dependent: :destroy
has_many :votes, dependent: :destroy
has_many :favorites, dependent: :destroy
before_save { self.email = email.downcase }
before_save { self.role ||= :member }
EMAIL_REGEX = /\A[\w+\-.]+#[a-z\d\-.]+\.[a-z]+\z/i
validates :name, length: { minimum: 1, maximum: 100 }, presence: true
validates :password, presence: true, length: { minimum: 6 }, if: "password_digest.nil?"
validates :password, length: { minimum: 6 }, allow_blank: true
validates :email,
presence: true,
uniqueness: { case_sensitive: false },
length: { minimum: 3, maximum: 100 },
format: { with: EMAIL_REGEX }
has_secure_password
enum role: [:member, :admin]
def favorite_for(post)
favorites.where(post_id: post.id).first
end
def avatar_url(size)
gravatar_id = Digest::MD5::hexdigest(self.email).downcase
"http://gravatar.com/avatar/#{gravatar_id}.png?s=#{size}"
end
end
Here is my Topic Model:
class Topic < ActiveRecord::Base
has_many :posts, dependent: :destroy
has_many :labelings, as: :labelable
has_many :labels, through: :labelings
end
Here is my Post Model:
class Post < ActiveRecord::Base
belongs_to :topic
belongs_to :user
has_many :comments, dependent: :destroy
has_many :votes, dependent: :destroy
has_many :labelings, as: :labelable
has_many :labels, through: :labelings
has_many :favorites, dependent: :destroy
default_scope { order('rank DESC') }
scope :visible_to, -> (user) { user ? all : joins(:topic).where('topics.public' => true) }
validates :title, length: { minimum: 5 }, presence: true
validates :body, length: { minimum: 20 }, presence: true
validates :topic, presence: true
validates :user, presence: true
def up_votes
votes.where(value: 1).count
end
def down_votes
votes.where(value: -1).count
end
def points
votes.sum(:value)
end
def update_rank
age_in_days = (created_at - Time.new(1970,1,1)) / 1.day.seconds
new_rank = points + age_in_days
update_attribute(:rank, new_rank)
end
end
Any insight anyone could provide, I would be extremely grateful for. If you have the time to explain where I went wrong as well, that would be even more helpful.
User#show where I am currently trying to display the favorited posts
But you're not setting #topic in your User#show action. That's why it's nil.
def show
#user = User.find(params[:id])
#posts = #user.posts.visible_to(current_user)
#posts = Post.joins(:favorites).where('favorites.user_id = ?', #user.id)
#favorites = current_user.favorites
# your #topic object is not in here?
end
Since a post belongs_to a topic you could do something like this:
<%= link_to post.title, topic_post_path(post.topic, post) %>

ActionController::ParameterMissing param is missing or the value is empty

I can't solve this problem.
When I try to use "Chatroom#new" method, I I got this error, ActionController::ParameterMissing param is missing or the value is empty .
below codes are the ChatroomController.
class ChatroomsController < ApplicationController
before_action :find_room_owner,only:[:index]
before_action :objects_for_index,only:[:index]
def index
#/users/:user_id/cart/items/chatroom
sign_in #user if signed_in?
if #seller && #buyer
flash[:success] = "U are owners of the chatroom"
#messages = Message.all #Messageのmodelを作成
else
flash[:error] = "U cant enter the chatroom."
redirect_to user_cart_items_url(#user,#cart,#items) ##user,#cart,#itemsをgetしろ
end
end
def new
#user = User.find(params[:user_id])
#cart = Cart.find(params[:user_id])
#item = Item.find(params[:item_id])
#message = Message.new(message_params)
end
def create
#user = User.find(params[:user_id])
#message = #user.messages.build
if #message.save
#message.update_attributes(user_id:#user.id)
redirect_to user_cart_chatroom_path(#user,#cart,#items)
else
flash[:error] = "could not create any message."
render 'new'
end
end
private
def message_params
params.require(:messages).permit(:id,:user_id,:messages)
#params{:message => :id,:user_id,:messages}
end
#before_aciton
def find_room_owner
#item = Item.find(params[:item_id])
#buyer = User.find(params[:user_id])
#seller = Product.find_by(user_id:#item.user_id)
end
def objects_for_index
#user = User.find(params[:user_id])
#items = Item.all
end
end
Below codes are the view of Message#new.
<h1>Chatroom#new</h1>
<p>Find me in app/views/chatroom/new.html.erb</p>
<%= form_for #message,url:new_user_cart_item_chatroom_path(#user,#cart,#item) do |f| %>
<%= f.label :messages %>
<%= f.text_field :messages %>
<%= f.submit "new message", class:"btn btn-default" %>
<% end %>
Below codes are the migration of Message.
class CreateMessages < ActiveRecord::Migration
def change
create_table :messages do |t|
t.integer :user_id
t.string :messages
t.timestamps
end
end
end
Below codes are the model of message.
class Message < ActiveRecord::Base
validates :messages,presence:true,length:{maximum:200}
belongs_to :user
end
Below codes are the routes.
KaguShop::Application.routes.draw do
resources :users,only:[:show,:new,:create,:edit,:update,:destroy] do
collection do
get 'get_images',as:'get_images'
end
resources :products,only:[:show,:index,:new,:create,:edit,:update,:destroy] do
collection do
post 'add_item', as:'add_item'
get 'get_image',as:'get_image'
get 'get_images',as:'get_images'
end
end
end
resources :users,only:[:show,:new,:create,:edit,:update,:destroy] do
resource :cart,except:[:new,:show,:edit,:destroy,:update,:create] do
collection do
post 'purchase', as:'purchase'
#get 'show' , as: 'show'
post 'create' , as: 'create'
#多分routeにas的な感じでtemplateを提供するのが一番いい気がする
delete 'destroy',as:'destroy'
delete 'remove_item',as:'remove_item'
end
resources :items,only:[:show,:index] do
collection do
get 'get_images',as:'get_images'
end
resources :chatrooms,only:[:index,:create,:new] do
end
end
end
end
resources :sessions,only:[:new,:create,:destroy]
root 'products#index'
match '/signup', to:'users#new',via:'get'
match '/signin', to:'sessions#new', via:'get'
match '/signout', to:'sessions#destroy', via:'delete'
match '/contact', to:'nomal_pages#contact', via:'get'
end
You should call Message.new without params because message_params nil in this request and this raise ActionController::ParameterMissing:
class ChatroomsController < ApplicationController
#.........
def new
#user = User.find(params[:user_id])
#cart = Cart.find(params[:user_id])
#item = Item.find(params[:item_id])
#message = Message.new
end
#........
private
def message_params
params.require(:messages).permit(:id,:user_id,:messages)
end
#.......
end

Resources