I am trying to create a booking functionality where users can book a car for a specific amount of time:
I have set up all my User functionality using devise and this is what my user model looks like at the moment:
class User < ApplicationRecord
# Include default devise modules. Others available are:
# :confirmable, :lockable, :timeoutable and :omniauthable
devise :database_authenticatable, :registerable, :recoverable,
:rememberable, :trackable, :validatable,
:omniauthable, :omniauth_providers => [:facebook , :google_oauth2]
end
I have also created a cars scaffold using rails g scaffold which hold the fields: name, make, model, number_plate and color
This is what my car model looks like at the moment:
class Car < ApplicationRecord
end
I want to make a bookings scaffold that is connected to both the tables. So that when a user makes a booking they can input the car name into the booking form and it will associate the booking with the car that has the same name.
I was thinking of running the scaffold command like this:
rails g scaffold Booking user:references car:references start_time:string end_time:string car_name:string
where the car name is what is used to connect the booking to a specific car
and then specifying the relationships in the models:
class User < ApplicationRecord
has_many :bookings
# Include default devise modules. Others available are:
# :confirmable, :lockable, :timeoutable and :omniauthable
devise :database_authenticatable, :registerable, :recoverable,
:rememberable, :trackable, :validatable,
:omniauthable, :omniauth_providers => [:facebook , :google_oauth2]
end
class Bookings < ApplicationRecord
belongs_to :user
has_one :car , :foreign_key => "car_name",
end
class Car < ApplicationRecord
belongs_to and has_many :bookings
end
I havent tried making a booking scaffold yet and really just wanted to ask if im going in the right direction in terms of what i want to do before i start. Any tips would be greatly appreciated
What you need is just a standard join model:
class User < ApplicationRecord
has_many :bookings
has_many :cars, through: :bookings
end
class Bookings < ApplicationRecord
belongs_to :user
# KISS. Just use an id for the foreign key
belongs_to :car
end
class Car < ApplicationRecord
has_many :bookings
has_many :users, through: :bookings
end
I want to make a bookings scaffold that is connected to both the
tables. So that when a user makes a booking they can input the car
name into the booking form and it will associate the booking with the
car that has the same name.
This is bound to not be very user friendly in reality as the user would have to enter the name exactly like the value in the DB. You also want to stick to convention and use IDs for foreign key associations, KISS. Instead create a select:
<%= form_for(#booking) do |f| %>
<div class="row">
<%= f.label :car_id, 'Select your car' %>
<%= f.collection_select :car_id, Car.all, :id, :name %>
</div>
<% end %>
If you really want to have that exact feature you should implement it as an AJAX autocomplete*.
Related
i'm currently working on building a site like freelancer using RoR, but i'm stuck somewhere, my user table which was generated with devise has a role column which can be admin, client or freelancer. Also i have a skills table which belongs to user but i don't want every user to have skills except from the users with the role of freelancer, how do i go about this, i'm currently using cancancan for user authorization and devise for authentication, is roles the best solution to this or STI and how would you advice me to approach this problem, here's an example code
class User < ApplicationRecord
# Include default devise modules. Others available are:
# :confirmable, :lockable, :timeoutable and :omniauthable
devise :database_authenticatable, :registerable,
:recoverable, :rememberable, :trackable, :validatable
has_many :user_roles
has_many :skills
has_many :skills, through: :user_skills ## I don't want all users to have skills except the users with the role of freelancer
has_many :roles, through: :user_roles
def role?(role)
roles.any? { |r| r.name.underscore.to_sym == role }
end
end
thank you in anticipation.
You could do something like this:
class Skill < ApplicationRecord
belongs_to :user, -> { where role: 'freelancer' }
end
Keep in mind that this would save the skills for any role, but they would be visible only for freelancer.
You could also use cancancan to check whether the user is a freelancer.
I am using rails 5.0.0.1
When I submit a form, validations for associated fields are coming into action.
I have Gig, User, Category and other models
I am using devise for user authentication
Gig model
class Gig < ActiveRecord::Base
has_many :proposals
belongs_to :category
has_many :abilities
has_many :skills, through: :abilities
belongs_to :user
end
User model
class User < ApplicationRecord
# Include default devise modules. Others available are:
# :confirmable, :lockable, :timeoutable and :omniauthable
devise :database_authenticatable, :registerable,
:recoverable, :rememberable, :trackable, :validatable
has_many :gigs
has_many :proposals
end
Category model
class Category < ActiveRecord::Base
has_many :gigs
end
When I try to create the gig in console, the transaction rolls back.
the error messages are
["Category must exist", "User must exist"]
I appreciate your help. Thanks in advance.
In rails 5 when you add belongs_to it makes this field required. Try this
belongs_to :user, optional: true
I have three models and here they are when I try to create a has_many. I basically want my users (using devise) to have many categories. And categories to have many users.
user.rb
class User < ActiveRecord::Base
# Include default devise modules. Others available are:
# :confirmable, :lockable, :timeoutable and :omniauthable
devise :database_authenticatable, :registerable,
:recoverable, :rememberable, :trackable, :validatable,
:omniauthable
has_many :user_categories
has_many :categories, through: :user_categories
acts_as_messageable
def mailboxer_email(object)
email
end
end
userCategory.rb
class UserCategory < ActiveRecord::Base
belongs_to :user
belongs_to :category
accepts_nested_attributes_for :categories
end
Category.rb
class Category < ActiveRecord::Base
has_many :user_categories
has_many :user, through: :user_categories
validates :name, presence: true, length: {minimum: 3, maximum: 25}
validates_uniqueness_of :name
end
when I run category.users << user I get this error:
ActiveRecord::HasManyThroughAssociationNotFoundError: Could not find the association :user_categories in model Category
I can't say for sure what the problem could be, but a few things I could point out:
UserCategory's accepts_nested_attributes_for, does that mean the you want to be able to dynamically create categories?
Category has_many :users, through: :user_categories, not user
You need to follow the Rails file naming conventions, user.rb, user_category.rb and category.rb
These may not be the problem/solution, but I believe they're in the way of resolving the problem.
I am working on a Rails app where a User can create a magazine and another user can subscribe to that magazine. I want to know the best way to do this.
Currently I have a subscription model that builds from current user when created and users the current magazine as the magazine_id. This allow me to have a table of user_ids and magazine_ids. This allows me to see all the subscriptions but it means I cant easily check all the magazines someone subscribes to or check all the subscribers of a magazine.
When I try to use has_many :through, it throws up an error with building from current user. I have put in the relevant code below, hopefully it covers it all and thanks in advance.
User model:
class User < ActiveRecord::Base
# Include default devise modules. Others available are:
# :confirmable, :lockable, :timeoutable and :omniauthable
devise :database_authenticatable, :registerable,
:recoverable, :rememberable, :trackable, :validatable
has_many :magazines
has_many :subscriptions
end
Subscription model:
class Subscription < ActiveRecord::Base
belongs_to :user
belongs_to :magazine
end
Magazine model:
class Magazine < ActiveRecord::Base
belongs_to :user
has_many :subscrptions
has_many :users
end
The snippet of code from the subscription controller that throws up the error when I use has many through
def new
#subscription = current_user.subscriptions.build
#sub = Sub.find(params[:sub_id])
end
Hopefully that is enough for someone to figure out, if not please ask me for the other code or information.
You're very close, you're just missing the connection. Magazine can see Subscription because Subscription has its magazine_id. User can see Subscription because Subscription has its user_id. Through the Subscription, Magazine and User can see each other. So you want to user through
class User < ActiveRecord::Base
# Include default devise modules. Others available are:
# :confirmable, :lockable, :timeoutable and :omniauthable
devise :database_authenticatable, :registerable,
:recoverable, :rememberable, :trackable, :validatable
has_many :magazines, through: :subscriptions
has_many :subscriptions
end
class Subscription < ActiveRecord::Base
belongs_to :user
belongs_to :magazine
end
class Magazine < ActiveRecord::Base
belongs_to :user
has_many :subscriptions
has_many :users, through: :subscriptions
end
If this doesn't work, make sure you post your schema.rb/relevant fields from the tables you mentioned.
I think this should work, might need to set additional options though.
User model:
class User < ActiveRecord::Base
# Include default devise modules. Others available are:
# :confirmable, :lockable, :timeoutable and :omniauthable
devise :database_authenticatable, :registerable,
:recoverable, :rememberable, :trackable, :validatable
has_many :magazines
has_many :subscriptions
has_many :subscribed_magazines, through: :subscriptions, source: :magazine
end
Subscription model:
class Subscription < ActiveRecord::Base
belongs_to :user
belongs_to :magazine
end
Magazine model:
class Magazine < ActiveRecord::Base
belongs_to :user
has_many :subscriptions
has_many :subscribed_users, through: :subscriptions, source: :user
end
Edit: Needed source, not class_name
I'm quite new to RoR. Sorry if I'm using wrong terminology or the answer is obvious.
Initially I had one model for users as follows,
class User
include Mongoid::Document
devise :database_authenticatable,
:registerable,
:recoverable,
:rememberable,
:trackable,
:validatable,
:token_authenticatable,
:omniauthable
has_many :foos
field :name, :type => String
# Some other company fields
....
end
class Foo
include Mongoid::Document
belongs_to :user
...
end
This initial User model used to represent a company.
Then I decided to add another model which will have a different role from the initial User model, so I started using polymorphic associations and moved the necessary fields from User to Company model. I also added a Manager model which is not directly related to Company. I basically use User model for devise.
class User
include Mongoid::Document
devise :database_authenticatable,
:registerable,
:recoverable,
:rememberable,
:trackable,
:validatable,
:token_authenticatable,
:omniauthable
belongs_to :rolable, :polymorphic => true
end
class Company
include Mongoid::Document
has_one :user, :as => :rolable
has_many :foos
field :name, :type => String
# Some other company fields
....
end
class Manager
include Mongoid::Document
has_one :user, :as => rolable
end
class Foo
include Mongoid::Document
belongs_to :company
...
end
Everything seems to work fine so far for the new user registrations. However, there is the old database I have to convert. What confuses me is essentially the has_many association that I had before. I already implemented migration (using this gem, https://github.com/adacosta/mongoid_rails_migrations) to move the fields from User model to Company model, but again I couldn't figure out how to deal with the associations.
You are not required to run your migration if you don't need to transfer the information from your old database to your new one.
MongoDB can have some useless keys on document, there are no problems. The only problem you can have is to have extra octet saved on your database.