Must i use a polymorphic setup? - ruby-on-rails

I have a app setup question: (for a travel site)
My models are
class User < ActiveRecord::Base
end
class House < ActiveRecord::Base
end
class Apartment < ActiveRecord::Base
end
class Boutique < ActiveRecord::Base
end
class City < ActiveRecord::Base
end
class Activity < ActiveRecord::Base
end
I want to add a "i've been there", "i've done that", "i want to go there" ect to the user model. So when a user/visitor is by example on the activity show page there is a function where they can add the status describe above.
Where do i start in relation with my db setup...must i use the polymorphic setup?
Thanks..remco

I believe we need more information as to how the models relate to each other rather than just saying "I want to add I've been there, I've done that". We need relevant information i.e. A user has_many ???? A house belongs_to ???. Please see ActiveRecord Association basics. This will help gain some more clarity on what you are trying to do.

Related

How do I validate an unavailable period

I'm practicing rails and I would like to know how I would validate a situation.
In this case, it's a car rental project. I have a table of Cars (Autos) and one of Unavailable Period.
When registering a car, I assume that the car is available 100% of the month. If someone rents in a certain period, it must be unavailable so it can't be rented again in the same period, how would I do this validation?
Model
class UnavailablePeriod < ApplicationRecord
belongs_to :auto
end
class Auto < ApplicationRecord
belongs_to :rental_company
belongs_to :category
has_many :unavailable_periods
end
Any suggestion? content tip to study this?
What would be the best way?
model
Instead of an UnavailablePeriod I would simply have a Rental model that has a rented_from and a rented_until columns (both datetime).
On creation of a new Rental you then only have to check that there is no existing, date overlapping rental. to check that you could use a custom validation like this:
class Rental < ApplicationRecord
belongs_to :auto
validate :rental_period_is_available
private
def rental_period_is_available
return unless Rental
.where.not(id: id)
.where("rented_from < ? && ? < rented_until", rented_until, rented_from)
.exist?
errors.add(:base, "Car is already booked in this time period")
end
end
I suggest reading about custom validations and validations in general in the offical Rails Guides.

rails association limit record based on an attribute

As you can see in the schema below, a user can create courses and submit a time and a video (like youtube) for it, via course_completion.
What I would like to do is to limit to 1 a course completion for a user, a given course and based one the attribute "pov" (point of view)
For instance for the course "high altitude race" a user can only have one course_completion with pov=true and/or one with pov=false
That mean when creating course completion I have to check if it already exist or not, and when updating I have to check it also and destroy the previous record (or update it).
I don't know if I'm clear enough on what I want to do, it may be because I have no idea how to do it properly with rails 4 (unless using tons of lines of codes avec useless checks).
I was thinking of putting everything in only one course_completion (normal_time, pov_time, normal_video, pov_video) but I don't really like the idea :/
Can someone help me on this ?
Thanks for any help !
Here are my classes:
class CourseCompletion < ActiveRecord::Base
belongs_to :course
belongs_to :user
belongs_to :video_info
# attribute pov
# attribute time
end
class Course < ActiveRecord::Base
belongs_to :user
end
class User < ActiveRecord::Base
has_many :courses
has_many :course_completions
end
You could use validates uniqueness with scoping Rails - Validations .
class CourseCompletion < ActiveRecord::Base
belongs_to :course
belongs_to :user
belongs_to :video_info
validates :course, uniqueness: { scope: :pov, message: "only one course per pov" }
# attribute pov
# attribute time
end

Rails - how to find out if an ID is in the "has_many" relation

