Ruby on Rails associating a User to another models text field - ruby-on-rails

hello I have 2 models User.rb and Guest.rb.
in my app the user is responsible for entering the Guest information. I have a table in my views that will show all guests. I would like each guest row to display the user who has entered their information. Iam having some trouble properly setting up the current_user method in my controller methods. Currently iam grabbing the current_usera nd entering it next to every guest. Thank you so much in advance.
Controller:
def new
#guest = Guest.new
end
def create
#guest = Guest.new(guest_params)
if #guest.save
redirect_to guests_path
else
render 'new'
end
end
def index
#guests = Guest.all
#user = current_user
end
def show
#guest = Guest.find(params[:id])
#user = current_user
end
def edit
#guest = Guest.find(params[:id])
end
def update
#guest = Guest.find(params[:id])
if #guest.update(guest_params)
flash[:success] = "Profile updated"
redirect_to #guest
else
render 'edit'
end
end
def destroy
Guest.find(params[:id]).destroy
flash[:success] = "User deleted"
redirect_to guests_url
end
def guest_params
params.require(:guest).permit(:experience,:interaction,:mood,:guest_name,:room_num,:arrival_date,:departure_date,:opportunity_string,:employee,:notes,:opportunity)
end
end
Models:
has_and_belongs_to_many :users
end
# Include default devise modules. Others available are:
# :confirmable, :lockable, :timeoutable, :trackable and :omniauthable
devise :database_authenticatable, :registerable,
:recoverable, :rememberable, :validatable
has_and_belongs_to_many :guests
end
Views:
body{background-color:white;}
</style>
<h1 class="text-center mt-3">Guests</h1>
<div class="container-fluid" style="overflow-x: auto; mb-3">
<table class="table table-bordered text-center ">
<thead>
<tr style="background-color:#CFD2CF;font-size:1.4vw">
<th>GUEST</th>
<th>EXPERIENCE</th>
<th>ROOM</th>
<th>ARRIVAL</th>
<th>DEPARTURE</th>
<th>OPPORTUNITY</th>
<th>EMPLOYEE</th>
<th>DEPARTMENT</th>
</tr>
</thead>
<tbody>
<% #guests.each do |guest| %>
<tr style="background-color:<%=guest.mood%>">
<td> <%= link_to guest.guest_name, "/guests/#{guest.id}" %></td>
<td><%= guest.experience %></td>
<td><%= guest.room_num %></td>
<td><%= guest.arrival_date %></td>
<td><%= guest.departure_date %></td>
<td ><%= #user.current_user%></td>
<td><%= %></td>
<td><%= guest.interaction %></td>
</tr>
<% end %>
</tbody>
</table>
</div>
Schema:
create_table "guests", force: :cascade do |t|
t.string "experience"
t.string "interaction"
t.string "mood"
t.string "guest_name"
t.string "room_num"
t.string "arrival_date"
t.string "departure_date"
t.string "opportunity_string"
t.string "employee"
t.string "notes"
t.datetime "created_at", precision: 6, null: false
t.datetime "updated_at", precision: 6, null: false
t.integer "user_id", null: false
t.index ["user_id"], name: "index_guests_on_user_id"
end
create_table "users", force: :cascade do |t|
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.datetime "created_at", precision: 6, null: false
t.datetime "updated_at", precision: 6, null: false
t.boolean "superadmin_role", default: false
t.boolean "supervisor_role", default: false
t.boolean "user_role", default: true
t.string "name"
t.index ["email"], name: "index_users_on_email", unique: true
t.index ["reset_password_token"], name: "index_users_on_reset_password_token", unique: true
end
add_foreign_key "guests", "users"
end

