Allow users to upload photos bypassing creating gallery - ruby-on-rails

I have a social network and for it I am using carrier wave. I need help with setting it up so that users do not have to create a Gallery name to upload photos. That's the default setup for carrierwave, but since this is a social network I am not allowing users to have different Galleries (or albums). There should only be a link to upload photos to their profile. So how should I attack this? BTW I am new to Rails so any and all help would be greatly appreciated!
photos controller:
def new
#photo = Photo.new(:gallery_id => params[:gallery_id])
end
def create
#photo = Photo.new(params[:photo])
if #photo.save
flash[:notice] = "Successfully created photos."
redirect_to #photo.gallery
else
render :action => 'new'
end
end
def edit
#photo = Photo.find(params[:id])
end
def update
#photo = Photo.find(params[:id])
if #photo.update_attributes(paramas[:photo])
flash[:notice] = "Successfully updated photo."
redirect_to #photo.gallery
else
render :action => 'edit'
end
end
def destroy
#photo = Photo.find(params[:id])
#photo.destroy
flash[:notice] = "Successfully destroyed photo."
redirect_to #photo.gallery
end
end
galleries controller:
def index
#galleries = Gallery.all
end
def show
#gallery = Gallery.find(params[:id])
end
def new
#gallery = Gallery.new
end
def create
#gallery = Gallery.new(params[:gallery])
if #gallery.save
flash[:notice] = "Successfully created gallery."
redirect_to #gallery
else
render :action => 'new'
end
end
def edit
#gallery = Gallery.find(params[:id])
end
def update
#gallery = Gallery.find(params[:id])
if #gallery.update_attributes(params[:gallery])
flash[:notice] = "Successfully updated gallery."
redirect_to gallery_url
else
render :action => 'edit'
end
end
def destroy
#gallery = Gallery.find(params[:id])
#gallery.destroy
flash[:notice] = "Successfully destroy gallery."
redirect_to galleries_url
end
end
routes:
Dating::Application.routes.draw do
get 'signup' => 'users#new'
get 'login' => 'sessions#new'
get 'logout' => 'sessions#destroy'
get 'edit' => 'users#edit'
get "/profile/:id" => "users#show"
get "profile/:id/settings" => 'users#edit'
match 'settings/:id' => 'users#settings'
resources :users
resources :sessions
resources :password_resets
resources :galleries
resources :photos
resources :searches
resources :users do
get 'settings', on: :member
end
root to: 'users#new'
root to: 'galleries#index'
resources :users do |user|
resources :messages do
collection do
post 'delete_multiple'
end
end
end

zwippie s answer is a good option as far as I can see.
If you follow zwippie´s answer, you have to modify your photos controller, e.g like follwoing:
def new
#photo = Photo.new
end
def create
#photo = Photo.new(params[:photo])
#photo.gallery = current_user.gallery
if #photo.save
flash[:notice] = "Successfully created photos."
redirect_to gallery_path #photo.gallery
else
render :action => 'new'
end
end
An completely other option is not to generate any gallery, just associate the current user to the photo.
user model:
class User < ActiveRecord::Base
has_many :photos
end
class Photos < ActiveRecord::Base
belongs_to :user
end
photos_controller
def new
#photo = Photo.new
end
def create
#photo = Photo.new(params[:photo])
#photo.user = current_user
if #photo.save
flash[:notice] = "Successfully created photos."
redirect_to user_photos_path(current_user)
else
render :action => 'new'
end
end
As gallery name for your carrierwave setup you can for example choose the current user username, or something else.
UPDATE: changed redirect path
your routes should look like following:
resources :users do
resources :photos
end

Why not create the gallery directly after the user has signed up? Or create it when the user uploads the first picture.
photos_controller:
def new
# Get the gallery for the current user (assuming Gallery has attribute user_id)
#gallery = current_user.gallery
# Create a new gallery if user does not have one already
#gallery = Gallery.create(:user_id => current_user.id) if #gallery.nil?
# Save the photo
#photo = Photo.new(:gallery_id => #gallery.id)
end

