Forms, nested resources and routing errors Rails 4 - ruby-on-rails-4

Rails newbie here. I have created a basic website that tracks events during a shift. I have created the models and nested them. However, I do not understand the connections completely.
When I create the nested event from a form linked to a shift I get the following error:
No route matches [POST] "/shifts/events" on url http://localhost:3000/shifts//events
should be http://localhost:3000/shifts/3/events/1 I think
_form.html.erb
<%= form_for shift_events_path(#shift) do |f| %>
<% if #event.errors.any? %>
<div id="error_explanation">
<h2><%= pluralize(#event.errors.count, "error") %> prohibited </h2>
<ul>
<% #event.errors.full_messages.each do |msg| %>
<li><%= msg %></li>
<% end %>
</ul>
</div>
<% end %>
<div class="field">
<%= f.label :time_s %><br>
<%= f.time_select :time_s %>
</div>
<div class="field">
<%= f.label :time_f %><br>
<%= f.time_select :time_f %>
</div>
<div class="field">
<%= f.label :odometre %><br>
<%= f.number_field :odometre %>
</div>
<div class="field">
<%= f.label :location %><br>
<%= f.text_field :location %>
</div>
<div class="field">
<%= f.label :activity %><br>
<%= f.text_field :activity %>
</div>
<div class="field">
<%= f.label :description %><br>
<%= f.text_area :description, rows: 4 %>
</div>
<div class="actions">
<%= f.submit %>
</div>
<% end %>
roots.rb
resources :shifts do
resources :events#,
end
events_controller.eb
class EventsController < ApplicationController
before_filter :get_shift
before_action :set_event, only: [:show, :edit, :update, :destroy]
# GET /events
# GET /events.json
def index
#events = #shift.events
end
# GET /events/1
# GET /events/1.json
def show
end
# GET /events/new
def new
#event = #shift.events.build
end
# GET /events/1/edit
def edit
end
# POST /events
# POST /events.json
def create
#event = #shift.events.build(event_params)
respond_to do |format|
if #event.save
format.html { redirect_to shift_event_path, notice:
'Event was successfully created.' }
format.json { render action: 'show', status: :created, location: #event }
else
format.html { render action: 'new' }
format.json { render json: #event.errors, status: :unprocessable_entity }
end
end
end
# PATCH/PUT /events/1
# PATCH/PUT /events/1.json
def update
respond_to do |format|
if #event.update(event_params)
format.html { redirect_to shift_event_path, notice:
'Event was successfully updated.' }
format.json { head :no_content }
else
format.html { render action: 'edit' }
format.json { render json: #event.errors, status: :unprocessable_entity }
end
end
end
# DELETE /events/1
# DELETE /events/1.json
def destroy
#event.destroy
respond_to do |format|
format.html { redirect_to shift_event_path }
format.json { head :no_content }
end
end
private
# Use callbacks to share common setup or constraints between actions.
def set_event
#event = #shift.events.find(params[:id])
end
def get_shift
#shift = Shift.find(params[:shift_id])
end
# Never trust parameters from the scary internet, only allow the white list through.
def event_params
params.require(:event).permit(:time_s, :time_f, :odometre,
:location, :activity, :shift_id)
end
end
routes
shift_events_path GET /shifts/:shift_id/events(.:format) events#index
POST /shifts/:shift_id/events(.:format) events#create
new_shift_event_path GET /shifts/:shift_id/events/new(.:format) events#new
edit_shift_event_path GET /shifts/:shift_id/events/:id/edit(.:format) events#edit
shift_event_path GET /shifts/:shift_id/events/:id(.:format) events#show
PATCH /shifts/:shift_id/events/:id(.:format) events#update
PUT /shifts/:shift_id/events/:id(.:format) events#update
DELETE /shifts/:shift_id/events/:id(.:format) events#destroy
shifts_path GET /shifts(.:format) shifts#index
POST /shifts(.:format) shifts#create
new_shift_path GET /shifts/new(.:format) shifts#new
edit_shift_path GET /shifts/:id/edit(.:format) shifts#edit
shift_path GET /shifts/:id(.:format) shifts#show
PATCH /shifts/:id(.:format) shifts#update
PUT /shifts/:id(.:format) shifts#update
DELETE /shifts/:id(.:format) shifts#destroy
root_path GET / shifts#index
I figure the form first line is wrong but I don't know what to change it to. Secondly, I think some the connections in the events controller are wrong. Any help would be appreciated.

Try this:
<%= form_for [#shift, #event] do |f| %>
Now you will post a particular event for a particular shift.

Related

Can't route to /logout with Authlogic

I've been trying to set up user authentication in my app using Authlogic, and I'm sure the problem is in my code but I can't seem to find it. When I hit the /login link, all works as expected, but my /logout wants to use GET instead of DELETE.
routing.db
Rails.application.routes.draw do
root 'comments#index'
resources :roles
resources :subjects
resources :comments
resources :topics
resources :users
resources :user_sessions, only: [:create, :destroy]
delete '/logout', to: 'user_sessions#destroy', as: :logout
get '/login', to: 'user_sessions#new', as: :login
end
user_sessions_controller
class UserSessionsController < ApplicationController
before_filter :require_no_user, :only => [:new, :create]
before_filter :require_user, :only => :destroy
def new
#user_session = UserSession.new
end
def create
#user_session = UserSession.new(user_session_params)
if #user_session.save
flash[:success] = "Welcome back!"
redirect_to root_path
else
render :action => :new
end
end
def destroy
current_user_session.destroy
flash[:success] = "Goodbye!"
redirect_to root_path
end
private
def user_session_params
params.require(:user_session).permit(:username, :password, :remember_me)
end
end
application.html.erb
<!DOCTYPE html>
<html>
<head>
<title><%= content_for?(:title) ? yield(:title) : "Untitled" %></title>
<%= stylesheet_link_tag "application" %>
<%= javascript_include_tag :defaults %>
<%= csrf_meta_tag %>
<%= yield(:head) %>
</head>
<body>
<div id="user_nav">
<% if current_user %>
<span><%= current_user.username %></span>
<%= link_to "Edit profile", edit_user_path(:current) %>
<%= link_to 'Sign Out', logout_path, :method => :delete %>
<% else %>
<%= link_to "Register", new_user_path %>
<%= link_to 'Sign In', login_path %>
<% end %>
</div>
<div id="container">
<% flash.each do |name, msg| %>
<%= content_tag :div, msg, :id => "flash_#{name}" %>
<% end %>
<%= content_tag :h1, yield(:title) if show_title? %>
<%= yield %>
</div>
</body>
</html>
Does anything here look wrong? Here's the error I'm getting:
In your application.html.erb file:
Change:
<%= javascript_include_tag :defaults %>
To:
<%= javascript_include_tag "application" %>
It should work after that!

Upload Image without any gemfile Rails4

I am new in Ruby on Rails.
I trying to upload images without any gemfile. I am following http://guides.rubyonrails.org/form_helpers
Here is my books_controller.rb file:
class BooksController < ApplicationController
before_action :set_book, only: [:show, :edit, :update, :destroy]
def index
#books = Book.all
end
def show
end
def new
#book = Book.new
end
def edit
end
def create
#book = Book.new(book_params)
respond_to do |format|
if #book.save
format.html { redirect_to #book, notice: 'Book was successfully created.' }
format.json { render action: 'show', status: :created, location: #book }
else
format.html { render action: 'new' }
format.json { render json: #book.errors, status: :unprocessable_entity }
end
end
end
def update
respond_to do |format|
if #book.update(book_params)
format.html { redirect_to #book, notice: 'Book was successfully updated.' }
format.json { head :no_content }
else
format.html { render action: 'edit' }
format.json { render json: #book.errors, status: :unprocessable_entity }
end
end
end
def destroy
#book.destroy
respond_to do |format|
format.html { redirect_to books_url }
format.json { head :no_content }
end
end
def upload
uploaded_io = params[:book][:image_url]
File.open(Rails.root.join('public', 'uploads', uploaded_io.original_filename), 'wb') do |file|
file.write(uploaded_io.read)
end
end
private
def set_book
#book = Book.find(params[:id])
end
def book_params
params.require(:book).permit(:title, :description, :image_url)
end
end
and here is my form.html.erb file:
<%= form_for #book do |f| %>
<% if #book.errors.any? %>
<div id="error_explanation">
<h2><%= pluralize(#book.errors.count, "error") %> prohibited this book from being saved:</h2>
<ul>
<% #book.errors.full_messages.each do |msg| %>
<li><%= msg %></li>
<% end %>
</ul>
</div>
<% end %>
<div class="field">
<%= f.label :title %><br>
<%= f.text_field :title %>
</div>
<div class="field">
<%= f.label :description %><br>
<%= f.text_area :description %>
</div>
<div class="field">
<%= f.label :image_url %><br>
<%= f.file_field :image_url %>
</div>
<div class="actions">
<%= f.submit %>
</div>
<% end %>
Here is my schema.rb file:
ActiveRecord::Schema.define(version: 20140724173638) do
create_table "books", force: true do |t|
t.string "title"
t.text "description"
t.string "image_url"
t.datetime "created_at"
t.datetime "updated_at"
end
end
i also create a dir(public/uploads).
But its not working.when i submit "create button" showing something like this:
TypeError: can't cast ActionDispatch::Http::UploadedFile to string: INSERT INTO "books" ("created_at", "description", "image_url", "title", "updated_at") VALUES (?, ?, ?, ?, ?, ?, ?)
What's the wrong??
Thanks,
Mezbah

nesting comments resources in posts resources

I'm doing the RoR tutorial on rubyonrails.org and have been doing fine up until adding comments to posts.
When I click through to 'show' a post, I get the following error:
ActionController::UrlGenerationError in Posts#show
No route matches {:action=>"index", :controller=>"comments", :id=>"1", :format=>nil} missing required keys: [:post_id]
I have a show method for posts_controller.rb (see below), and, unless there's a typo on the rails guide (likely, since there are others in other spots), I think there's something going on with my routes.rb.
It says the error occurs around line 25 of /show.html.erb.
Title:
<%= #post.title %>
<p>
<strong>Text:</strong>
<%= #post.text %>
</p>
<h2>Comments</h2>
<% #post.comments.each do |comment| %>
<p>
<strong>Commenter:</strong>
<%= comment.commenter %>
</p>
<p>
<strong>Comment:</strong>
<%= comment.body %>
</p>
<% end %>
<h2>Add a comment:</h2>
<%= form_for([:post, #post.comments.build]) do |f| %>
<p>
<%= f.label :commenter %><br />
<%= f.text_field :commenter %>
</p>
<p>
<%= f.label :body %><br />
<%= f.text_area :body %>
</p>
<p>
<%= f.submit %>
</p>
<% end %>
<%= link_to 'Back', posts_path %>
<%= link_to 'Edit', edit_post_path(#post) %>
/posts_controller.rb
class PostsController < ApplicationController
def new
#post = Post.new
end
def index
#post = Post.all
end
def show
#post = Post.find(params[:id])
end
def create
#post = Post.new(params[:post].permit(:title, :text))
if #post.save
redirect_to #post
else
render 'new'
end
def edit
#post = Post.find(params[:id])
end
end
def update
#post = Post.find(params[:id])
if #post.update(params[:post].permit(:title, :text))
redirect_to #post
else
render 'edit'
end
end
def destroy
#post = Post.find(params[:id])
#post.destroy
redirect_to posts_path
end
private
def post_params
params.require(:post).permit(:title, :text)
end
end
routes.rb
Myapp::Application.routes.draw do
resources :posts do
resources :comments
end
root "welcome#index"
end
I think the error has something to do with my routes.rb file, but I can't figure out exactly what. Am I nesting my routes for the comments incorrectly?

trying to render a view on my reviews index page

I am a newbie to rails, and I've been pulling out my hair trying to figure out how to render my "logs" on my "reviews" page (which is now the index page).
I keep on getting a nomethoderror even when I've defined logs in my review controller.
Reviews controller
ReviewsController < ApplicationController
def index
#reviews = Review.all.order('created_at DESC').paginate(:page => params[:page], :per_page => 2)
end
def show
#logs = #logs.all
end
def new
#review = current_user.reviews.build
end
def edit
end
def create
#review = current_user.reviews.build(review_params)
if #review.save
redirect_to #review, notice: 'review was successfully created.'
else
render action: 'new'
end
end
def update
if #review.update(review_params)
redirect_to #review, notice: 'Review was successfully updated.'
else
render action: 'edit'
end
end
def destroy
#review.destroy
redirect_to reviews_url
end
end
private
# Use callbacks to share common setup or constraints between actions.
def set_review
#review = Review.find(params[:id])
end
def correct_user
#review = current_user.reviews.find_by(id: params[:id])
redirect_to reviews_path, notice: "Not authorized to edit this review!" if #review.nil?
end
# Never trust parameters from the scary internet, only allow the white list through.
def review_params
params.require(:review,).permit(:description, :attachment)
end
my reviews/index.html/erb
<div id='reviews' class='transitions-enabled'>
<% #reviews.each do |review| %>
<div class='box panel panel-default'>
<div class='panel-body'>
<p><%= review.description %></p>
<p><strong><%= review.user.name if review.user %></strong></p>
<%= link_to Time.now.strftime("%m/%d/%Y"), review %>
<% if review.user == current_user %>
<div class='actions'>
<%= link_to edit_review_path(review) do %>
<span class="glyphicon glyphicon-edit"></span> Edit
<% end %>
<%= link_to review, method: :delete, data: { confirm: 'Are you sure?' } do %>
<span class="glyphicon glyphicon-trash"></span>Delete
<% end %>
</div>
<% end %>
</div>
</div>
<% end %>
</div>
<%= render template:"logs/show" %>
<%= link_to new_review_path do %>
<span class="glyphicon glyphicon-pencil"></span>New Review
<% end %>
When you render the logs/show template in your "index" controller action, it doesn't go through the "show" action, it just renders the show view. So in order for the logs/show template to show your logs, you also need to initialize your #logs variable in the controller, like this:
def index
#reviews = Review.all.order('created_at DESC').paginate(:page => params[:page], :per_page => 2)
#logs = #logs.all
end
That way, when the logs/show view template is called, it has a #logs array to work from.

Ruby on Rails Getting name can't be blank error when trying to add new user

I am a Ruby on Rails newbie, and am trying to put into practice some of the tutorials I have been following.
I am currently trying to get a basic user signup working.
When the signup form is completed and submitted, the Firstname and Lastname fields are blanked out and I get two error messages (I also get a failing error when running the cucumber tests):
Firstname can't be blank
Lastname can't be blank
I think I have missed something fairly obvious with the authentication code, but can't spot what I have missed.
All my code is on my github account
Controller
class UsersController < ApplicationController
before_action :set_user, only: [:show, :edit, :update, :destroy]
# GET /users
# GET /users.json
def index
#users = User.all
end
# GET /users/1
# GET /users/1.json
def show
end
# GET /users/new
def new
#user = User.new
end
# GET /users/1/edit
def edit
end
# POST /users
# POST /users.json
def create
#user = User.new(user_params)
respond_to do |format|
if #user.save
format.html { redirect_to #user, notice: 'User was successfully created.' }
format.json { render action: 'show', status: :created, location: #user }
else
format.html { render action: 'new' }
format.json { render json: #user.errors, status: :unprocessable_entity }
end
end
end
# PATCH/PUT /users/1
# PATCH/PUT /users/1.json
def update
respond_to do |format|
if #user.update(user_params)
format.html { redirect_to #user, notice: 'User was successfully updated.' }
format.json { head :no_content }
else
format.html { render action: 'edit' }
format.json { render json: #user.errors, status: :unprocessable_entity }
end
end
end
# DELETE /users/1
# DELETE /users/1.json
def destroy
#user.destroy
respond_to do |format|
format.html { redirect_to users_url }
format.json { head :no_content }
end
end
private
# Use callbacks to share common setup or constraints between actions.
def set_user
#user = User.find(params[:id])
end
# Never trust parameters from the scary internet, only allow the white list through.
def user_params
params.require(:user).permit(:firstname, :middlename, :lastname, :email, :password, :password_confirmation)
end
end
Model
class User < ActiveRecord::Base
# Include default devise modules. Others available are:
# :token_authenticatable, :encryptable, :confirmable, :lockable, :timeoutable and :omniauthable
devise :database_authenticatable, :registerable,
:recoverable, :rememberable, :trackable, :validatable
# Setup accessible (or protected) attributes for your model
attr_accessible :email, :password, :password_confirmation, :remember_me, :firstname, :lastname, :middlename
validates :firstname, :presence =>true
validates :lastname, :presence=>true
validates :email, :presence=>true, :uniqueness => { :case_sensitive => false }
before_validation :downcase_email
def name
[firstname, middlename, lastname].compact.join(' ')
end
private
def downcase_email
self.email = self.email.downcase if self.email.present?
end
end
Views User
new.erb.rb
<h1>New user</h1>
<%= render 'form' %>
<%= link_to 'Back', users_path %>
_form.rb
<%= form_for(#user) do |f| %>
<% if #user.errors.any? %>
<div id="error_explanation">
<h2><%= pluralize(#user.errors.count, "error") %> prohibited this user from being saved:</h2>
<ul>
<% #user.errors.full_messages.each do |msg| %>
<li><%= msg %></li>
<% end %>
</ul>
</div>
<% end %>
<div class="field">
<%= f.label :firstname %><br />
<%= f.text_field :firstname %>
</div>
<div class="field">
<%= f.label :lastname %><br />
<%= f.text_field :lastname %>
</div>
<div class="field">
<%= f.label :middlename %><br />
<%= f.text_field :middlename %>
</div>
<div class="field">
<%= f.label :email %><br />
<%= f.text_field :email %>
</div>
<div class="actions">
<%= f.submit %>
</div>
<% end %>
Since it looks like you're using devise, you can try running rails generate devise:views. This will generate all of the correct views for everything devise does. You might want to save the forms that you already have in case Devise tries to override them, though.