A few things that will help:
Devise and current_user:
Devise takes care of current_user for you, so you should just be able to call current_user in your controllers and views.
#user.current_user isn't a method unless you've created one in your User model, which I would not recommend doing.
Don't mix #user with current_user
It's possible to set #user = current_user, but I think it's a bad practice as it will get confusing quickly
#user should be tied to the model User and represent the user that the current_user is interacting with.
For example, a URL like /users/1/edit should set #user = User.find(1).
The current_user could be someone else who is editing the #user object.
HABTM Associations
Given an assigned #user, you can call #user.guests to get all guests associated with that user.
E.g. for a route that creates the following URL: /users/1/guests then your controller can have something like this:
# users_controller.rb
class UsersController < ApplicationController
...
def guests
#user = User.find(params[:id])
#guests = #user.guests
end
end
And the reverse is true as well. For a route like guests/1/users you can call #guest.users.
But...
Do you really want a HABTM?
If a User can create many Guests, but a Guest is never associated with many Users, then this isn't really a "has and belongs to many" relationship. You probably just want a simple has_many belongs_to.
I revisit this article often as a refresher when I'm considering my relationships.
Your schema has a user_id on your guest model, which indicates to me that you want to be able to say: "A User has_many guests. A Guest belongs_to a user."
But you wouldn't really say "A Guest can belong_to many Users"
Code fixes
I have a table in my views that will show all guests.
For ALL guests, this would be the URL /guests, which should map to GuestsController#index:
# guests_controller.rb
class GuestsController < ApplicationController
...
def index
#guests = Guest.all # or some scope like Guest.active
end
...
end
For guests related to a give user, this would be the URL /users/:id/guests which should map to UsersController#guests:
# users_controller.rb
class UsersController < ApplicationController
before_action :set_user, only: %i[show edit update guests]
...
def guests
#user.guests
...
end
...
private
# this method sets #user for all views defined in the `:only` hash of the `before_action` callback.
def set_user
#user = User.find(params[:id]
end
I would like each guest row to display the user who has entered their information.
Since you have a user_id field on Guest, if you switch to a has_many belongs_to relationship, then you can just call the user:
<tbody>
<% #guests.each do |guest| %>
<tr style="background-color:<%=guest.mood%>">
<td> <%= link_to guest.guest_name, "/guests/#{guest.id}" %></td>
<td><%= guest.experience %></td>
<td><%= guest.room_num %></td>
<td><%= guest.arrival_date %></td>
<td><%= guest.departure_date %></td>
<td ><%= guest.user%></td> <!-- guest.user instead of #user.current_user -->
<td></td>
<td><%= guest.interaction %></td>
</tr>
<% end %>
</tbody>
Extra credit: use Includes to pre-load associations
Also, as a pro tip, calling guest.user could get slow because each guest record needs to make a call to the User table.
Rails offers eager loading for just this situation.
Change #guests = Guest.all to #guest = Guest.includes(:user).all and Rails will handle the rest.

Related

How can I set my controller and views when I have two Many-to-Many association?