You can use paperClip to create photoalbum, here is link for paperclip gem:
https://github.com/thoughtbot/paperclip

Related

the foreign key is just passing to the new form not the create action (ruby on rails)

This is my controllers and routes
I have a albums controller and a bands controler with their models, and I want to access the foreign key to pass it, but it told me bands is blank
def show
#album = Album.find_by(:id => params[:id])
render :show
end
def new
#band = Band.find_by(:id => params[:band_id])
#albums = Album.new(:band_id => params[:band_id])
render :new
end
def create
#albums = Album.new(albums_params)
if #albums.save
flash[:success] = "Album created successfully"
redirect_to album_path(#albums.id)
else
#band = #albums.band
flash[:error] = #albums.errors.full_messages
render :new
end
end
def update
render :edit
end
def edit
end
def destroy
end
private
def albums_params
params.require(:albums).permit(:name, :band_id, :live, :year)
end
end```
resources :bands do
resources :albums, :only => :new
end
Try to pass Band relation like below.
def new
#band = Band.find_by(:id => params[:band_id])
#albums = Album.new(:band => #band)
render :new
end
OR check your code. Can you find Band with correct id?
#band = Band.find_by(:id => params[:band_id])
AND check your Views
You must put someting like below
<%=form.hidden_field :band_id, value: #albums.band_id%>
OR
<%=form.hidden_field :band_id, value: #band.id %>

Couldn't find Item with 'id'. Paper trail issue, unable to undo action

My To-do list application, I want to be able to undo changes.
If the task(item) is completed or deleted, I have an undo hyperlink to revert the change.
I am using the paper trail gem file.
The URL is http://localhost:3000/versions/315/revert
Looks like it is not reverting back and picking the item, to revert the change.
I have the versions controller with fi statements that if the Item is blank, return record not found. As it is not returning the message it must have something?
I don't know what I am doing wrong here, any help would be greatly appreciated.
Here is my main Task (item) controller.rb
class ItemsController < ApplicationController
before_action :find_item, only: [:show, :edit, :update, :destroy]
def index
if user_signed_in?
#items = Item.where(:user_id => current_user.id).order("created_at DESC")
end
end
def show
end
def new
#item = current_user.items.build
end
def create
#item = current_user.items.build(item_params)
if #item.save
redirect_to root_path, :notice => "Congrats! Task was created!"
else
render 'new'
end
end
def edit
end
def update
if #item.update(item_params)
redirect_to item_path(#item), :notice => "Congrats! Task was updated!"
else
render 'edit'
end
end
def destroy
#item.destroy
redirect_to root_path , :notice => "Task was Deleted! To Revert click. #{undo_link}"
end
def complete
#item = Item.find(params[:id])
#item.update_attribute(:completed_at, Time.now)
redirect_to root_path , :notice => "To undo completed task please click. #{undo_link}"
end
private
def item_params
params.require(:item).permit(:title, :description)
end
def find_item
#item = Item.find(params[:id])
end
def undo_link
view_context.link_to("undo",revert_version_path(#item.versions.scope.last), :method => :post)
end
end
Here is the versions controller
class VersionsController < ApplicationController
PaperTrail::Version.where('created_at < ?', 1.day.ago).delete_all
def revert
#item = Item.find(params[:id])
if #item.blank?
format.html {redirect_to(rooth_path, :notice => 'Record not found') }
elsif #item.reify
#item.reify.save!
else
#item.item.destroy
end
link_name = params[:redo] == "true" ? "undo" : "redo"
link = view_context.link_to(link_name, revert_version_path(#item.next, :redo => !params[:redo]), :method => :post)
redirect_to :back, :notice => "Undid #{#item.event}. #{link}"
end
end
Here is my Item model (tasks)
class Item < ActiveRecord::Base
belongs_to :user
has_paper_trail # you can pass various options here
def completed?
!completed_at.blank?
end
end
Here is my routes folder
Rails.application.routes.draw do
post "versions/:id/revert" => "versions#revert", :as => "revert_version"
devise_for :users
resources :items do
member do
patch :complete
end
end
root 'items#index'
get '/about' => 'page#about'
end

Ruby on rails "Could find user with id= create"

i don't know what's wrong, I tried to add "create" method to my application, and what i get is :
"ActiveRecord::RecordNotFound in UsersController#show"
"Couldn't find User with id=create"
And then code
# Use callbacks to share a common setup
def set_user
#user = User.find(params[:id])
end
# Permit only specific parameters
here's my User controller
class UsersController < ApplicationController
before_action :set_user, only: [:show, :edit, :update, :destroy]
def index
#users = User.all
end
def show
end
def create
#user = User.new(user_params)
respond_to do |user|
if #user.save(user_params)
user.html { redirect_to users_path, :notice => "User has been created!" }
else
user.html { redirect_to create_user_path(#user), :notice => "Sorry, couldn't create user. Try again!" }
end
end
end
def edit
end
def update
respond_to do |format|
if #user.update(user_params)
format.html { redirect_to users_path, :notice => "User has been updated!" }
else
format.html { redirect_to edit_user_path(#user), :notice => "Sorry, couldn't update user. Try again!" }
end
end
end
def destroy
#user.destroy
respond_to do |d|
d.html { redirect_to users_path, :notice => "User has been successfully destroyed :C !" }
end
end
private
# Use callbacks to share a common setup
def set_user
#user = User.find(params[:id])
end
# Permit only specific parameters
def user_params
params.require(:user).permit(:name, :email)
end
end
The thing is, the index page works perfectly fine, but if i try to go somewhere else, like /users/create i get that error.. I tried changing routes, rewriting the code, nothing helps.My routes are like this:
# Root '/'
root "users#index"
# Show Users
get "users/:id" => "users#show"
Can you guys help me ? I am literally stuck, as to how fix that problem :c
This should help you - you're missing resources :users, which creates a set of RESTful routes for your controller. This, combined with the other answers should help
You don't go to the create action via a URL. It's there to create a new user coming back from the new.html.erb file.
If you want to create a new user you could use /users/new and add a new method to your controller along the lines of:
def new
#user = User.new
end
You will also need to change your routes.rb file to add all the default actions like:
resources :users
I suggest you work through http://guides.rubyonrails.org/getting_started.html.
In your controller:
class UsersController < ApplicationController
before_action :set_user, only: [:show, :edit, :update, :destroy]
def index
#users = User.all
end
def show
end
def new
#user = User.new
end
def create
#user = User.new(user_params)
if #user.save
redirect_to users_path, :notice => "User has been created!"
else
render :new
end
end
def edit
end
def update
if #user.update(user_params)
redirect_to users_path, :notice => "User has been updated!"
else
render :edit
end
end
def destroy
#user.destroy
redirect_to users_path, :notice => "User has been successfully destroyed :C !" }
end
private
def set_user
#user = User.find(params[:id])
end
def user_params
params.require(:user).permit(:name, :email)
end
end
You are using all RESTful actions, so you can add to routes.rb:
resources :users
And remove this:
get "users/:id" => "users#show"

How to pass parameters when building an Object in Rails controller

I have an Event model and a Notifications model. An event has many notifications, and a notification only has one event. My notification object has two attributes: message and event_id. When I build a new notification, how can I set the event_id to the current event's id?
events_controller.rb
class EventsController < ApplicationController
before_action :signed_in, only: [:new,:create]
def new
#event = Event.new
end
def create
#event = Event.new(event_params)
if #event.save
flash[:success] = "Your Event has been created."
redirect_to root_path
else
render 'new'
end
end
def show
#event = Event.find(params[:id])
#notification = #event.notifications.build
respond_to do |format|
format.html
format.xml { render :xml => #event }
format.json { render :json => #event }
end
end
private
def event_params
params.require(:event).permit(:name, :description)
end
def signed_in
unless user_signed_in?
redirect_to new_user_session_path
flash[:warning] = "You must be signed in to access that page"
end
end
end
notifications_controller.rb
class NotificationsController < ApplicationController
def create
#notification = Notification.new(notification_params)
if #notification.save
redirect_to root_path
flash[:success] = "Your message has been sent"
else
render 'new'
end
end
def show
end
private
def notification_params
params.require(:notification).permit(:message, :event_id)
end
def signed_in
unless user_signed_in?
redirect_to new_user_session_path
flash[:warning] = "You must be signed in to access that page"
end
end
end
routes.rb
devise_for :users
resources :events
resources :notifications
root 'static_pages#home'
match '/help', to: 'static_pages#help', via: 'get'
match '/about', to: 'static_pages#about', via: 'get'
match '/contact', to: 'static_pages#contact', via: 'get'
#notification = #event.build_notification(notification_params)

Nesting resource

I'm trying to nest my messages controller into my channels controller. But when I go to my messages view i get the error "couldn't find channel with no id"
class MessagesController < ApplicationController
def index
#channel = Channel.find(params[:channel_id])
#messages = #channel.messages
end
def new
#channel = Channel.find(params[:channel_id])
#message = #channel.messages.build
end
def create
#channel = Channel.find(params[:channel_id])
#message = #channel.messages.build(params[:message])
if #message.save
flash[:notice] = "Successfully created message."
redirect_to channel_url(#message.channel_id)
else
render :action => 'new'
end
end
def edit
#message = Message.find(params[:id])
end
def update
#message = Message.find(params[:id])
if #message.update_attributes(params[:message])
flash[:notice] = "Successfully updated message."
redirect_to channel_url(#message.channel_id)
else
render :action => 'edit'
end
end
def destroy
#message = Message.find(params[:id])
#message.destroy
flash[:notice] = "Successfully destroyed message."
redirect_to channel_url(#message.channel_id)
end
end
Channels controller
class ChannelsController < ApplicationController
def index
#channels = Channel.find(:all)
end
def show
#channel = Channel.find(params[:id])
#message = Message.new(:channel => #channel)
end
def new
#channel = Channel.new
end
def create
#channel = Channel.new(params[:channel])
if #channel.save
flash[:notice] = "Successfully created channel."
redirect_to #channel
else
render :action => 'new'
end
end
def edit
#channel = Channel.find(params[:id])
end
def update
#channel = Channel.find(params[:id])
if #channel.update_attributes(params[:channel])
flash[:notice] = "Successfully updated channel."
redirect_to #channel
else
render :action => 'edit'
end
end
def destroy
#channel = Channel.find(params[:id])
#channel.destroy
flash[:notice] = "Successfully destroyed channel."
redirect_to channels_url
end
end
routes.rb
SeniorProject::Application.routes.draw do
resources :users
resources :channels, :shallow => true do |channels|
channels.resources :messages
end
root :channels
resources :users, :user_sessions
match 'login' => 'user_sessions#new', :as => :login
match 'logout' => 'user_sessions#destroy', :as => :logout
match ':controller(/:action(/:id(.:format)))'
end
What's going on here is that this line:
#channel = Channel.find(params[:channel_id])
Is falling over because there's no defined channel_id in the params hash. I see you're using shallow routes, which means your uri probably looks like this:
/messages
And you need it to look like:
/channels/1/messages
Try changing your url to be:
channel_messages_url(#channel)
instead of
messages_url
This is a guess btw, it could be because of the way you've defined your routes.rb, which looks a little odd because you're defining the messages routes twice, once with the has_many and again as a proper resource. You probably want something like:
# assuming you need shallow routes
resources :channels, :shallow => true do |channels|
channels.resources :messages
end

Resources