How do i sort by date? - ruby-on-rails

am new to rails, I have a rails app that allows me to create a deadline by providing a title, date and description and it creates a countdown, the problem is I want to sort all the deadlines by the date entered, how do i do that in my index method?
class DeadlinesController < ApplicationController
def new
#deadline = current_user.deadlines.new
end
def create
#deadline = current_user.deadlines.new(params[:deadline].permit(:title, :date, :description))
if #deadline.save
redirect_to #deadline
else
render 'new'
end
end
def show
#deadline = Deadline.find(params[:id])
end
def edit
#deadline = current_user.deadlines.find(params[:id])
end
def index
#deadlines = current_user.deadlines.all
#deadlines = current_user.deadlines.paginate(:page => params[:page], :per_page => 5)
end
def update
#deadline = current_user.deadlines.find(params[:id])
if #deadline.update(params[:deadline].permit(:title, :date, :description))
redirect_to #deadline
else
render 'edit'
end
end
def destroy
#deadline = current_user.deadlines.find(params[:id])
#deadline.destroy
redirect_to deadlines_path
end
private
def post_params
params.require(:deadline).permit(:title, :date, :description)
end
end
deadlines model:
class Deadline < ActiveRecord::Base
validates :title, presence: true,
length: { minimum: 8 }
validates :date, presence: true
validates :description, presence: true,
length: { maximum: 230 }
#validates_format_of :date, :with => /\A[0-9]{4}-[0-1][0-9]-[0-3][0-9]\z/, :message => "Enter Date in this format: YYYY-MM-DD"
belongs_to :user
end

#deadlines = current_user.deadlines.order(:date)
.paginate(:page => params[:page], :per_page => 5)

You can use the order method
#deadlines = current_user.deadlines.order(:date)
You can also specify ascending or descending using,
#deadlines = current_user.deadlines.order(date: :asc) # Ascending
#deadlines = current_user.deadlines.order(date: :desc) # Descending

Related