My aim is to organize uploaded posts by categories. These categories are shown on the nav bar and if you click one of the category's names, you will see the posts assigned with the category. When uploading a post, you can assign it with multiple categories too. So, I think this is like many posts can have many categories and many categories can have many posts.
This is how I want my posts organized by categories
However, I cannot set things right in my posts_controller.rb, posts/index.html.erb, posts/show.html.erb, and _navigation.html.erb
post.rb
class Post < ActiveRecord::Base
#This validates presence of title, and makes sure that the length is not more than 140 words
validates :title, presence: true, length: {maximum: 140}
#This validates presence of body
validates :body, presence: true
has_many :categorizations
has_many :categories, :through => :categorizations
end
category.rb
class Category < ApplicationRecord
has_many :categorizations
has_many :posts, :through => :categorizations
end
categorization.rb
class Categorization < ApplicationRecord
belongs_to :post
belongs_to :category
end
Then, here are these controller and views I am confused with:
posts_controller.rb
class PostsController < ApplicationController
before_action :find_post, only: [:edit, :update, :show, :delete]
before_action :authenticate_admin!, except: [:index, :show]
# Index action to render all posts
def index
if params.has_key?(:category)
#category = Category.find_by_name(params[:category])
#posts = Post.where(category: #category)
else
#posts = Post.all
end
end
# New action for creating post
def new
#post = Post.new
end
# Create action saves the post into database
def create
#post = Post.new(post_params)
if #post.save
flash[:notice] = "Successfully created post!"
redirect_to post_path(#post)
else
flash[:alert] = "Error creating new post!"
render :new
end
end
# Edit action retrives the post and renders the edit page
def edit
end
# Update action updates the post with the new information
def update
#post = Post.find(params[:id])
if #post.update_attributes(post_params)
flash[:notice] = "Successfully updated post!"
redirect_to posts_path(#posts)
else
flash[:alert] = "Error updating post!"
render :edit
end
end
# The show action renders the individual post after retrieving the the id
def show
end
# The destroy action removes the post permanently from the database
def destroy
#post = Post.find(params[:id])
if #post.present?
#post.destroy
flash[:notice] = "Successfully deleted post!"
redirect_to posts_path
else
flash[:alert] = "Error updating post!"
end
end
private
def post_params
params.require(:post).permit(:title, :body, category_ids: [])
end
def find_post
#post = Post.find(params[:id])
end
end
index.html.erb
<div class="container">
<div class="col-sm-10 col-sm-offset-1 col-xs-12">
<% #posts.each do |post| %>
<div class="col-xs-12 text-center">
<div class="text-center">
<h2><%= post.title %></h2>
<h6><%= post.created_at.strftime('%b %d, %Y') %></h6>
</div>
<div>
<%= raw post.body.truncate(358) %>
</div>
<div class="text-center">
<%= link_to "READ MORE", post_path(post) %>
</div>
<% if admin_signed_in? %>
<%= link_to "Show", post_path(post), class: "btn btn-primary" %>
<%= link_to "Edit", edit_post_path(post), class: "btn btn-default" %>
<%= link_to "Delete", post_path(post), class: "btn btn-danger", data: {:confirm => "Are you sure?"}, method: :delete %>
<% end %>
<hr />
</div>
<% end %>
</div>
</div>
show.html.erb
<div class="col-sm-11 col-xs-12 blog-content">
<h2 class="text-center"><%= #post.title %></h2>
<h1 class="text-center"><%= #category.name %></h1>
<h5 class="text-center"><%= #post.created_at.strftime('%b %d, %Y') %></h5>
<div class="text-center"><%= raw #post.body %></div>
</div>
_navigation.html.erb(part of it)
<ul class="nav navbar-nav navbar-left">
<% Category.all.each do |cat| %>
<li class="text-center"><%= link_to cat.name, posts_path(category: cat.name) %></li>
<% end %>
</ul>
Just in case, schema.rb
ActiveRecord::Schema.define(version: 2018_11_07_082317) do
create_table "admins", force: :cascade do |t|
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.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.string "avatar"
t.index ["email"], name: "index_admins_on_email", unique: true
t.index ["reset_password_token"], name: "index_admins_on_reset_password_token", unique: true
end
create_table "categories", force: :cascade do |t|
t.string "name"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
end
create_table "categories_posts", id: false, force: :cascade do |t|
t.integer "category_id"
t.integer "post_id"
end
create_table "categorizations", force: :cascade do |t|
t.integer "post_id"
t.integer "category_id"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
end
create_table "ckeditor_assets", force: :cascade do |t|
t.string "data_file_name", null: false
t.string "data_content_type"
t.integer "data_file_size"
t.string "type", limit: 30
t.integer "width"
t.integer "height"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.index ["type"], name: "index_ckeditor_assets_on_type"
end
create_table "posts", force: :cascade do |t|
t.string "title"
t.text "body"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
end
end
In show view you have
<h1 class="text-center"><%= #category.name %></h1>
But you don't define #category in show action. If you want to list categories, it should be
<h1 class="text-center"><%= #post.categories.pluck(:name).join(', ') %></h1>
Btw, looks like you have useless table categories_posts in the schema.rb
Update:
About index action - you should change query for #posts, since the post doesn't have a category column, but he has categories association:
def index
if params.has_key?(:category)
# you can remove #category defining if you don't need it somewhere in view
#category = Category.find_by_name(params[:category])
#posts = Post.joins(:categories).where(categories: { name: params[:category] } )
else
#posts = Post.all
end
end
Note, it is better to use id for the query, not name, searching by id is faster. You need to change link in navbar to link_to cat.name, posts_path(category: cat.id) for it and replace name with id in the query. And it is better to move the whole query to named scope in the Post model.

Rails Issues with association between User and Contact

Initially started with Contacts, as expected created a list of populated contacts which correctly allow CRUD. Then set up the login with devise which created Users. When logging in as two different users each should only see their own contacts however currently users sees all the same contacts.
Any help resolving this issue would be appreciated?
(Not sure if should have started with User and then created Contact, feels like this is created backwards.)
Understanding for associations is User 'has_many :contacts' and Contacts 'belongs_to :users' have been changing and spiking to no avail.
ContactsController
class ContactsController < ApplicationController
before_action :contact, only: [ :show, :edit, :update, :destroy] before_action :authenticate_user!
def index
#contacts = Contact.all end
def new
#contact = Contact.new end
def create
Contact.create(contact_params)
redirect_to '/contacts' end
def show end
def edit end
def update
#contact.update(contact_params)
redirect_to '/contacts/' + "#{#contact[:id]}" end
def destroy
#contact.destroy
redirect_to '/contacts' end
private
def contact_params
params.require(:contact).permit(:firstname, :surname, :email, :phone, :image) end``
def contact
#contact = Contact.find(params[:id]) end
end
UsersController
class UsersController < ApplicationController
end
model Contact
class Contact < ActiveRecord::Base
belongs_to :users
has_attached_file :image, styles: {thumb: "100x100>"}
validates_attachment_content_type :image, content_type:
/\Aimage\/.*\Z/
end
model user
class User < ActiveRecord::Base has_many :contacts, dependent: :destroy devise :database_authenticatable, :registerable,
:recoverable, :rememberable, :trackable, :validatable end
indexhtml
<%if user_signed_in? %> <%= link_to 'Log out', destroy_user_session_path, method: :delete %> <%end%>
<% if #contacts.any? %> <% #contacts.each do |contact| %> <%= link_to image_tag(contact.image.url(:thumb)), contact_path(contact) %> <h3><%= contact.firstname%> <%=contact.surname%></h3> <%=contact.email%><br /> <%=contact.phone%> <br /> <br /> <%end%> <%else%> No contacts yet! <%end%> <br /> <br /> <%= link_to 'Add a contact', new_contact_path%>
show html
<p><%= image_tag #contact.image.url(:thumb) %></p> <p><%= #contact.firstname %> <%= #contact.surname %></p> <p><%= #contact.phone %></p> <p><%= #contact.email %></p>
<%= link_to 'Edit', edit_contact_path(#contact) %> <%= link_to 'Remove', contact_path(#contact), method: :delete %><br /><br /> <%= link_to 'Contacts', contacts_path %>
schema
ActiveRecord::Schema.define(version: 20160504125849) do
# These are extensions that must be enabled in order to support this database enable_extension "plpgsql"
create_table "contacts", force: :cascade do |t|
t.string "firstname"
t.string "surname"
t.string "email"
t.integer "phone"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.string "image_file_name"
t.string "image_content_type"
t.integer "image_file_size"
t.datetime "image_updated_at" end
create_table "users", force: :cascade do |t|
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.inet "current_sign_in_ip"
t.inet "last_sign_in_ip"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false end
When logging in as two different users each should only see their own
contacts however currently users sees all the same contacts
The problem is with this line #contacts = Contact.all. It holds all the contacts. As you want to display only the current_user's contacts, you just need it to below
#contacts = current_user.contacts
ActionView::Template::Error: PG::UndefinedColumn: ERROR: column
contacts.user_id does not exist LINE 1: SELECT 1 AS one FROM
"contacts" WHERE "contacts"."user_id" ... ^ : SELECT 1 AS one FROM
"contacts" WHERE "contacts"."user_id" = $1 LIMIT 1
It seems the contacts table doesn't have user_id column. Create a new migration to add the same and do rake db:migrate

Rails 4 Update Data Through View Page

I currently have a view page named "users". In my view page, I'm displaying a table with attributes pulled from the users table such as the first name, last name, last login, admin, etc... In the admin field, it displays from the users table true or false.
What I would like to accomplish is to create a drop down, that displays the user's current value for admin (true or false), and then be able to change this attribute from the view page. Currently, I'm having to use the console on the server to manually change a user's value to true or false to grant or revoke admin privileges. Needless to say, this is inconvenient. I'm still fairly new to Rails and have been using scaffolds up to this point. I'm not sure how to accomplish this, and any advise would be greatly appreciated!
Users schema:
create_table "users", force: true do |t|
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"
t.datetime "updated_at"
t.boolean "admin", default: false
t.string "first_name"
t.string "last_name"
end
Admin controller:
class AdminController < ApplicationController
before_action :authenticate_user!
def users
#users = User.all.order('last_name ASC')
end
def reports
end
end
Users view page:
<table class="table table-hover table-condensed">
<thead>
<tr>
<th>Last Name</th>
<th>First Name</th>
<th>Email</th>
<th>Creation Date</th>
<th>Last Sign In</th>
<th>IP Address</th>
<th>Admin</th>
</tr>
</thead>
<tbody>
<% #users.each do |user| %>
<tr>
<td><%= user.last_name %></td>
<td><%= user.first_name %></td>
<td><%= user.email %></td>
<td><%= user.created_at.strftime("%-m/%-d/%y") %></td>
<td><%= user.current_sign_in_at.strftime("%-m/%-d/%y") %></td>
<td><%= user.current_sign_in_ip %></td>
<td><%= user.admin %></td>
</tr>
<% end %>
</tbody>
</table>
You could accomplish this in a couple of different ways. For example, you could let the link in the drop-down trigger a method toggle_admin for removing admin if user is admin or the reverse if that's the case.
First create the route, in routes.rb:
resource :users do
get :toggle_admin
end
in your view:
<%=link_to (#current_user.admin ? 'Remove admin' : 'Make admin'), toggle_admin_users_path %>
And in your controller, you could have something like this:
def toggle_admin
#current_user.update_attribute :admin, (#current_user.admin ? false : true)
end
Hmm... yeah, I don't know. Could work. As you can see, I assume here that you have a #current_user variable for picking up the relevant user, otherwise send in the user.id into these methods, either from the url params or directly into the controller method.
First you'll need a route and a corresponding controller action that handles the update.
In a RESTful way this would be in routes.rb: resources :users, only: [:update]
In your view you need a from, that sends the data to the controller:
<%= form_for user do %>
...
Each of the users in the #users.each should have it's own form and a submit button. To create the select (that's the dropdown with true/false value) use the Rails form helper.
The controller action could look something like this:
def update
user = User.find(params[:id])
user.update_attributes(user_params)
end
private
def user_params
params.require(:user).permit(:admin)
end

Trying to create a nested class' show - getting the error 'ActiveRecord::StatementInvalid in StocksController#show Could not find table 'time_deltas''

I'm trying to follow along the Rails getting started guide except for the fact that I'm using Stocks instead of articles and TimeDeltas instead of comments. Now when I go to the view I keep getting this error
ActiveRecord::StatementInvalid in StocksController#show Could not find
table 'time_deltas'
on line: #time_delta = #stock.time_deltas.build
Heres my view:
<h1> Stock </h1>
<table>
<tr>
<th>Stock</th>
<th>Hashtag</th>
</tr>
<tr>
<td><%= #stock.name %></td>
<td><%= #stock.hashtag %></td>
</tr>
</table>
<h2>Deltas: </h2>
<table>
<tr>
<th>Stock</th>
<th>Hashtag</th>
</tr>
<% #stock.deltas.each do |delta| %>
<tr>
<td><%= #delta.start %></td>
<td><%= #delta.length %></td>
</tr>
<% end %>
</table>
<h2>Add a TimeDelta:</h2>
<%= form_for([#stock, #stock.time_deltas.build]) do |f| %>
<p>
<%= f.label :start %><br>
<%= f.text_field :start %>
</p>
<p>
<%= f.label :length %><br>
<%= f.text_area :length %>
</p>
<p>
<%= f.submit %>
</p>
<% end %>
<%= link_to 'Back', stocks_path%>
<%= link_to 'Edit', edit_stock_path(#stock)%>
Heres my stocks controller:
class StocksController < ApplicationController
def new
#stock = Stock.new
end
def index
#stocks = Stock.all
end
def create
# XXX Add columns for delta and current standing when we get there
# they can intiate to nil
#stock = Stock.new(stock_params)
if #stock.save
redirect_to #stock
else
render 'new'
end
end
def show
#stock = find_stock
#time_delta = #stock.time_deltas.build
end
def edit
#stock = find_stock
end
def update
#stock = find_stock
if #stock.update(stock_params)
redirect_to #stock
else
render 'edit'
end
end
def destroy
#stock = find_stock
#stock.destroy
redirect_to stocks_path
end
private
def stock_params
params.require(:stock).permit(:name, :hashtag)
end
def find_stock
return Stock.find(params[:id])
end
end
Heres my TimeDelta controller
class TimeDeltasController < ApplicationController
def new
#stock = Stock.find(params[:stock_id])
#time_delta = #stock.time_deltas.build
# respond_with(#stock, #time_delta)
end
def create
#stock = Stock.find(time_delta_params)
#time_delta = #stock.time_deltas.create(params[:stock])
redirect_to stock_path(#stock)
end
private
def time_delta_params
params.require(:time_delta).permit(:start, :length)
end
end
I've tried re running my migrations as well and to no-avail, any suggestions?
EDIT: Both models
Stock:
class Stock < ActiveRecord::Base
has_many :deltas
has_many :time_deltas
validates :hashtag, :name , presence: true, :uniqueness => true, length: { minimum: 2 }
end
Time Delta:
class TimeDelta < ActiveRecord::Base
belongs_to :stock
end
Database Schema:
# encoding: UTF-8
# This file is auto-generated from the current state of the database. Instead
# of editing this file, please use the migrations feature of Active Record to
# incrementally modify your database, and then regenerate this schema definition.
#
# Note that this schema.rb definition is the authoritative source for your
# database schema. If you need to create the application database on another
# system, you should be using db:schema:load, not running all the migrations
# from scratch. The latter is a flawed and unsustainable approach (the more migrations
# you'll amass, the slower it'll run and the greater likelihood for issues).
#
# It's strongly recommended that you check this file into your version control system.
ActiveRecord::Schema.define(version: 20140412204548) do
create_table "delta", force: true do |t|
t.datetime "start"
t.integer "length"
t.integer "stock_id"
t.datetime "created_at"
t.datetime "updated_at"
end
add_index "delta", ["stock_id"], name: "index_delta_on_stock_id"
create_table "queries", force: true do |t|
t.text "tweet"
t.integer "tweetId"
t.datetime "created_at"
t.datetime "updated_at"
end
create_table "stocks", force: true do |t|
t.text "name"
t.text "hashtag"
t.datetime "created_at"
t.datetime "updated_at"
end
create_table "time_delta", force: true do |t|
t.datetime "start"
t.integer "length"
t.integer "stock_id"
t.datetime "created_at"
t.datetime "updated_at"
end
add_index "time_delta", ["stock_id"], name: "index_time_delta_on_stock_id"
end
When you created your table via migration the name of your "time_deltas" table was actually created as "time_delta". Keeping the database name in singular form could bring up troubles in the future. The best suggestion is to rename your database to "time_deltas" and it'd work just fine. Also, i noticed that there's another table with a singular name form (delta). I suggest you rename it to "deltas".
Happy coding!

Objects Being Attached to their Creator Question

I am working on a rails application where one user class named (submitters) are able to login and once they are logged in they create videos. My videos controller is here:
class VideosController < ApplicationController
def index
#videos = Video.find :all
end
def new
#submitter = current_submitter
#video = #submitter.videos.build
end
def create
#submitter = current_submitter
#video = #submitter.videos.build(params[:video])
if #video.save
#video.convert
flash[:notice] = 'Video has been uploaded'
redirect_to :action => 'index'
else
render :action => 'new'
end
end
def show
#video = Video.find(params[:id])
end
def destroy
#video = Video.find(params[:id])
#video.destroy
flash[:notice] = "Successfully deleted the video."
redirect_to root_url
end
def update_date
#video = Video.find(params[:id])
#video.update_attributes(params[:video])
flash[:notice] = "Successfully added a launch date!"
redirect_to #video
end
end
As you can probably see, I am trying to construct the controller so that when a video is created, it is created as belonging to the submitter who upload the video (via the video new view). I am using a auth system with a current_submitter method written in the application controller.
Now it lets me upload a video fine when I am logged in as a submitter. The trouble for me is working out how to display information in my view. If I want to display some columns with information about the video and then others with information about the submitter who uploaded the video, how do I go about doing that from the controller (index action), into the index view. My current view which does not work in below:
<% title "Films Submitted" %>
<table>
<tr>
<th>Title</th>
<th>Film Type</th>
<th>Premiere</th>
<th>Company</th>
<th>Name</th>
</tr>
<% for video in #videos do %>
<tr>
<td><%= link_to video.title, video %></td>
<td><%= video.film_type %></td>
<% if video.premiere == "true" %>
<td>Premiere</td>
<% else %>
<td><%= %></td>
<% end %>
<td><%= video.submitter.company %></td>
<td><%= video.submitter.name %></td>
<td><%= link_to "Delete", video, :confirm => 'Are you sure?', :method => :delete %></td>
</tr>
<% end %>
</table>
<br><br>
<%= link_to "Upload a Video", new_video_path %>
Any suggestions or tips from rails developers would be much appreciative... I am new and trying to learn.
Video Model:
class Video < ActiveRecord::Base
belongs_to :submitter
has_attachment :content_type => :video,
:storage => :file_system,
:max_size => 50.megabytes
end
Submitter Model:
class Submitter < ActiveRecord::Base
acts_as_authentic
has_many :videos
end
Schema:
create_table "videos", :force => true do |t|
t.string "title"
t.text "description"
t.string "state"
t.datetime "created_at"
t.datetime "updated_at"
t.string "content_type"
t.integer "size"
t.string "filename"
t.string "film_type"
t.boolean "premiere", :default => false
t.date "preferred_date"
t.text "reason"
t.integer "submitter_id"
t.date "actual_date"
end
create_table "submitters", :force => true do |t|
t.string "name"
t.string "company"
t.string "email"
t.string "username"
t.string "crypted_password"
t.string "password_salt"
t.string "persistence_token"
t.datetime "created_at"
t.datetime "updated_at"
t.integer "video_id"
end
I think you've probably only setup your associations in one direction. You already have:
class Submitter < ActiveRecord::Base
has_many :videos
end
But you also need to reciprocate that relationship in the video model:
class Video < ActiveRecord::Base
belongs_to :submitter
end
This will create the submitter method in your video model, that references the submitter it belongs to.
UPDATE:
After you updated your question with the model info, I noticed one small thing: You have a video_id column on your submitters table that doesn't need to be there. Only the "belongs_to" side of the association needs a foreign key. But this isn't causing your problem.
I think you might have a video in your database without a submitter! In the index action, since you're not checking for a valid submitter before you start using it, if even a single video record is missing a submitter_id, it'll break the view.

Resources