after_create destroy a record - ruby-on-rails

I have two tables bookings and rentals. A user books a car to rent and an admin approves the rental.
As the admin approves the rental. The booking is no longer needed. How can i delete the booking record at the same time as creating the rental record.
this was my attempt (i'm new to ruby so apolagies if i am being stupid)
#rental_controller.rb
after_create :delete_booking
def delete_booking
#booking = Booking.find(params[:id])
#booking.destroy
respond_to do |format|
format.html { redirect_to rental_url }
format.json { head :no_content }
end
end

After create belong in the model, not the controller. I'm assuming you have a rental model since the snippet is from the rentals controller.
In the rental model:
after_create :delete_booking
def delete_booking
#booking = Booking.where(:booking_no => self.booking_no).first
#booking.destroy
end

Ideally something like ..
# Booking.rb Model
has_one :booking
And
# Rental.rb Model
belongs_to :booking, :class_name => "Booking", :foreign_key => "booking_no"
after_create :delete_booking
private
def delete_booking
self.booking.destroy
end

Related

has_many :through add extra param in join table in one call (object creation)

I have the following code letting a user to create a new album through a join table with an extra params (creator).
In order to do it, my controller does 2 requests (one for creating the album object and the collaboration object / the other to update the collaboration object with the extra params).
I would like to know if there is a way to do this call with only one request. (add the extra "creator" params in the same time than the album creation)
Thank you.
albums_controller.rb
class AlbumsController < ApplicationController
def new
#album = current_user.albums.build
end
def create
#album = current_user.albums.build(album_params)
if current_user.save
#album.collaborations.first.update_attribute :creator, true
redirect_to user_albums_path(current_user), notice: "Saved."
else
render :new
end
end
private
def album_params
params.require(:album).permit(:name)
end
end
Album.rb
class Album < ApplicationRecord
# Relations
has_many :collaborations
has_many :users, through: :collaborations
end
Collaboration.rb
class Collaboration < ApplicationRecord
belongs_to :album
belongs_to :user
end
User.rb
class User < ApplicationRecord
has_many :collaborations
has_many :albums, through: :collaborations
end
views/albums/new
= simple_form_for [:user, #album] do |f|
= f.input :name
= f.button :submit
You can just add associated objects on the new album instance:
#album = current_user.albums.new(album_params)
#album.collaborations.new(user: current_user, creator: true)
When you call #album.save ActiveRecord will automatically save the associated records in the same transaction.
class AlbumsController < ApplicationController
def new
#album = current_user.albums.new
end
def create
#album = current_user.albums.new(album_params)
#album.collaborations.new(user: current_user, creator: true)
if #album.save
redirect_to user_albums_path(current_user), notice: "Saved."
else
render :new
end
end
private
def album_params
params.require(:album).permit(:name)
end
end
You are also calling current_user.save and not #album.save. The former does work due to fact that it causes AR to save the associations but is not optimal since it triggers an unessicary update of the user model.

product.number for user_id rails

I have a question for rails.
I have a User controller,
I have a Product controller.
I have a user id references in product:db.
How to puts User.product number in Html?
Firstly you need configure devise gem for authentication to your user model to add user_id column to your products table.
rails g migartion add_user_id_to_products user_id:integer:index
In your users model
class User < ApplicationRecord
has_many :products
end
In your products model
class Products < ApplicationRecord
belongs_to :user
end
As your user and products are associated through has_many and belongs_to.
you can as below in the products controller
class ProductsController < ApplicationController
def index
#products = Product.all
end
def new
#product = Product.new
end
def create
#product = current_user.products.build(product_params)
if #product.save
redirect_to edit_product_path(#product), notice: "Saved..."
else
render :new
end
end
private
def product_params
params.require(:product).permit( :title, :description, :category)
end
end
If the data is successfully saved into the database, you will find the user_id column of the products table filled with the id of the current_user.
To get all the products of a particular user
In your users controller show action
def show
#user_products = #user.products
end
The #user_products will have all the products belonging to the corresponding user.

How to get the right id before create in rails

I'm expanding upon M.Hartl's Sample twitter app.
What I've done is created a new model called Books. I want the books to be followable, like users, so if you are following a book you will see all comments associated with that book in your feed.
I have had minor success in creating the model, and following it. I can follow the book, say with id "2" and have the posts show in the feed. though when I try follow a user with id 2, I end up following book id "2" or get the UNIQUE constraint failed in my console. Another strange thing, if I destroy the relationship with both book and id "2" and just follow user "2", I actually get the users posts, though I can't unfollow the user from his button, I have to go to book "2" and unfollow from there.
Any ideas?
I'm thinking I need to have an if else check in my .create to make sure if Im on a book page I follow a book and not a user before committing to the database.
Any help or thoughts would be greatly appreciated.
here's some relevant code:
class User < ActiveRecord::Base
def feed
following_ids_subselect = "SELECT followed_id FROM relationships
WHERE follower_id = :user_id"
Micropost.where("book_id IN (#{following_ids_subselect})
OR user_id = :user_id", user_id: id)
end
# Follows a user.
def follow(other_user)
active_relationships.create(followed_id: other_user.id)
end
# Follows a book.
def follown(book)
active_relationships.create(followed_id: book.id)
end
# Unfollows a user.
def unfollow(other_user)
active_relationships.find_by(followed_id: other_user.id).destroy
end
# Unfollows a book.
def unfollown(book)
active_relationships.find_by(followed_id: book.id).destroy
end
# Returns true if the current user is following the other user.
def following?(other_user)
following.include?(other_user)
end
# Returns true if the current user is following the book.
def followingn?(book)
following.include?(book)
end
class RelationshipsController < ApplicationController
def create
#user = User.find(params[:followed_id])
if current_user.follow(#user)
else
#book = Book.find(params[:followed_id])
current_user.follown(#book)
end
# respond_to do |format|
# format.html { redirect_to #user }
# format.js
# end
end
class Relationship < ActiveRecord::Base
belongs_to :follower, class_name: "User"
belongs_to :followed, class_name: "User"
belongs_to :followed, class_name: "Book"
validates :follower_id, presence: true
validates :followed_id, presence: true
end

Update many-to-many association in rails (User-Team relationship aka Membership)

I just created a create feature for adding a team together with adding the members to a said team.
The form contains the following:
Name of the team.
Team's department.
Leader (value is the user id, but displayed as full name)
Members (values are user ids, but displayed also as full names) //I used a special select menu called select2.
Here are the models. I'll only show the associations and some methods related to my problem.
user.rb
class User < ActiveRecord::Base
has_many :memberships
has_many :teams, through: :memberships
accepts_nested_attributes_for :memberships, :teams
end
team.rb
class Team < ActiveRecord::Base
has_many :memberships
has_many :teams, through: :memberships
accepts_nested_attributes_for :memberships, :users
def build_membership(user_ids)
unless user_ids.blank?
user_ids.each do |id|
self.users << User.find_by_id(id)
end
end
end
end
membership.rb
class Membership < ActiveRecord::Base
belongs_to :team
belongs_to :user
#Note that leader and members are both users
end
Here is the controller, with the create and update methods.
class TeamsController < ApplicationController
def create
#team = Team.new(team_params)
#team.build_membership(build_members_array(members_params))
if #team.save
flash.now[:success] = 'Team was successfully created.'
redirect_to #team
else
flash.now[:notice] = #team.errors.full_messages
render "new"
end
end
def update
# TO-DO: update leader and members (i.e. add or remove member)
if #team.update(team_params)
flash.now[:success] = "Team was successfully updated."
redirect_to #team
else
flash.now[:notice] = #team.errors.full_messages
render "edit"
end
end
private
def team_params
params.require(:team).permit(:name,:department)
end
def members_params
params.require(:team).permit(:leader, members:[])
end
def build_user_ids_array(members)
#put ids of leader and members in an array
end
end
It seems that only the name and department attributes are only updated while the leader and the members are not. Should I create my own method again for updating the roster of the team or do something else in mind?
#team.build_membership would be if you are passing in the params to create a new user, but you are using existing User's so this wouldn't apply. You will want to instead fetch all of the User's by their id and then add that the the Team. You also need to permit the id in the members_attributes in your member_params method.
Something like:
def create
#team = Team.new(team_params)
#team.memberships << users_from_params
if #team.save
flash.now[:success] = 'Team was successfully created.'
redirect_to #team
else
flash.now[:notice] = #team.errors.full_messages
render "new"
end
end
def members_params
params.require(:team).permit(:leader, members_attributes: [:id])
end
def users_from_params
#This members_params[:members_attributes].values should be an array of `id`s
User.find(members_params[:members_attributes].values)
end

Creating a join table record through two different controllers in rails

I'm trying to get my head around the best way to add a record to a join table through alternative controllers in rails.
I have various models in my app that will require this, but I'm focusing on these two first before I transcribe the method into others, so shall use this as the example. I have a Venue and Interest model which are to be connected through VenuesInterests model (it has a couple of extra optional attributes so isn't a HABTM relationship). A user can admin a Venue instance and/or an Interest instance and therefore there should be an ability to select Venues to attach to an Interest and likewise Interests to attach to a Venue. This should be done with an Add Venues link on the Interest instance view and an Add Interests link on the Venue instance view. This would then take the user to a list of the relevant instances for them to select ones they would like to select.
Here are my models:
Venue.rb
class Venue < ActiveRecord::Base
has_many :interests, through: :venue_interests
has_many :venues_interests, dependent: :destroy
accepts_nested_attributes_for :venues_interests, :allow_destroy => true
end
Interest.rb
class Interest < ActiveRecord::Base
has_many :venues, through: :venue_interests
has_many :venues_interests, dependent: :destroy
end
VenuesInterests.rb
class VenuesInterest < ActiveRecord::Base
belongs_to :interest
belongs_to :venue
validates :interest_id, presence: true
validates :venue_id, presence: true
end
This all seems fine, however it's the controller and views that I'm struggling with. I've tried adding an extra method add_interest to the Venues controller to do the job of the create method in the VenuesInterests controller, so that there will be a different view when adding Venues to an Interest than there would be adding Interests to a Venue, otherwise I don't know how I would do this. My current Venues controller is as follows:
VenuesController.rb:
class VenuesController < ApplicationController
before_filter :authenticate_knocker!, only: [:new, :edit, :create, :update, :destroy]
respond_to :html, :json
def index
#venues = Venue.all.paginate(page: params[:page]).order('created_at DESC')
end
def show
#venue = Venue.find(params[:id])
#hash = Gmaps4rails.build_markers(#venue) do |venue, marker|
marker.lat venue.latitude
marker.lng venue.longitude
marker.infowindow venue.name
end
end
def new
#venue = Venue.new
end
def edit
#venue = Venue.find(params[:id])
end
def create
#venue = current_knocker.venues.create(venue_params)
respond_to do |format|
if #venue.save!
format.html { redirect_to #venue, notice: 'Venue was successfully created.' }
format.json { render json: #venue, status: :created, location: #venue }
else
format.html { render action: "new" }
format.json { render json: #venue.errors, status: :unprocessable_entity }
end
end
end
def update
#venue = Venue.find(params[:id])
#venue.update_attributes(venue_params)
respond_to do |format|
if #venue.update_attributes(venue_params)
format.html { redirect_to(#venue, :notice => 'Your Venue was successfully updated.') }
format.json { respond_with_bip(#venue) }
else
format.html { render :action => "edit" }
format.json { respond_with_bip(#venue) }
end
end
end
def destroy
end
def add_interests
#venues_interests = VenuesInterest.new
#interests = Interests.all.paginate(page: params[:page]).order(:name)
end
private
def venue_params
params.require(:venue).permit(:admin... etc)
end
end
This isn't currently working as I'm not sure how to reference other classes within a controller, but the important thing I'd like to know is is there a better way to do this or am I (kind of) on the right track? If anyone has a good method (perhaps a jQuery plugin) for allowing multiple selection of instances for the view, that would be great too!
In my opinion, I would take advantage of the existing update method to add the relationship between Interest and Venue. I can do like this:
def update
#venue = Venue.find(params[:id])
#venue.update_attributes(params[:venue_params])
if params[:interest_ids].present?
#venue.interests = Interest.where(id: params[:interest_ids])
#venue.save
end
#more code to handle the rendering
end

Resources