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?
Related
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!
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'm making a single page application based on Futureme.org for practice. The user goes to the home page, sees a form to put their email address, subject, and the body of their message and sends it.
The problem I am having is I get an error "First argument in form cannot contain nil or be empty". Here is my code;
Model;
class Letter < ActiveRecord::Base
VALID_EMAIL_REGEX = /\A[\w+\-,]+#[a-z\d\-.]+\.[a-z]+\z/i
validates_presence_of :email, presence: true, format: { with: VALID_EMAIL_REGEX },
uniqueness: { case_sensitive: false }
validates_length_of :subject, presence: true, length: { maximum: 50 }
validates_presence_of :message
end
Controller;
class LettersController < ApplicationController
def new
#letter = Letter.new
end
def create
#letter = Letter.new(params[:letter])
if #letter.save
redirect_to letters_path, :notice => "Your letter was sent!"
else
render "new"
end
end
end
View form;
<%= form_for #letter, :html => {:class => 'form-horizontal'} do |f| %>
<% if #letter.errors.any? %>
<div class="error_messages">
<h2><%= pluralize(#letter.errors.count, "error")%>stopped this message from being saved</h2>
<ul>
<% #letter.errors.full_messages.each do |msg| %>
<li><%= msg %></li>
<% end %>
</ul>
<% end %>
<div class="field">
<%= f.label :email %><br />
<%= f.text_field :email %>
</div>
<div class="field">
<%= f.label :subject %><br />
<%= f.text_field :subject %><br />
</div>
<div class="field">
<%= f.label :message, "Message" %><br />
<%= f.text_area :message, size: "60x10" %>
</div>
<div class="actions"><%= f.submit "Submit", class: "btn btn-small btn-primary" %></div>
<% end %>
The form is on the home page which is in the "Welcome Controller".
Any help would be great.
It looks like you build letter in action new when form is drawn on other view :)
You should move #letter = Letter.new to appropriate action
One of the variant is:
#WelcomeController
def home
#letter = Letter.new
end
#LettersController
def create
#letter = Letter.new(params[:letter])
if #letter.save
redirect_to letters_path, :notice => "Your letter was sent!"
else
render "welcome/home"
end
end
be careful if you prepare some data in action home you should care about initializing them for action create when validation failed because you render "welcome/home" view
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?
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.