Undefined method `keys' for nil:NilClass after include Paperclip

Im new in ruby on rails and after I included papperclip i get this error if i try to change photo.
If I change create method like in a README.md on paperclip`s github:
def create
#hotel = Hotel.create( hotel_params )
end
private
# Use strong_parameters for attribute whitelisting
# Be sure to update your create() and update() controller methods.
def hotel_params
params.require(:hotel).permit(:name, :photo, :room_description, :price_for_room, :breakfast, :country, :state, :city, :street)
end
I get the same error in Create method. Could you help me? What am I missing here?
Ruby 1.9.3
Rails 4
Paperclip 4.2.0
Error screenshot
hotels_controller.rb
class HotelsController < ApplicationController
before_action :signed_in_user, except: [:index, :show]
def index
#hotels = Hotel.paginate(:page => params[:page], :per_page => 5)
end
def show
#hotel = Hotel.find(params[:id])
#comments = #hotel.comments
end
def new
#hotel = Hotel.new
end
def edit
#hotel = Hotel.find(params[:id])
end
def create
#hotel = current_user.hotels.new(params[:hotel])
if #hotel.save
redirect_to #hotel, notice: "Hotel was successfully created."
else
render "new"
end
end
def update
#hotel = Hotel.find(params[:id])
if #hotel.update_attributes(params[:hotel])
redirect_to #hotel, notice: "Hotel was successfully updated."
else
render "edit"
end
end
def destroy
#hotel = Hotel.find(params[:id])
#hotel.destroy
redirect_to hotels_url
end
end
hotel.rb
class Hotel < ActiveRecord::Base
has_many :comments
belongs_to :user
has_many :ratings
has_many :raters, :through => :ratings, :source => :users
validates :name, presence: true, length: { minimum: 5 }
validates :room_description, presence: true
validates :price_for_room, presence: true, numericality: true
validates_associated :comments
has_attached_file :photo, :styles => { :medium => "500x500>", :thumb => "100x100>" }, :default_url => "/images/:style/missing.png"
validates_attachment_content_type :photo, :content_type => /\Aimage\/.*\Z/
def update_average_rating
#value = 0
self.ratings.each do |rating|
#value = #value + rating.value
end
#total = self.ratings.size
update_attributes(average_rating: #value.to_f / #total.to_f)
end
end
As you are using Rails4, your update action should be like this
def update
#hotel = Hotel.find(params[:id])
if #hotel.update_attributes(hotel_params) #Here
redirect_to #hotel, notice: "Hotel was successfully updated."
else
render "edit"
end
end

Unable to make after_create to work

I'm creating a ticket booking app for my sample project using Ruby on Rails 4.1. Three are three models - Events, Tickets and Bookings. Events have many tickets and bookings. Tickets have many bookings and they belong to events. Bookings belongs to events and tickets.
Here's the ticket model:
class Ticket < ActiveRecord::Base
belongs_to :event
has_many :bookings
belongs_to :user
validates :ticket_name, :terms_conditions, presence: true
validates_date :booking_start_date, on: :create, on_or_after: :today
validates_date :booking_end_date, after: :booking_start_date
validates :ticket_price, presence: true, numericality: true
validates :ticket_quantity, :minimum_quantity, :maximum_quantity, presence: true, numericality: { only_integer: true }
before_create :check_start_date
before_update :check_start_date
def check_start_date
if (self.booking_start_date >= DateTime.now) && (self.booking_end_date != DateTime.now)
self.status = 'Open'
else
self.status = 'Closed'
end
end
def maximum_tickets_allowed
(1..maximum_quantity.to_i).to_a
end
end
The bookings model:
class Booking < ActiveRecord::Base
belongs_to :event
belongs_to :ticket
has_many :charges
validates :buyer_name, presence: true
validates :order_quantity, presence: true, numericality: { only_integer: true }
validates :email, presence: true, format: { with: /\A[^#\s]+#([^#.\s]+\.)+[^#.\s]+\z/ }
def total_amount
ticket.ticket_price.to_i * order_quantity.to_i
end
def check_ticket_count
count = ticket.ticket_quantity.to_i - order_quantity.to_i
ticket.update_attribute(:ticket_quantity, count)
end
end
The bookings controller:
class BookingsController < ApplicationController
before_action :authenticate_user!, only: [:index, :destroy]
def index
#event = Event.find(params[:event_id])
##bookings = #event.bookings.all
#bookings = #event.bookings.paginate(page: params[:page], per_page: 10)
end
def new
#event = Event.find(params[:event_id])
#ticket = #event.tickets.find(params[:ticket_id])
#booking = Booking.new
end
def create
#event = Event.find(params[:event_id])
#ticket = #event.tickets.find(params[:ticket_id])
#booking = #event.bookings.create(booking_params)
#booking.ticket = #ticket
Stripe.api_key = Rails.configuration.stripe[:secret_key]
#token = params[:stripeToken]
#amount = #booking.total_amount
begin
customer = Stripe::Customer.create(
:email => #booking.email,
:card => params[:stripeToken]
)
charge = Stripe::Charge.create(
:customer => customer.id,
:amount => #amount,
:currency => "usd",
#:card => token
)
flash[:notice] = "Thanks for the order"
rescue Stripe::CardError => e
flash[:danger] = e.message
end
if #booking.save
BookingMailer.booking_confirmation_user(#booking).deliver
flash[:notice] = "You've successfully booked the tickets!"
redirect_to [#event, #booking]
else
render 'new'
end
end
def show
#event = Event.find(params[:event_id])
#booking = #event.bookings.find(params[:id])
end
def destroy
#event = Event.find(params[:event_id])
#booking = #event.bookings.find(params[:id])
#booking.destroy
redirect_to event_bookings_path
end
private
def booking_params
params.require(:booking).permit(:buyer_name, :email, :mobile, :address, :order_quantity, :ticket_id)
end
end
The check_ticket_count method in Booking.rb works fine as long as I don't an add after_create :check_ticket_count method. The moment I add that after_create method, the app throws the "undefined method `ticket_quantity' for nil:NilClass" error. How to get past this?
Looks like you should first associate ticket with booking, and only then create booking.
#booking = #event.bookings.new(booking_params)
#booking.ticket = #ticket
#booking.save
Hopefully you will ask questions with less code next time.

creating an object with has_many association results in item can not be blank

I have following associations and the related controller, in my form I am adding every field as it should be. But I still get an error Ratings item can't be blank when I try to create an Item. I am using Rails 4.0 . I did searched extensively for this but could not still find what I am doing wrong. Thankyou!
class Item < ActiveRecord::Base
has_many :ratings, dependent: :destroy
accepts_nested_attributes_for :ratings, :allow_destroy => true
validates :name , :length => { minimum: 3 }
validates :category , :length => { minimum: 3 }
end
class Ratings < ActiveRecord::Base
belongs_to :user
belongs_to :item
default_scope -> { order('created_at DESC') }
validates :user_id, :presence => true
validates :item_id, :presence => true
validates_numericality_of :rating, :greater_than_or_equal_to => 0
validates_numericality_of :rating, :less_than_or_equal_to => 5
end
class ItemsController < ApplicationController
before_action :set_item, only: [:show]
before_action :user_signed_in?, only: :create
def create
#item = Item.new
#rating = #item.ratings.build
#rating.comment = params[:item][:ratings_attributes][:comment]
#rating.rating = params[:item][:ratings_attributes][:rating]
#rating.user_id = current_user.id
#item.name = params[:item][:name]
#item.url = params[:item][:url]
#item.full_address = params[:item][:full_address]
#item.city = params[:item][:city]
#item.country = params[:item][:country]
#item.category = params[:item][:category]
respond_to do |format|
if #item.save
#TODO create rating here (First rating of an Item)
flash[:success] = "Welcome to inmyopnion"
format.html { redirect_to #item, notice: 'Item was successfully created.' }
format.json { render action: 'show', status: :created, location: #item }
else
format.html { render action: 'new' }
format.json { render json: #item.errors, status: :unprocessable_entity }
end
end
end
def new
#item = Item.new
end
def show
end
def destroy
end
private
def set_item
#item = Item.find(params[:id])
end
def item_params
params.require(:item).permit(:name, :url, :full_address, :city, :country, :category, :ratings_attributes => [:rating, :comment])
end
def user_signed_in?
#TODO: should display should sign in to rate an item
redirect_to(root_url) unless signed_in?
end
end
Simplify your controller! Since you are allowing nested_attributes this should be sufficient:
#item = Item.create(params[:item])
The problem might be caused by #rating object not being saved.
I got it working by commenting the below given line in
class Ratings < ActiveRecord::Base
validates :item_id, :presence => true
but my association rspec test fails and saves a Ratings without an item_id.
Rest of the code is similar to what I posted as
#item = Item.create(params[:item])
gives ActiveModel::ForbiddenAttributesError
Alright much playing with the code and docs of nested_attributes finally a working program that validates association too. These are the changes (marked in between ** .... **) listed below
class Item < ActiveRecord::Base
has_many :ratings, dependent: :destroy, **inverse_of: :item**
accepts_nested_attributes_for :ratings, :allow_destroy => true
validates :name , :length => { minimum: 3 }
validates :category , :length => { minimum: 3 }
end
class Ratings < ActiveRecord::Base
belongs_to :user
belongs_to :item, **inverse_of: :ratings**
default_scope -> { order('created_at DESC') }
validates :user_id, :presence => true
validates_presence_of :item
validates_numericality_of :rating, :greater_than_or_equal_to => 0
validates_numericality_of :rating, :less_than_or_equal_to => 5
end
Still not able to create one from #item = Item.create(params[:item]) which still gives an gives
ActiveModel::ForbiddenAttributesError as suggested by #BroiSatse and also the docs of nested_attributes that should not be the case
the problem might be in
class ItemsController < ApplicationController
def item_params
params.require(:item).permit(:name, :url, :full_address, :city, :country, :category, :ratings_attributes => [:rating, :comment])
end
will work on to resolve that too and post an answer if I find a solution.

undefined method `unread_messages' in controller

I am working on the unread folder for my inbox messaging system. I received a undefined method `unread_messages' when going to /users/1/messages?mailbox=unread and it's pointing to the messages controller. However I have unread_messages defined in the user.rb so that it shows unread messages in the inbox, so I'm assuming the code should also work for the unread folder. Any help would be appreciated.
user.rb:
class User < ActiveRecord::Base
has_secure_password
attr_accessible :role, :age, :age_end, :password_confirmation, :about_me, :feet, :inches, :password, :birthday, :career, :children, :education, :email, :ethnicity, :gender, :height, :name, :password_digest, :politics, :religion, :sexuality, :user_drink, :user_smoke, :username, :zip_code
validates_uniqueness_of :email
validates_format_of :email, with: /^[-a-z0-9_+\.]+\#([-a-z0-9]+\.)+[a-z0-9]{2,4}$/i
validates_presence_of :password, :on => :create
has_many :galleries
has_many :photos, :through => :galleries
before_create { generate_token(:auth_token) }
ROLES = %w[admin user guest banned]
# models/user.rb
after_create :setup_gallery
def received_messages
Message.received_by(self)
end
def unread_messages?
unread_message_count > 0 ? true : false
end
def sent_messages
Message.sent_by(self)
end
# Returns the number of unread messages for this user
def unread_message_count
eval 'messages.count(:conditions => ["recipient_id = ? AND read_at IS NULL", self.user_id])'
end
def to_s; username
end
def has_role?(role_name)
role.present? && role.to_sym == role_name.to_sym
end
def send_password_reset
generate_token(:password_reset_token)
self.password_reset_sent_at = Time.zone.now
save!
UserMailer.password_reset(self).deliver
end
def generate_token(column)
begin
self[column] = SecureRandom.urlsafe_base64
end while User.exists?(column => self[column])
end
private
def setup_gallery
self.galleries << Gallery.create
end
end
messages_controller:
def index
if params[:mailbox] == "sent"
#messages = #user.sent_messages
elsif params[:mailbox] == "inbox"
#messages = #user.received_messages
#elsif params[:mailbox] == "archieved"
# #messages = #user.archived_messages
end
if params[:mailbox] == "unread"
#messages = #user.unread_messages
end
end
def new
#message = Message.new
if params[:reply_to]
#reply_to = User.find_by_user_id(params[:reply_to])
unless #reply_to.nil?
#message.recipient_id = #reply_to.user_id
end
end
end
def create
#message = Message.new(params[:message])
#message.sender_id = #user.id
if #message.save
flash[:notice] = "Message has been sent"
redirect_to user_messages_path(current_user, :mailbox=>:inbox)
else
render :action => :new
end
end
def show
#message = Message.find(params[:id])
#message.readingmessage if #message.recipient == current_user
end
def destroy
#message = Message.find(params[:id])
#message.destroy
flash[:notice] = "Successfully deleted message."
redirect_to user_messages_path(#user, #messages)
end
def delete_multiple
if params[:delete]
params[:delete].each { |id|
#message = Message.find(id)
#message.mark_message_deleted(#message.id,#user.id) unless #message.nil?
}
flash[:notice] = "Messages deleted"
end
redirect_to user_messages_path(#user, #messages)
end
private
def set_user
#user = current_user
end
end
message.rb:
attr_accessible :subject, :body, :sender_id, :recipient_id, :read_at,:sender_deleted,:recipient_deleted
validates_presence_of :subject, :message => "Please enter message title"
belongs_to :sender,
:class_name => 'User',
:foreign_key => 'sender_id'
belongs_to :recipient,
:class_name => 'User',
:foreign_key => 'recipient_id'
# marks a message as deleted by either the sender or the recipient, which ever the user that was passed is.
# When both sender and recipient marks it deleted, it is destroyed.
def mark_message_deleted(id,user_id)
self.sender_deleted = true if self.sender_id == user_id
self.recipient_deleted = true if self.recipient_id == user_id
(self.sender_deleted && self.recipient_deleted) ? self.destroy : self.save!
end
# Read message and if it is read by recipient then mark it is read
def readingmessage
self.read_at ||= Time.now
save
end
# Based on if a message has been read by it's recipient returns true or false.
def read?
self.read_at.nil? ? false : true
end
def self.received_by(user)
where(:recipient_id => user.id)
end
def self.not_recipient_deleted
where("recipient_deleted = ?", false)
end
def self.sent_by(user)
Message.where(:sender_id => user.id)
end
end
First of all, you've defined unread_messages? method, not unread_messages
Secondly, you should not use ? : in unread_messages? method:
unread_messages_count > 0
is enough.
You should define unread_messages method in your User model. I can't show the inner code in this method because I don't know your models relations.
You defined
unread_messages? # note the question mark
Then referred to it as
#user.unread_messages # no question mark
You probably want a method
def unread_messages ## which holds the actual unread messages and does not return boolean

Access Param in model

I know this is something you can't do inside of rails or aren't supposed to do but I need to somehow get the amount a user is inputing in a field of the form and use that value.
This is what my model looks like
class Deposit < ActiveRecord::Base
belongs_to :credit_card
belongs_to :user
validates :credit_card, presence: true
validates :user, presence: true
validates :tx_type, inclusion: %w(debit credit)
# validates :amount, presence: true, numericality: true
before_create :add_transaction_to_merchant
after_create :update_user_balance
attr_readonly :credit_card_id, :user_id, :fee_id, :tx_type, :status, :merchant_tx_id
attr_accessible :tx_type, :amount, :status, :merchant_tx_id, :credit_card_id,
:user_id, :user
def amount
return attributes[:amount] if attributes[:amount]
set_amount
end
def tx_type
attributes[:tx_type] || 'debit'
end
def send_receipt
Resque.enqueue(PaymentCompletedSender, self.id)
end
def update_user_balance
user_balance =user.balance + set_amount
user.balance = user_balance
user.save
end
private
def add_transaction_to_merchant
set_amount
return false if credit_card.nil?
return true unless amount > 0
result = Braintree::Transaction.sale(
amount: amount,
payment_method_token: credit_card.token,
options: { submit_for_settlement: true }
)
if result.success?
self.merchant_tx_id = result.transaction.id
# status will be authorized or submitted_for_settlement
self.status = result.transaction.status
else
errors.add(:base, result.message)
if result.transaction.nil?
# validation errors prevented transaction from being created
logger.error(result.errors)
else
self.merchant_tx_id = result.transaction.id
# status will be processor_declined, gateway_rejected, or failed
self.status = result.transaction.status
end
end
end
def set_amount
attributes[:amount]
end
end
The Controller:
# POST /deposits
# POST /deposits.json
def create
#deposit = Deposit.new(params[:deposit])
#deposit.user = current_user
#deposit.credit_card = current_user.credit_cards.try(:first)
binding.pry
respond_to do |format|
if #deposit.save
format.html { redirect_to "/", notice: 'Deposit was successfully created.' }
format.json { render json: #deposit, status: :created, location: #deposit }
else
format.html { render action: "new" }
format.json { render json: #deposit.errors, status: :unprocessable_entity }
end
end
end
This is what is params the form is sending
{"utf8"=>"✓",
"authenticity_token"=>"r0M0sRr7QO9kl0IWrJSgvj45DFrC6mbbuA+ttgEaUI0=",
"deposit"=>{"amount"=>"100"},
"commit"=>"Pay Now"}
Any thoughts on how to return the value of amount from the form in the model?
you are doing this right? #deposit = Deposit.new(params[:deposit]) if you remove the amount and set_amount method in the model, you should be able to just use amount or self.amount in the model so the following should be enough
def add_transaction_to_merchant
return false if credit_card.nil?
return true unless amount > 0
result = Braintree::Transaction.sale(
amount: amount,
payment_method_token: credit_card.token,
options: { submit_for_settlement: true }
)

Resources