Ruby on Rails 4.0 session[cart_id] = nil - ruby-on-rails-4

In my process of learning RoR 4.0, I am following a tutorial to build a Rails project where a Cart is being implemented. My problem is that I can't place more than one item on my cart, because when I go back to the main page to select another item, my cart changes its id . I have the cart_id stored on a session variable, on a function on my application controller:
class ApplicationController < ActionController::Base
protect_from_forgery
private
def current_cart
if session[cart_id].nil? (*)
puts “ ********************* “ (*)
puts session[cart_id] (*)
end
Cart.find(session[:cart_id])
rescue ActiveRecord::RecordNotFound
cart = Cart.create
session[:cart_id] = cart.id
cart
end
end
I call this function from this controller as follows:
class LineItemsController < ApplicationController
def create
#cart = current_cart
product = Product.find(params[:product_id])
#line_item = #cart.line_items.build(:product => product)
respond_to do |format|
if #line_item.save
format.html { redirect_to(#line_item.cart,
:notice => 'Line item was successfully created.') }
format.xml { render :xml => #line_item,
:status => :created, :location => #line_item }
else
format.html { render :action => "new" }
format.xml { render :xml => #line_item.errors,
:status => :unprocessable_entity }
end
end
end
I made several testes, added the three lines of code marked as (*) to my current_cart and I notice that every time that #cart = currect_cart is executed on my lineItems Controller, session[cart_id] is nil.
How could this happen? can comeone explain this to me?
Thank you in advance for your help !

Related

Rails - Adding a "Delete" button to a Users Timetable

Hi I have a rails App where Users can have a timetable with a one to many relationship.
When i add this
<%= link_to "delete", user, method: :delete,
data: { confirm: "You sure?" } %>
to _user.html it renders a delete link which deletes a user no problem
but when i add this
<%= link_to "delete", timetable, method: :delete,
data: { confirm: "You sure?" } %>
to _timetable.html.erb it throws an error
ActionController::RoutingError (No route matches [DELETE] "/timetable.4"):
My Routes.rb
get 'password_resets/new'
get 'password_resets/edit'
root 'static_pages#home'
get 'help' => 'static_pages#help'
get 'about' => 'static_pages#about'
get 'contact' => 'static_pages#contact'
get 'timetable' => 'timetables#new'
get 'signup' => 'users#new'
get 'mobile' => 'users#mobile'
get 'login' => 'sessions#new'
post 'login' => 'sessions#create'
delete 'logout' => 'sessions#destroy'
resources :account_activations, only: [:edit]
resources :password_resets, only: [:new, :create, :edit, :update]
resources :timetables
resources :users
resources :projects
Timetable Controller
class TimetablesController < ApplicationController
before_action :logged_in_user, only: [:create, :destroy]
before_action :correct_user, only: :destroy
def index
#timetables = current_user.timetables.find(current_user)
end
def new
#user = User.find(current_user)
#timetable = Timetable.new
#timetables = #user.timetables.paginate(page: params[:page], per_page: 1)
end
def feed
Timetable.where("user_id = ?", id)
end
def show
#feed_items3 = current_user.feed.paginate(page: params[:page])
#timetable = current_user.timetables.find(params[:id])
end
def create
#timetable = Timetable.new(timetable_params)
#user = User.find(current_user)
if current_user.timetables.create(timetable_params)
flash[:success] = "Timetable created!"
redirect_to timetable_path
else
flash[:success] = "Timetable not created!"
redirect_to timetable_path
end
end
def destroy
#timetable = Timetable.find(params[:id])
#timetable.destroy
redirect_to timetables_path, notice: "The timetable #{#timetable.name} has been deleted."
end
private
def timetable_params
params.require(:timetable).permit(:name, :attachment, :id)
end
def correct_user
#project = current_user.projects.find_by(id: params[:id])
redirect_to root_url if #project.nil?
end
end
Without seeing your Controllers it is hard to be sure, but I would look at a few areas:
Specifying the path & the timetable object to be deleted:
<%= link_to "Delete Timetable", timetable_path(timetable), :method => :delete %>
Ensure that the destroy action for the timetable sits within the timetable_controller
Regarding your routes.rb file I am not sure why you need:
get 'timetable' => 'timetables#new'
and then also
resources :timetables
This is duplication - why not try use 'only' (edit to your preference):
resources :timetables, only: [:index, :new, :create, :destroy]

routing issue passing id rails 4

Firstly apologies as just when i think i have a grip on routing i find that i don't!!
When a registered user logs in to my app they are taken to the admin index view and all i am trying to do is display their user name within that view.
This is my routes config: -
Easygifts::Application.routes.draw do
get 'admin' => 'admin#index'
controller :sessions do
get 'login' => :new
post 'login' => :create
delete 'logout' => :destroy
end
get "sessions/create"
get "sessions/destroy"
resources :users
resources :admin
resources :stores do
collection do
get "writing"
get "office"
get "time"
get "home"
get "wellness"
get "travel"
get "bags"
get "leisure"
get "contact"
get "terms"
end
member do
get 'quote'
end
end
resources :products
Users login via the sessions controller and are passed on to the Admin controllers index view. Where i am trying to display their name using the following: - <th colspan="2">Welcome <%= #users.name %></th>
The Sessions controller: -
class SessionsController < ApplicationController
skip_before_action :authorize
def new
end
def create
user = User.find_by(name: params[:name])
if user and user.authenticate(params[:password])
session[:user_id] = user.id
redirect_to admin_url
else
redirect_to login_url, alert: "Invalid user/password combination"
end
end
def destroy
session[:user_id] = nil
redirect_to stores_url, notice: "Logged out"
end
end
The Users Controller: -
class UsersController < ApplicationController
before_action :set_user, only: [:show, :edit, :update, :destroy]
# GET /users
# GET /users.json
def index
#users = User.order(:name)
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 users_url, notice: "User #{#user.name} 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 users_url, notice: "User #{#user.name} 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
begin
#user.destroy
flash[:notice] = "User #{#user.name} deleted"
rescue StandardError => e
flash[:notice] = e.message
end
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(:name, :password, :password_confirmation, :add1, :add2, :add3, :add4, :post_code, :home_tel, :mobile, :ice_tel, :ni_number, :position, :image_url, :staff_num, :start_date, :birthday)
end
end
And the Admin Controller: -
class AdminController < ApplicationController
def index
#users = User.find(params[:id])
end
end
My first point of confusion is whether i should be going through the Sessions controller or the Users controller?
If it's in the Sessions controller am i supposed to write something like get 'admin#index' => :show
Or if it's in Users am i to write something like resources :users do member do get 'admin' end end
I think i have to define a controller with an action within my routes but i don't understand in this instance how to work out who is doing what.

How to send an email with an inline image in Rails 4

I am working on a rails application and want to send an email with an inline image to the email address that the user enters. I have been struggling to do it. I checked online and this is what I did.
When I enter an email in development it gives me an error saying,
ActionController::UnknownFormat
This is my ActionMailer Notifier.rb
class Notifier < ActionMailer::Base
default from: "insidespintex#gmail.com"
def enter_email(sending)
#coming = sending
attachments.inline['blank'] = {
:data => File.read("#{Rails.root.to_s + '/app/assets/images/News.png'}"),
:mime_type => "image/png",
:encoding => "base64"
}
mail :to => #coming.email, :subject => 'InsideSpintex is coming soon'
end
end
This is my ApplicationController LandingController.rb
class LandingController < ApplicationController
layout 'landingPage'
def soon
#coming = Coming.new
end
def after
render 'after'
end
def save_email
#coming = Coming.new(soon_params)
respond_to do |format|
if #coming.save
Notifier.enter_email(#coming).deliver
format.html { render action: 'after' }
#render 'after'
else
render 'soon'
end
end
end
#render 'soon'
private
def soon_params
params.require(:coming).permit(:email)
end
end
And this is my View enter_email.html.erb
<p> Hello There,</h3>
<%= image_tag attachments['News.png'] %>
Well, I think that you don't need the encoding part in your attachments.inline hash. I was using something like this on a project:
Mailer method:
attachments.inline['logo.png'] = {
data: File.read(Rails.root.join('app/assets/images/logo.png')),
mime_type: 'image/png'
}
and you are missing the .url in the view:
<%= image_tag attachments['logo.png'].url %>

NoMethodError in Courses#edit undefined method `model_name'

I need help with the follow problem. I have been looking at similar questions but am still unable to find the solution to the problem. I am currently having this problem.
NoMethodError in Courses#edit
undefined method `model_name' for #Class:0xb5068474
the error seems to be with this line of code.
<%= simple_fields_for #lesson do |f| %>
<%= f.input :lesson_name %>
<%end%>
The lesson database is link to the course database, where course has_many lessons and lesson belongs_to course. I think that the problem may be due to my controller code. I am relatively new and not very sure about how to go about solving this problem.
I am able to go to create page to create that relation but nothing else is saved inside the database but the id of course and lesson. However, when i go to the edit page for course, this error pops out.
courses_controller.rb
class CoursesController < ApplicationController
before_action :set_course, only: [:show, :edit, :update, :destroy]
before_action :authenticate_user!, :except => [:show,:index]
# GET /courses
# GET /courses.json
def index
#courses = Course.all
end
# GET /courses/1
# GET /courses/1.json
def show
end
# GET /courses/new
def new
#course = Course.new
#lesson = #course.lessons.build
end
# GET /courses/1/edit
def edit
#course = Course.find(params[:id])
#lesson = #course.lessons
end
# POST /courses
# POST /courses.json
def create
#course = Course.new(course_params)
#course.lessons.new(lesson_params)
respond_to do |format|
if #course.save
format.html { redirect_to #course, notice: 'Course was successfully created.' }
format.json { render action: 'show', status: :created, location: #course }
else
format.html { render action: 'new' }
format.json { render json: #course.errors, status: :unprocessable_entity }
end
end
end
# PATCH/PUT /courses/1
# PATCH/PUT /courses/1.json
def update
respond_to do |format|
if #course.update(course_params)
#course.lesson.update_attributes(lesson_params)
#course.staff_ids=params[:course][:staff_ids]
format.html { redirect_to #course, notice: 'Course was successfully updated.' }
format.json { head :no_content }
else
format.html { render action: 'edit' }
format.json { render json: #course.errors, status: :unprocessable_entity }
end
end
end
# DELETE /courses/1
# DELETE /courses/1.json
def destroy
#course.destroy
respond_to do |format|
format.html { redirect_to courses_url }
format.json { head :no_content }
end
end
private
# Use callbacks to share common setup or constraints between actions.
def set_course
#course = Course.find(params[:id])
end
# Never trust parameters from the scary internet, only allow the white list through.
def course_params
params.require(:course).permit(:course_code, :course_name, :year_of_study, :discipline, :Acad_unit, :cohort_size, :remark)
end
def lesson_params
params.require(:lesson).permit(:lesson_type, :lesson_name, :num_lesson, :frequency)
end
end
lesson.rb
class Lesson < ActiveRecord::Base
belongs_to :course
end
course.rb
class Course < ActiveRecord::Base
validates_presence_of :course_code, :course_name
validates_uniqueness_of :course_code, :course_name
validates :year_of_study, :Acad_unit, :cohort_size, :numericality => { :greater_than => 0}
has_and_belongs_to_many :staffs, join_table: :scheduleCourse
has_many :lessons, dependent: :destroy
end
Please give me some advise. Thanks in advance
The error that you get:
undefined method `model_name` for #Class:0xb5068474
Means that simple_fields_for method is doing something like #lesson.class.model_name, which is ok when object you pass (#lesson) is an instance of ActiveRecord::Base, but in edit action you define #lesson
#lesson = #course.lessons
As a relation, so it is not one Lesson instance, it is internal ActiveRecord object for storing relations. If for instance you call first on it:
#lesson = #course.lessons.first
This should work. Or you can iterate through collection of lessons in view to create form for each one of them, it depends on what you want to do.

Querying Active Records and Foreign Key Help [Rails 4]

I know there are probably many different ways to do this, but using http://guides.rubyonrails.org/active_record_querying.html, I have been unable to find the best way that works for me.
I am making a forum using RoR, and I came across a problem when deleting posts from topics.
Each Topic has many posts. Each post has one topic.
When you post in the topic, it updates the topic table with who last posted and the time. However, when you delete a post, it keeps the old data of the post.
When I delete a post, I need to update the topic table with the previous post's data.
I know after deleting, I need to query all the posts in a topic, find the last one and use its data to update the topic.
How do I do that though?
The Query would be something like
SELECT * FROM posts WHERE (topic_id = topic.id) ORDER BY id DESC
Post Controller
class PostsController < ApplicationController
before_action :set_post, only: [:show, :edit, :update, :destroy]
def index
#posts = Post.all
end
def show
end
def new
#post = Post.new
end
def edit
#post = Post.find(params[:id])
end
def create
#post = Post.new(
:content => params[:post][:content],
:topic_id => params[:post][:topic_id],
:user_id => current_user.id)
if #post.save
#topic = Topic.find(#post.topic_id)
#topic.update_attributes(
:last_poster_id => current_user.id,
:last_post_at => Time.now)
flash[:notice] = "Successfully created post."
redirect_to "/topics/#{#post.topic_id}"
else
render :action => 'new'
end
end
def update
#post = Post.find(params[:id])
if #post.update_attributes(params[:post].permit!)
#topic = Topic.find(#post.topic_id)
#topic.update_attributes(:last_poster_id => current_user.id, :last_post_at => Time.now)
flash[:notice] = "Successfully updated post."
redirect_to #post
else
render :action => 'edit'
end
end
def destroy
#post = Post.find(params[:id])
#post.destroy
**# WHAT QUERY STATEMENT GOES HERE**
#topic.update_attributes(
:last_poster_id => #post.user_id,
:last_post_at => #post.created_at)
redirect_to "/topics/#{#post.topic_id}"
end
end
Try using this code:
def destroy
#post = Post.find(params[:id])
#topic = #post.topic
#post.destroy
last_post = #topic.reload.posts.last
#topic.update_attributes(last_poster_id: last_post.user_id, last_post_at: last_post.created_at)
redirect_to #topic
end