I've been searching these forums for the passed 2 days and finally given up. I've been working on a rails app where you can upload workouts, and then have other view them and download any attached excel files. My form looks like this
'<div class="form-group">
<div class="control-label col-md-2">
<%= f.label :name, "Workout name" %><br>
</div>
<div class="col-md-10">
<%= f.text_field :name, class: "form-control" %>
</div>
</div>
<div class="form-group">
<div class="control-label col-md-2">
<%= f.label :summary, "Summary", placeholder: "Who's this for? what experience level? Athletes or Bodybuilders etc" %>
</div>
<div class="col-md-10">
<%= f.text_area :summary, class: "form-control", rows: 10%>
</div>
</div>
<div class="clearfix">
<div class="col-lg-3 col-md-6">
<%= f.label :Movement %>
<%= f.fields_for :movements do |movement| %>
<%= render 'movement_fields', f: movement %>
<% end %>
<div class="links">
<%= link_to_add_association 'Add movement', f, :movements, class: "pull-right d-inline-block btn btn-primary add-button" %>
</br>
</br>
</div>
</div>
<div class="col-lg-3 col-md-6">
<%= f.label :Reps %>
<%= f.fields_for :reps do |rep| %>
<%= render 'rep_fields', f: rep %>
<% end %>
<div class="links">
<%= link_to_add_association 'Add Reps', f, :reps, class: "pull-right d-inline-block btn btn-primary add-button" %>
</br>
</br>
</div>
</div>
<div class="col-lg-3 col-md-6">
<%= f.label :Sets %>
<%= f.fields_for :zets do |zet| %>
<%= render 'zet_fields', f: zet %>
<% end %>
<div class="links">
<%= link_to_add_association 'Add Set', f, :zets, class: "pull-right d-inline-block btn btn-primary add-button" %>
</div>
</br>
</br>
</div>
<div class="col-lg-3 col-md-6">
<%= f.label :Weights %>
<%= f.fields_for :weights do |weight| %>
<%= render 'weight_fields', f: weight %>
<% end %>
<div class="links">
<%= link_to_add_association 'Add weight', f, :weights, class: "pull-right d-inline-block btn btn-primary add-button" %>
</div>
</br>
</br>
</div>
<strong>Upload image: </strong>
<span class="picture">
<%= f.file_field :attachment %>
</span>
</div>
<div class="form-group">
<div class="col-md-offset-2 col-md-10">
<%= f.submit class: "btn btn-success btn-lg" %>
</div>
</div>
<% end %>
</div>
</div>
</div>`
Which seems to upload everything i need to the database, because when i go through the entries it seems to have the data i need i.e workout_id attached to a movement etc.
Heres the schema.rb
# Deleted some other columns in this that are in the app that aren't relevant to the post to reduce the amount of text. Exercises column is from another element in the app that works that i used basically the exact same method in creating.
ActiveRecord::Schema.define(version: 20161113011850) do
create_table "exercises", force: :cascade do |t|
t.integer "duration_in_min"
t.text "workout"
t.date "workout_date"
t.integer "user_id"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
end
add_index "exercises", ["user_id"], name: "index_exercises_on_user_id"
create_table "movements", force: :cascade do |t|
t.string "name"
t.integer "exercise_id"
t.integer "workout_id"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.integer "workout_id"
end
add_index "movements", ["exercise_id"], name: "index_movements_on_exercise_id"
add_index "movements", ["workout_id"], name: "index_movements_on_workout_id"
create_table "reps", force: :cascade do |t|
t.integer "amount"
t.integer "exercise_id"
t.integer "workout_id"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
end
add_index "reps", ["exercise_id"], name: "index_reps_on_exercise_id"
add_index "reps", ["workout_id"], name: "index_reps_on_workout_id"
create_table "reviews", force: :cascade do |t|
t.text "body"
t.integer "user_id"
t.integer "recipe_id"
t.datetime "created_at"
t.datetime "updated_at"
end
create_table "users", force: :cascade do |t|
t.string "username"
t.string "email", default: "", null: false
t.string "encrypted_password", default: "", null: false
t.string "reset_password_token"
t.datetime "reset_password_sent_at"
t.datetime "remember_created_at"
t.integer "sign_in_count", default: 0, null: false
t.datetime "current_sign_in_at"
t.datetime "last_sign_in_at"
t.string "current_sign_in_ip"
t.string "last_sign_in_ip"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.string "first_name"
t.string "last_name"
t.boolean "admin", default: false
end
add_index "users", ["email"], name: "index_users_on_email", unique: true
add_index "users", ["reset_password_token"], name: "index_users_on_reset_password_token", unique: true
create_table "weights", force: :cascade do |t|
t.integer "kilogram"
t.integer "workout_id"
t.integer "exercise_id"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
end
add_index "weights", ["exercise_id"], name: "index_weights_on_exercise_id"
add_index "weights", ["workout_id"], name: "index_weights_on_workout_id"
create_table "workouts", force: :cascade do |t|
t.string "name"
t.text "summary"
t.integer "user_id"
t.string "attachment"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.integer "duration_in_min"
end
create_table "zets", force: :cascade do |t|
t.integer "quantity"
t.integer "exercise_id"
t.integer "workout_id"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
end
add_index "zets", ["exercise_id"], name: "index_zets_on_exercise_id"
add_index "zets", ["workout_id"], name: "index_zets_on_workout_id"
end
And the model workout.rb
class Workout < ActiveRecord::Base belongs_to :user mount_uploader :attachment, AttachmentUploader
has_many :movements
has_many :reps
has_many :zets
has_many :weights
accepts_nested_attributes_for :movements,
reject_if: proc { |attributes| attributes['name'].blank? },
allow_destroy: true
accepts_nested_attributes_for :reps,
reject_if: proc { |attributes| attributes['amount'].blank? },
allow_destroy: true
accepts_nested_attributes_for :zets,
reject_if: proc { |attributes| attributes['quantity'].blank? },
allow_destroy: true
accepts_nested_attributes_for :weights,
reject_if: proc { |attributes| attributes['kilogram'].blank? },
allow_destroy: true
validates :name, presence: true
validates :summary, presence: true
validates :movements, presence: true
validates :reps, presence: true
validates :zets, presence: true
validates :weights, presence: true
end
and the controller workouts_controller.rb
class WorkoutsController < ApplicationController
before_action :set_workout, only: [:edit, :update, :show, :like, :review]
before_action :authenticate_user!, except: [:show, :index, :like, :search]
before_action :require_same_user, only: [:edit, :update]
before_action :admin_user, only: :destroy
def index
@workouts = Workout.all
end
def show
@random_workout = Workout.where.not(id: @workout).order("RANDOM()").first(3)
end
def new
@workout = Workout.new
end
def create
@workout = Workout.new(workout_params)
@workout.user = current_user
if @workout.save
flash[:success] = "Your workout was created successfully!"
redirect_to workouts_path
else
render :new
end
end
def edit
end
def update
if @workout.update(workout_params)
flash[:success] = "Your workout was update success"
redirect_to workout_path(@workout)
else
render :edit
end
end
def destroy
Workout.find(params[:id]).destroy
flash[:success] = "Workout Deleted"
redirect_to workouts_path
end
def review
review = Review.create(body: params[:body], user: current_user, workout: @workout)
if review.valid?
flash[:success] = "Thank you for reviewing this workout"
else
flash[:danger] = "Review failed to post"
end
redirect_to :back
end
def deletereview
Review.find(params[:revid]).destroy
flash[:success] = "Review deleted"
redirect_to :back
end
private
def workout_params
params.require(:workout).permit(:name, :summary, :attachment, :user_id, movements_attributes: [:id, :name, :_destroy], reps_attributes: [:id, :amount, :_destroy], zets_attributes: [:id, :quantity, :_destroy], weights_attributes: [:id, :kilogram, :_destroy],)
end
def set_workout
@workout = Workout.find(params[:id])
end
def require_same_user
if current_user != @recipe.user and !current_user.admin?
flash[:danger] = "You can only edit your own recipes"
redirect_to recipes_path
end
end
def admin_user
redirect_to recipes_path unless current_user.admin?
end
end
and finally the index.html.erb
<thead>
<tr>
<th>Name</th>
<th>Summary</th>
<th>Attachment</th>
<th>Exercises</th>
<th colspan="3"></th>
</tr>
</thead>
<tbody>
<% @workouts.each do |workout| %>
<tr>
<td><%= workout.name %></td>
<td><%= truncate(workout.summary, length: 350) %><%= link_to 'click to see workout', workout_path(workout)%></td>
<td><%= link_to "Download Workout", workout.attachment_url %>%></td>
<td><%= link_to 'Show', workout %></td>
<% end %>
<% @workout.movements.each do |movement| %>
<td>
<ol>
<li>
<%= movement.name %>
</li>
</ol>
<%end%>
<% @workout.reps.each do |rep| %>
<td>
<ol>
<li>
<%= rep.amount %>
</li>
</ol>
<%end%>
Sorry about all the text, i just wanted to include everything the first time round. And i know this question has been asked to death and i appologise, for not being able to workout the issue from the already answered questions, but, was reallly hoping to figure out why im getting this error.
NoMethodError in Workouts#index Showing /home/ubuntu/workspace/app/views/workouts/index.html.erb where line #24 raised:
undefined method `movements' for nil:NilClass
As I mentioned I've implemented almost the exact same functionality twice now, on 2 other functions within the app, which work almost exactly the same as this is 'supposed to'. So im quite confused :(