I have this structure of models:
class User < ActiveRecord::Base
has_many :groups
end
class Group < ActiveRecord::Base
belongs_to :user
end
and in the view, I would need to find out if the respective user is in the specific group - how to do that?
Is there any native Rails method that would do something like this:
<% if current_user.groups.IS_THIS_GROUP_ID_IN_USERS_GROUPD(#group.id)? %>
or do I need to write it by me? Or, what's the most time efficient way to find out this?
EDIT:
Sorry guys, I made a mistake - there's one more model, so the structure look like this:
class Favorite < ActiveRecord::Base
belongs_to :user
belongs_to :group
end
class User < ActiveRecord::Base
has_many :groups
end
class Group < ActiveRecord::Base
belongs_to :user
end
So what I am trying to do is basically this:
<% if current_user.favorites.IS_THIS_GROUP_ID_IN_USERS_FAVORITES_GROUPS(#group.id)? %>
I am sorry one more time, I don't know how I could overlooked the Favorite model.
Thanks
I would go with:
current.user.groups.include?(#group)
or if you only have an id:
current.user.group_ids.include?(id)
How about current.user.groups.include?(#group)
You can also use exists?, which is done in the database.
current_user.groups.exists?(#group)
More information about exists? can be found in the Rails Active Record Querying Guide.
Try
If you're trying to see if the object has any groups, you may wish to use the .try method (although I'm not sure if this an accurate use case):
current_user.try(:groups)
--
Include
You may wish to try and use the include? method, as shown by spickerman. This will ping the array to see if a particular element exists inside (it's not ActiveRecord, so you'll have to use ids)
current_user.groups.include?(#group.id) #-> true / false

User to mark (favorite-like) another Model in Ruby on Rails

I want to implement a "Read Later" (just like Favorites) system in a Ruby on Rails app. What I want is for a User model to be able to mark a Content model to read later.
My associations between the two models are like this:
class User < ActiveRecord::Base
has_many :contents
end
-------------
class Content < ActiveRecord::Base
belongs_to :user
end
Then a Content belongs to a Category, etc, but that doesn't matter for the question so I just didn't put it there.
A User can mark a Content (that could belong to another user) and there will be a list of "marked contents (to read later)" for each user.
How could I implement this?
I've already read this question but I didn't really understand and when trying to simulate it, it didn't work.
What did you try and what didn't work?
This is pretty straight forward. Let us think through:
There is a User:
class User < ActiveRecord::Base
end
There is Content:
class Content < ActiveRecord::Base
end
A User can create Content and is he restricted to create only one content? no. A User can create as many contents as he wants. This is to say in Rails terms a User has_many contents. To put this in other words, can we say that a Content is created by a User.
class User < ActiveRecord::Base
has_many :contents
end
class Content < ActiveRecored::Base
belongs_to :user
end
Now, the content (typically created by other users) can be favorited (marked as 'Read Later') by other users. Each User can favorite (mark 'Read Later') as many contents as he wants and each Content can be favorited by many users isn't it? However, we'll have to track which User favorited which Content somewhere. The easiest would be to define another model, let us say MarkedContent, to hold this information. A has_many :through association is often used to set up a many-to-many connection with another model. So the relevant association declarations could look like this:
class User < ActiveRecord::Base
has_many :contents
has_many :marked_contents
has_many :markings, through: :marked_contents, source: :content
end
class MarkedContent < ActiveRecord::Base
belongs_to :user
belongs_to :content
end
class Content < ActiveRecord::Base
belongs_to :user
has_many :marked_contents
has_many :marked_by, through: :marked_contents, source: :user
end
Now you can do:
user.contents # to get all the content created by this user
user.marked_contents # to get all the contents marked as 'Read Later' by this user
content.user # to get the creator of this content
content.marked_by # to get all the users who have marked this content
Read more here to learn about associations.
To mark a content as a favorite, one way would be:
#user = User.first
#content = Content.last
#user.markings << #content
You can also implement a method in the User model to do this for you:
class User < ActiveRecord::Base
...
def read_later(content)
markings << content
end
end
Now, you can do:
#user.read_later(#content)

Ruby on Rails models relationship

need some advice.
I'm doing a project on RoR, and do not sure what relationship between the models should I use. I've got three models - Users, Boards and Messages.
The beginning is pretty simple:
User has one Wall, and it belongs to the User, so I guess this should be:
class User < ActiveRecord::Base
has_one :board
end
class Board < ActiveRecord::Base
belongs_to :user
end
The last model is Messages and here comes my problem. Message belongs to User cause he writes it, but it also belongs to a Wall cause he writes it on a wall (and it can be Wall that belongs to other user).
I used the simple solution:
class Theme < ActiveRecord::Base
belongs_to :board
belongs_to :user
end
class User < ActiveRecord::Base
has_one :board
has_many :themes
end
class Board < ActiveRecord::Base
belongs_to :user
has_many :themes
end
But I not satisfy with it, and feel that it isn't perfect. I'm looking for a solution that will let me write thinks like:
user.themes.create(:board => #board)
(now it doesn't fill user_id field)
I hope that isn't a hard task for those who more experienced than me in Ruby on Rails model. I'll appreciate good advices, thanks.
For normal you use some authentification gem like devise. Then you have the current_user variable which includes the object of the user that is currently calling the action.
Then when a user creates the Topic you add one simple line to the controller to set the user:
#theme.user = current_user
You should also use a gem like cancan to manage the authorisation in a cenral file. Youl find a railscast here:
http://railscasts.com/episodes/192-authorization-with-cancan

Resources