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.
Related
I am following this tutorial just to learn more about implementing coffeescript.
My model is
class Url < ActiveRecord::Base
validates :url, presence: true
end
controller
class UrlsController < ApplicationController
def new
#shortened_url = Url.new
end
def create
#shortened_url = Url.new(url_params)
if #shortened_url.save
flash[:shortened_id] = #shortened_url.id
redirect_to new_url_url
else
render :action => "new"
end
end
def show
#shortened_url = Url.find(params[:id])
redirect_to #shortened_url.url
end
private
def url_params
params.require(:url).permit(:url)
end
end
end
coffeescript
$(document).ready ->
preview = $("#preview-url")
$('#url_url').keyup ->
current_value = $.trim #value
if current_value is ''
preview.hide().attr 'src', ''
else
preview.show().attr 'src', current_value
app/views/layouts/application.rb
<!DOCTYPE html>
<html>
<head>
<title>Shorty</title>
<%= stylesheet_link_tag 'application', media: 'all', 'data-turbolinks-track' => true %>
<%= javascript_include_tag 'application', 'data-turbolinks-track' => true %>
<%= csrf_meta_tags %>
</head>
<body>
<% if flash[:shortened_id].present? %>
<p class='shortened-link'>
The shortened url is available <%= link_to 'here',
url_url(flash[:shortened_id]) %>.
(Right click and copy link to share it).
</p>
<% end %>
<%= yield %>
</body>
</html>
app/views/urls/new.html.erb
<h1>Add a new URL</h1>
<%= form_for #shortened_url do |form| %>
<p>
<%= form.label :url, "Your URL:" %>
<%= form.text_field :url %>
</p>
<% if #shortened_url.errors[:url].any? %>
<p class='error-messages'>
The given url <%= #shortened_url.errors[:url].to_sentence %>.
</p>
<% end %>
<p class='buttons'>
<%= form.submit "Shorten my URL" %>
</p>
<% end %>
<iframe id='preview-url' style='width: 600px; height: 400px; display: none'></iframe>
config/routes.rb
Rails.application.routes.draw do
resources :urls, :only => [:new, :show, :create]
# get '/', to: 'urls#create', as: :new_url_url
root :to => redirect('/urls/new')
end
the error is
No route matches [GET] "/urls/www.rte.ie"
I assume the coffeescript is being executed because the above address is the url I entered inthe text box and the iframe is invisible until an url is provided
It seems you need to add the protocol to the url, otherwise the redirect won't work when you do redirect_to #shortened_url.url in your show action. You can do that in your model with a before_save like this:
class Url < ActiveRecord::Base
before_save :ensure_protocol
private
def ensure_protocol
self.url = "http://#{url}" unless url_protocol_present?
end
def url_protocol_present?
u = URI.parse(url)
u.scheme
end
end
Also, I think you have a typo in your new action: what is new_url in the redirect_to statement?
I am new to ruby on rails and i want to create a session for each signed in user.
but I get that error.
In my controller I have :
class SessionsController < ApplicationController
def new
end
def create
user =User.find_by pseudo :params[:pseudo]
if user
session[:user_id]=user.id
flash[:notice]= "you are signed in! "
redirect root_url
else
flash.now[:alert]= "wrong password/pseudo"
render 'new'
end
end
def destroy
session[:user_id]=nil
flash[:notice]='You are now signed out'
redirect root_url
end
end
in my new.html.erb:
<h1>Sessions#new</h1>
<%= form_tag sessions_path do %>
<div>
<%=label_tag 'pseudo', 'pseudo' %>
<%= text_field_tag 'pseudo' %>
</div>
<div>
<%= label_tag 'password', 'password' %>
<%= password_field_tag 'password' %>
</div>
<%= submit_tag 'log in' %>
<% end %>
and in my index I have :
<h1>Users#index</h1>
<% if current_user.present? %>
Welcome <%= current_user.pseudo %> | <%= link_to 'Sign out' , logout_path %>
<% else %>
<%= link_to 'Register', new_user_url %><br/>
<%= link_to 'SignIn', login_path %>
<% end %>
in the application_controller.rb:
class ApplicationController < ActionController::Base
# Prevent CSRF attacks by raising an exception.
# For APIs, you may want to use :null_session instead.
protect_from_forgery with: :exception
helper_method :current_user
private
def current_user
User.find_by id: session[:user_id] if session[:user_id]
end
end
and that error is related to "user =User.find_by pseudo :params[:pseudo]" and i did not understand why
I am trying to show the 'status' & 'project' from an '#user' on that users profile page, I believe I have the correct relationships etc but the error I am getting is that I cannot call render multiple times in one action.
class ProfilesController < ApplicationController
def show
#user = User.find_by_profile_name(params[:id])
if #user
#statuses = #user.statuses.all
render actions: :show
else
render file: 'public/404', status: 404, formats: [:html]
end
#user = User.find_by_profile_name(params[:id])
if #user
#projects = #user.projects.all
render actions: :show
else
render file: 'public/404', status: 404, formats: [:html]
end
end
end
What is the best way to express the above, to render both items on the users profile page without calling render twice?
This is my view:
<div class="container">
<div class="page-header">
<h1><%= "Hi " + #user.first_name + "!" %>
</div>
<div class="col-md-6 col-md-offset-3">
<%= link_to "Create Project", new_project_path, class: "btn btn-success btn-block" %>
</div>
<% if #statuses %>
<% #statuses.each do |status| %>
<div class="well">
<%= status.content %>
<hr />
<%= link_to time_ago_in_words(status.created_at), status_path(status) %> ago
</div>
<% end %>
<% end %>
<% if #projects %>
<% #projects.each do |project| %>
<div class="well">
<%= project.title %>
<hr />
<%= link_to time_ago_in_words(project.created_at), projects_path(project) %> ago
</div>
<% end %>
<% end %>
</div>
Thanks for your time!
Try as below.
class ProfilesController < ApplicationController
def show
#user = User.find_by_profile_name(params[:id])
if #user
#statuses = #user.statuses.all
#projects = #user.projects.all
render action: :show
else
render file: 'public/404', status: 404, formats: [:html]
end
end
end
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.
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?