Ruby: If last variable was saved more than 3 hours ago - ruby-on-rails

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

Related

Rails: How not to save value with using time_select

I'm trying to add time_select with include_blank. I'm doing this:
<%= f.time_select :start_at, include_blank: true, ampm: true %><br>
What I'd like to do is to delete value (save nil?) if blank is selected in view.
Although I tried the following posts, it didn't work for me.
time_select blank field saves a default time when form is submitted
Optional time_select with allow_blank defaults to 00:00
1) When I try as below, no error is appeared, but 00:00:00 is saved.
controller
def update
#event = Event.find(params[:id])
if event_params["start_at(4i)"].blank? or event_params["start_at(5i)"].blank?
#event.start_at = nil
end
if #event.update(event_params)
flash[:success] = "event updated!"
redirect_to root_url
else
render 'edit'
end
end
2) When I try as below (change if clause), no error is appeared, but 00:00:00 is saved.
controller
def update
#event = Event.find(params[:id])
if params[:id]["start_at(4i)"].blank? or params[:id]["start_at(5i)"].blank?
#event.start_at = nil
end
if #event.update(event_params)
flash[:success] = "event updated!"
redirect_to root_url
else
render 'edit'
end
end
3) When I try as below (add before_action), no error is appeared, but 00:00:00 is saved.
controller
before_action :blank_time, only: [:update]
def update
#event = Event.find(params[:id])
if #event.update(event_params)
flash[:success] = "event updated!"
redirect_to root_url
else
render 'edit'
end
end
private
def blank_time
if params[:id]["start_at(4i)"].blank? or params[:id]["start_at(5i)"].blank?
params[:id]['start_at(1i)'] = ""
params[:id]["start_at(2i)"] = ""
params[:id]["start_at(3i)"] = ""
params[:id]["start_at(4i)"] = ""
params[:id]["start_at(5i)"] = ""
end
end
4) When I try as below (use nil instead of ""), error is appeared.
error
IndexError (string not matched):
app/controllers/events_controller.rb:106:in `[]='
app/controllers/events_controller.rb:106:in `blank_time'
controller
before_action :blank_time, only: [:update]
def update
#event = Event.find(params[:id])
if #event.update(event_params)
flash[:success] = "event updated!"
redirect_to root_url
else
render 'edit'
end
end
private
def blank_time
if params[:id]["start_at(4i)"].blank? or params[:id]["start_at(5i)"].blank?
params[:id]['start_at(1i)'] = nil
params[:id]["start_at(2i)"] = nil
params[:id]["start_at(3i)"] = nil
params[:id]["start_at(4i)"] = nil
params[:id]["start_at(5i)"] = nil
end
end
It would be appreciated if you could give me any advice.
UPDATE
Although I change the edit in events_controller.rb as below, the error ActiveModel::MissingAttributeError (can't write unknown attribute 'start_at(4i)'): is displayed.
def edit
#room = Room.find(params[:room_id])
#event = #room.events.find(params[:id])
#event['start_at(4i)'] = #event.start_at.split(':')[0] #the error occur here
#event['start_at(5i)'] = #event.start_at.split(':')[1]
end
My idea works like this:
Migration:
class CreateTests < ActiveRecord::Migration[5.0]
def change
create_table :tests do |t|
t.string :time
t.timestamps
end
end
end
Form:
<%= form_for(test) do |f| %>
<% if test.errors.any? %>
<div id="error_explanation">
<h2><%= pluralize(test.errors.count, "error") %> prohibited this test from being saved:</h2>
<ul>
<% test.errors.full_messages.each do |message| %>
<li><%= message %></li>
<% end %>
</ul>
</div>
<% end %>
<div class="field">
<%= f.label :time %>
<%= f.time_select :time, include_blank: true, ampm: false %><br>
</div>
<div class="actions">
<%= f.submit %>
</div>
<% end %>
Controller:
This will save : when value send are null where you can use conditional to check if parameters are null or and set value of time. //It's consuming much time and I skipped for you to complete.
def create
#test = Test.new(test_params)
#time = (params[:test]['time(4i)']).to_s
#time_ampm = (params[:test]['time(5i)']).to_s
#test.time = #time+":"+ #time_ampm
respond_to do |format|
if #test.save
format.html { redirect_to #test, notice: 'Test was successfully created.' }
format.json { render :show, status: :created, location: #test }
else
format.html { render :new }
format.json { render json: #test.errors, status: :unprocessable_entity }
end
end
end
For updating
def edit
#test = Test.find(params[:id])
#test['time(4i)'] = #test.time.split(':')[0]
#test['time(5i)'] = #test.time.split(':')[1]
end
def update
#test = Test.find(params[:id])
#time = (params[:test]['time(4i)']).to_s
#time_ampm = (params[:test]['time(5i)']).to_s
#test.time = #time+":"+ #time_ampm
#test.update(test_params)
end
Assigning #event.starts_at to nil does nothing as the attributes in #event_params is used when calling #update, overwriting your initial assignment.
Overwriting the starts_at attribute in your params should work instead.
def update
#event = Event.find(params[:id])
if event_params["start_at(4i)"].blank? or event_params["start_at(5i)"].blank?
event_params = event_params.reject { |k, v| k.starts_with? 'starts_at' }
.merge(starts_at: nil)
end
if #event.update(event_params)
flash[:success] = "event updated!"
redirect_to root_url
else
render 'edit'
end
end
The following line finds and remove the parameters for starts_at(1i) to starts_at(5i), then sets the whole starts_at attribute to be nil:
event_params.reject { |k, v| k.starts_with? 'starts_at' }.merge(starts_at: nil)

Undefined Method `stringify_keys' for Model's Show Page

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>

undefined method `picture' for nil:NilClass using carrierwave

I am making a form in my rails application where people have the option of adding images and I am using 'carrierwave' but I am getting an undefined method error on the edit page. Here is the code for the form:
<%= title "Add Item to #{#todo_list.title}" %>
<%= form_for [#todo_list, #todo_item], builder: FoundationFormBuilder do |form| %>
<%= render partial: 'form', locals: { form: form } %>
<%= form.file_field :picture %>
<% end %>
Here I can see the upload button and it is working fine but on the edit page I get the above stated error. Code for my edit page:
<%= title "Editing Todo Item" %>
<%= form_for [#todo_list, #todo_item], builder: FoundationFormBuilder do |form| %>
<%= render partial: 'form', locals: { form: form } %>
<% end %>
<div class="row">
<div class="small-12 columns">
<%= link_to "Delete", todo_list_todo_item_path(#todo_list, #todo_item), method: :delete, data: { confirm: "Are you sure?" }, class: "button radius expand alert" %>
</div>
<%= #todo_item.picture %>
</div>
Why is this showing an undefined method error. I tried creating a method in my todo_item model but its still showing the above error.
Controller for todo_item:
class TodoItemsController < ApplicationController
before_action :require_user
before_action :find_todo_list
before_action :set_back_link, except: [:index]
def index
go_back_link_to todo_lists_path
end
def new
#todo_item = #todo_list.todo_items.new
end
def create
#todo_item = #todo_list.todo_items.new(todo_item_params)
if #todo_item.save
flash[:success] = "Added todo list item."
redirect_to todo_list_todo_items_path
else
flash[:error] = "There was a problem adding that todo list item."
render action: :new
end
end
def edit
#todo_item = #todo_list.todo_items.find(params[:id])
end
def update
#todo_item = #todo_list.todo_items.find(params[:id])
if #todo_item.update_attributes(todo_item_params)
flash[:success] = "Saved todo list item."
redirect_to todo_list_todo_items_path
else
flash[:error] = "That todo item could not be saved."
render action: :edit
end
end
def destroy
#todo_item = #todo_list.todo_items.find(params[:id])
if #todo_item.destroy
flash[:success] = "Todo list item was deleted."
else
flash[:error] = "Todo list item could not be deleted."
end
redirect_to todo_list_todo_items_path
end
def complete
#todo_item = #todo_list.todo_items.find(params[:id])
#todo_item.toggle_completion!
redirect_to todo_list_todo_items_path, notice: "Todo item updated."
end
def url_options
{ todo_list_id: params[:todo_list_id] }.merge(super)
end
private
def set_back_link
go_back_link_to todo_list_todo_items_path(#todo_list)
end
def find_todo_list
#todo_list = current_user.todo_lists.find(params[:todo_list_id])
end
def todo_item_params
params[:todo_item].permit(:content)
end
end
To display your image you should change
<%= #todo_item.picture %>
to
<%= image_tag(#todo_item.picture_url) %>

undefined method `accepted_user_friendships'

NoMethodError in UserFriendshipsController#index
undefined method `accepted_user_friendships'
I'm getting the above error message when clicking on the 'accepted' link within my index.html page. All the other links function properly except this one. Thanks in advance. Any help is greatly appreciated.
user_friendships_controller
class UserFriendshipsController < ApplicationController
before_filter :authenticate_user!
respond_to :html, :json
def index
#user_Friendships = UserFriendshipDecorator.decorate_collection(friendship_association.all)
respond_with #user_Friendships
end
def accept
#user_friendship = current_user.user_friendships.find(params[:id])
if #user_friendship.accept_mutual_friendship!
#user_friendship.friend.user_friendships.find_by(friend_id: current_user.id).accept_mutual_friendship!
flash[:success] = "You are now friends with #{#user_friendship.friend.name}!"
redirect_to user_friendships_path
else
flash[:error] = "That friendship could not be accepted."
end
end
def block
#user_friendship = current_user.user_friendships.find(params[:id])
if #user_friendship.block!
flash[:success] = "You have blocked #{#user_friendship.friend.name}."
else
flash[:error] = "This friendship could not be blocked."
end
redirect_to user_friendships_path
end
def new
if params[:friend_id]
#friend = User.find(params[:friend_id]).first
raise ActiveRecord::RecordNotFound if #friend.nil?
#user_friendship = current_user.user_friendships.new(friend: #friend)
else
flash[:error] = "Friend required."
end
rescue ActiveRecord::RecordNotFound
render file: 'public/404', status: :not_found
end
def create
if params[:user_friendship] && params[:user_friendship].has_key?(:friend_id)
#friend = User.find(params[:user_friendship][:friend_id])
#user_friendship = UserFriendship.request(current_user, #friend)
respond_to do |format|
if #user_friendship.new_record?
format.html do
flash[:error] = "There was a problem creating this friend request."
redirect_to user_path(#friend)
end
format.json { render json: #user_friendship.to_json, status: :precondition_failed }
else
format.html do
flash[:success] = "Friend request sent."
redirect_to user_path(#friend)
end
format.json { render json: #user_friendship.to_json }
end
end
else
flash[:error] = "Friend required"
redirect_to root_path
end
end
def edit
#friend = User.find(params[:id])
#user_friendship = current_user.user_friendships.find_by(friend_id: #friend.id).decorate
end
def destroy
#user_friendship = current_user.user_friendships.find(params[:id])
if #user_friendship.destroy
flash[:success] = "Your friendship was deleted"
end
redirect_to user_friendships_path
end
def user_friendship
params.require(:user_friendship).permit(:user_id, :friend_id, :user, :friend, :state, :user_friendship)
end
private
def friendship_association
case params[:list]
when nil
current_user.user_friendships
when 'blocked'
current_user.blocked_user_friendships
when 'pending'
current_user.pending_user_friendships
when 'accepted'
current_user.accepted_user_friendships
when 'requested'
current_user.requested_user_friendships
end
end
end
Index.html
<div class="page-header">
<h1> Friends </h1>
</div>
<div>
<strong>Friend list:</strong>
<%= link_to 'Accepted', user_friendships_path(list: 'accepted') %>
<%= link_to 'Pending', user_friendships_path(list: 'pending') %>
<%= link_to 'Requested', user_friendships_path(list: 'requested') %>
<%= link_to 'Blocked', user_friendships_path(list: 'blocked') %>
</div>
<% #user_Friendships.each do |friendship| %>
<% friend = friendship.friend %>
<div id="<%= dom_id(friendship) %>" class="friend row">
<div class="span1">
</div>
<div class="span7">
<strong><%= friend.name %></strong><br />
<%if friendship.pending? %>
<em>Friendship is pending.</em> <%=link_to "Delete request", edit_user_friendship_path(friendship.friend) %>.
<% end %>
<% if friendship.requested? %>
<em>Friendship requested.</em> <%=link_to "Accept Friendship", edit_user_friendship_path(friendship.friend) %>.
<% end %>
<% if friendship.accepted? %>
<em>Friendship started <%= friendship.updated_at %>.</em> <%= link_to "Update friendship", edit_user_friendship_path(friendship.friend) %>.
<% end %>
</div>
</div>
<% end %>
Problem solved. I forgot to add the below code into my user model. That was a complete miss on my part.
has_many :accepted_user_friendships, class_name: 'UserFriendship',
foreign_key: :user_id,
conditions: { state: 'accepted' }
has_many :accepted_friends, through: :pending_user_friendships, source: :friend

RoR : You have a nil object you did not expect

Been Facing this issue,I Have as my view
<%= form_for(:pin, :url => {:action =>"fees"}) do |f| %>
<%= f.text_field :pin_no %>
<%= f.submit "Check Pin" , :class => "new_button round" %>
<% end %>
and in my controller i have
def fees
#title = "Pay Fees"
pin = Pin.check_pin(params[:pin][:pin_no])
if pin.nil?
flash.now[:error] = "Pin is not Avaliable"
render 'fees'
else
flash.now[:success] = "Pin Avaliable"
end
end
in my model, i have a check_pin method defined thus
def check_pin(pin_to_check)
pin = find_by_pin_no(pin_to_check)
if pin.nil?
nil
else
pin
end
end
and i always have this error
You have a nil object when you didn't expect it!
You might have expected an instance of Array.
The error occurred while evaluating nil.[]
what am i missing here please?
You get params[:pin][:pin_no] only when you post the form so it is giving error nil.[] so add request.post? to check it only when form is post
def fees
#title = "Pay Fees"
if request.post?
pin = Pin.check_pin(params[:pin][:pin_no])
if pin.nil?
flash.now[:error] = "Pin is not Avaliable"
render 'fees'
else
flash.now[:success] = "Pin Avaliable"
end
end
end
What if you try to simplify it a bit and scrap the check pin method and just do this:
def fees
#title = "Pay Fees"
if p = Pin.find_by_pin_no params[:pin][:pin_no]
flash.now[:success] = "Pin: #{p} is Avaliable"
else
flash.now[:error] = "Pin is not Avaliable"
render 'fees'
end
end

Resources