I'm trying to make a method that gets the date and adds onto it an amount of days specified.
At present I cannot call the days specified.
I have a Plant Class that has_many DaysTillSellables, The Period class has_many DaysTillSellable also.
When the user creates a plant they can add a DaysTillSellables and then select a period and then enter an amount of days.
I first need to check to see which period the date is in, then return that period. Currently attempting like so
def current_period
return unless completed_at_week.between?(period.start_week, period.finish_week)
index_days_till_sellables_on_period_id
end
Then Find the days till sellable that is connected to that period and finally call the days from that
Below is the code for the class I'm trying to call it in
class Potting < ApplicationRecord
belongs_to :batch, inverse_of: :pottings
validates :plant_count, :completed_at, presence: true
enum germination_result: { light: 0, medium: 1, full: 2 }
def pottings_completed_at
"Week #{completed_at.strftime('%U').to_i}/#{completed_at.strftime('%Y').to_i}"
end
def completed_at
super || Time.zone.today
end
def completed_at_week
completed_at.strftime('%U')
end
def current_period
return unless completed_at_week.between?(period.start_week, period.finish_week)
index_days_till_sellables_on_period_id
end
def period_days
plant.days_till_sellables.find_by(period: :current_period).¤t_period.days
end
def ready_for_sale
completed_at + period_days
end
end
I've added more Code below to give better context for classes
class DaysTillSellable < ApplicationRecord
belongs_to :period, inverse_of: :days_till_sellables, foreign_key: :period_id
belongs_to :plant, inverse_of: :days_till_sellables, foreign_key: :plant_id
validates :days, presence: true
end
.
class Period < ApplicationRecord
has_many :days_till_sellables, dependent: :destroy, inverse_of: :period
belongs_to :organization
.
class Plant < ApplicationRecord
has_many :batches, dependent: :destroy
has_many :goals, dependent: :destroy
has_many :days_till_sellables, dependent: :destroy, inverse_of: :plant
belongs_to :organization
accepts_nested_attributes_for :days_till_sellables, allow_destroy: true
validates :genus, :species, :period_id, presence: true
end
I think you are looking for:
class Potting
belongs_to :plant, through: :batch
...
end
Related
I'm trying to build a query such that if a driver sends an offer to a ride, that ride no longer shows up in the collection rendered in the index view.
I've tried so many variations and I'm still getting all the rides. Even the ones Ive sent an offer to.
lang - ruby
class Driver < ApplicationRecord
belongs_to :user
has_many :offers
has_many :rides
end
class User < ApplicationRecord
has_many :rides
has_one :driver
end
class Ride < ApplicationRecord
validates :to, presence: true
validates :from, presence: true
validates :directions_from, presence: true
has_many :offers
belongs_to :user
belongs_to :driver, optional: true
end
lang - ruby
class Driver < ApplicationRecord
belongs_to :user
has_many :offers
has_many :rides
end
class User < ApplicationRecord
has_many :rides
has_one :driver
end
class Ride < ApplicationRecord
validates :to, presence: true
validates :from, presence: true
validates :directions_from, presence: true
has_many :offers
belongs_to :user
belongs_to :driver, optional: true
end
class Offer < ApplicationRecord
belongs_to :ride
belongs_to :driver
end
def index
#location = current_user.currently_at
#rides = Ride.includes(:driver).where(from: #location).select do |ride|
ride.offers.map do |offer|
offer.driver.user != current_user
end
end
#offer = Offer.new
end
I have the following models
class User < ActiveRecord::Base
has_many :games, dependent: :destroy
validates :games, length: { maximum: 3 }
end
class Game < ActiveRecord::Base
belongs_to :user
validates :user, presence: true
validates_associated :user
end
I want to make sure that no user has more than 3 games, but the validation does not seem to work.
Why?
You can make a custom validation method. As is shown in the Rails guide:
custom validation method
class User < ActiveRecord::Base
has_many :games, dependent: :destroy
validate :has_three_games_or_less
private:
def has_three_games_or_less
if games.count > 3.
errors.add_to_base("can't have more than 3 games")
end
end
end
According to this documentation, it should be achievable using the code you have.
If it doesn't work, you could use inverse_of to store the associated objects in memory (hence making them available to your validator):
#app/models/user.rb
class User < ActiveRecord::Base
has_many :games, inverse_of: :user
validates :games, length: { maximum: 3 }
end
#app/models/game.rb
class Game < ActiveRecord::Base
belongs_to :user, inverse_of: :games
end
You could alternatively set up a custom method to do it for you:
#app/models/user.rb
class User < ActiveRecord::Base
has_many :games, inverse_of: :user
validate :max_games
private
def max_games
errors.add(:base, "You cannot have more than 3 games on this account.") unless games.size <= 3
end
end
How can add a cascade of deletes that will remove Profile, TodoList, and TodoItem rows for any User removed.
User Model:
class User < ActiveRecord::Base
has_one :profile
has_many :todo_lists
has_many :todo_items, through: :todo_lists, source: :todo_items
validates :username, presence: true
end
Profile Model:
class Profile < ActiveRecord::Base
belongs_to :user
validates :first_name, presence: true
validates :last_name, presence: true
validates :gender, inclusion: %w(male female)
validate :first_and_last
validate :male_Sue
def first_and_last
if (first_name.nil? and last_name.nil?)
errors.add(:base, "Specify a first or a last.")
end
end
def male_Sue
if (first_name == "Sue" and gender == "male")
errors.add(:base, "we are prevent male by name Sue.")
end
end
end
TodoList Model:
class TodoList < ActiveRecord::Base
belongs_to :user
has_many :todo_items, dependent: :destroy
default_scope { order :list_due_date }
end
TodoItem Model:
class TodoItem < ActiveRecord::Base
belongs_to :todo_list
default_scope {order :due_date }
end
Thanks, Michael.
I guess adding dependent: :destroy will do.
#user.rb
class User < ActiveRecord::Base
has_one :profile, dependent: :destroy
has_many :todo_lists, dependent: :destroy
has_many :todo_items, through: :todo_lists, source: :todo_items, dependent: :destroy
validates :username, presence: true
end
From the docs:
has_many, has_one and belongs_to associations support the :dependent option. This allows you to specify that associated records should be deleted when the owner is deleted
By using dependent: :destroy on your association in the User class, anytime you destroy a User, all associated objects to that instance gets destroyed as well.
You can check this documentation for more information.
I'm wondering if there is a cleaner way to validate multiple relationships in rails. I don't mean validating an association, rather ensuring relationship integrity between two or more belongs_to associations. Here is some code as an example:
class User < ActiveRecord::Base
has_many :products, inverse_of: :user
has_many :purchases, inverse_of: :user
end
class Purchase < ActiveRecord::Base
belongs_to :user, inverse_of: :purchases
has_many :products, inverse_of: :purchase
end
class Product < ActiveRecord::Base
belongs_to :user, inverse_of: :products
belongs_to :purchase, inverse_of: :products
validates :user, :purchase, presence: true
validate :purchase_user
private
def purchase_user
errors.add(:purchase, 'purchase user does not match user') if user != purchase.user
end
end
The purchase_user validation method here checks that the user is the same as purchase.user and adds an error if they are not.
I could change it to use :inclusion like so:
validates :purchase, inclusion: { in: proc { |record| record.user.purchases } }
But that seems even more inefficient, any suggestions?
Problem: I want to have only 1 UserLesson per User per Video
because I'm building a tracking system (progress system) User shall be able to see how many lessons are remaining lesson/total lesson and also when marked as completed shall add css
I send the data from the view to the controller:
<%= link_to 'Mark as completed', user_lessons_path(#user_lesson, user_lesson: {user_id: current_user.id, lesson_id: #lesson.id}), :method => :post, class: 'btn btn-primary-big' %>
The controller receives data and launch the create method
class UserLessonsController < ApplicationController
before_filter :set_user_and_lesson
def show
end
def create
#user_lesson = UserLesson.create(user_lesson_params)
if #user_lesson.save
flash[:success] = "You rock! Keep up ;)"
redirect_to(:back)
else
flash[:success] = "You have already completed this lesson"
redirect_to(:back)
end
end
private
def user_lesson_params
params.require(:user_lesson).permit(:user_id, :lesson_id, :completed)
end
end
Here is the model relationship
class UserLesson < ActiveRecord::Base
belongs_to :user
belongs_to :lesson
# validates_uniqueness_of :user_lesson, :scope => [:user, :lesson]
end
class Lesson < ActiveRecord::Base
has_one :lecture, through: :chapter
belongs_to :chapter
end
class User < ActiveRecord::Base
has_many :enrollments
has_many :user_lessons
has_many :lectures, through: :enrollments
accepts_nested_attributes_for :enrollments
end
class Enrollment < ActiveRecord::Base
belongs_to :user
belongs_to :lecture
validates :lecture, uniqueness: { scope: :user, message: "should happen once per user" }
end
class Lecture < ActiveRecord::Base
belongs_to :category
has_many :lessons, through: :chapters, dependent: :destroy
has_many :chapters
belongs_to :teacher
# For course user relationship
has_many :enrollments
has_many :users, through: :enrollments
accepts_nested_attributes_for :enrollments
accepts_nested_attributes_for :chapters
end
class Chapter < ActiveRecord::Base
has_many :lessons
belongs_to :lecture
accepts_nested_attributes_for :lessons
end
My guess was to validates uniqueness of user-lesson per user and lesson. However can't seem to work got the error message.
Add this validation to your model to ensure uniqueness by user scope:
validates :lesson_id, :uniqueness => {:scope=>:user_id}