Create dynamic association according to db values - associations

In a Rails4 app I'd like to create dynamic associations.
I have the following models:
class Pilot < ActiveRecord::Base
has_many :cars
end
class Cars < ActiveRecord::Base
belongs_to :pilot
end
Cars have an attribute color and I'd like to create as many associations as available colors
For instance if I have 1 red car, 2 blue cars and 1 green car, I'd like to have in my pilot model
has_many :red_cars
has_many :blue_cars
has_many :green_cars
The point is that I don't know the colors that will be picked up.
Is it possible to implement it?
Thanks.
UPDATE
I guess I can probably do something like
#untested. Written just now
Car.all.map(&:color).uniq.each do |color|
has_many "#{color}_cars".to_sym, -> { where(color: '#{color}') }, class_name: 'Car'
end
If nothing better is possible.

You can easily add conditions to your has_many associations (make sure they are the first argument).
class Pilot < ActiveRecord::Base
has_many :cars
has_many :red_cars, -> { where(color: 'red') }, class_name: 'Car'
end
You can make this even more nicely organized with named scopes.
class Pilot < ActiveRecord::Base
has_many :cars
has_many :red_cars, -> { red }, class_name: 'Car'
end
class Cars < ActiveRecord::Base
belongs_to :pilot
scope :red, -> { where(color: 'red') }
end
When you go with the named scopes, you can always do #pilot.cars.red to find all red cars belongs to a pilot, and if this is convenient enough for you, you might not need a custom has_many :red_cars association at all.
Update
If you don't know the color you want to retrieve beforehand, you can pass dynamic conditions into a named scope.
class Pilot < ActiveRecord::Base
has_many :cars
end
class Cars < ActiveRecord::Base
belongs_to :pilot
scope :with_color, ->(color) { where(color: color) }
end
In your controller, you can then select #pilot.cars.with_color('red') and #pilot.cars.with_color(params[:color]). I'd not want to create hardcoded has_many :red_cars associations in this case.

Another way to solve this is to treat the colors as enums Rails4+ will create scopes for the enums based on the types:
http://edgeapi.rubyonrails.org/classes/ActiveRecord/Enum.html

Related

ruby-on-rails-7 encrypt polymorphic associations for certain type

How does one use the Declaration of Encrypted Attributes for Polymorphic Associations only for a certain type?
Using Active Record Validations like:
class Address < ApplicationRecord
encrypts :city, unless: -> { addressable_type == 'public' }
end
does not work.

authorizing specific controller action using cancancan

I have link to access player's load_player view to access player that belongs to current_user. So how can i restrict access to load_player method for current_user that has no belonging club or club belonging to other user. Note I want restrict access to load_player page.
routes.rb
get 'player/load_player/:id' => "player#load_player", as: :player
# player_controller.rb
class PlayerController < ApplicationController
before_action :authenticate_user!
authorize_resource :class => false
layout "player"
def load_player
#club_hash = Club.where({:id => params[:id]}).pluck(:club_hash).first
end
end
# ability.rb
class Ability
include CanCan::Ability
def initialize(user)
user ||= User.new # guest user (not logged in)
if user.is?(:admin)
can :manage, :all
elsif user.is?(:owner)
can :read, all: { except: [UploadedSong]}
can :manage, Club, user_id: user.id
can :read, :load_player, id: user.id
elsif user.is?(:user)
can :read, all: { except: [UploadedSong]}
end
end
end
current_user.clubs.where(id: params[:id]).pluck(:club_hash).try(:first)
# or add user_id inside where clause
Club.where(id: params[:id], user_id: current_user.id).pluck(:club_hash).try(:first)
Hope this solve your problem :)

Select from nested entity framework entity

I'm using Entity Framework 4.3.
I have a user entity named Lender - a lender has many lending Tiers. There are many other entities linked to lender but for or the purpose of clarity, I'll keep the structure simple.
What I need to do is return a lender but only with a single matched Tier based on some criteria, in other words a flattened structure for Tier.
I'm unsure as to how to do this in a single statement - can anyone help?
The meaning of your "flattened structure for Tier" is a bit dark to me but perhaps you are looking for a projection like the following one:
var lenderWithTier = context.Lenders
.Where(l => l.Something == something) // lender filter
.Select(l => new
{
Lender = l,
Tier = l.Tiers
.Where(t => t.SomethingElse == somethingElse) // tier filter
.FirstOrDefault() // only one tier
})
.FirstOrDefault();
lenderWithTier is an anonymous object that has a lenderWithTier.Lender property and a lenderWithTier.Tier property which is a single Tier object (or null if none of the tiers related to the lender matches the tier filter).

Rails / Rspec - writing spec for class name of belongs_to association

Given the code below:
(1) How would you write a spec to test that the class name of home_team and away_team should be a Team class?
(2) Should you even bother to write such a spec? I'm not sure I see the value in doing so, but wanted to get your thoughts.
class Event < ActiveRecord::Base
belongs_to :home_team, :class_name => 'Team', :foreign_key => :home_team_id
belongs_to :away_team, :class_name => 'Team', :foreign_key => :away_team_id
end
describe Event do
it { should belong_to(:home_team) }
it { should belong_to(:away_team) }
end
Would be nice if shoulda had something like:
it { should belong_to(:home_team).with_class_name(:team) }
Judging by the shoulda-matchers source, you should be able to do something like...
it { should belong_to(:home_team).class_name(:team) }
or
it { should belong_to(:home_team).class_name('Team') }
Here is a blog post about why this really shouldn't be done:
http://blog.davidchelimsky.net/2012/02/12/validations-are-behavior-associations-are-structure/
To summarize, associations are the structure of your application. RSpec is meant to test behaviors. So, its probably better if you write tests for the behavior that is derived from the home_team or the away_team.
Take for example if you wanted the name of the home_team. It would be better if you wrote a method like this:
def home_team_name
home_team.name
end
This is a behavior that the event class would ask the home_team for. You could write a spec such as:
describe '#home_team_name' do
before do
#home_team = Team.new(:name => 'The Home Team')
#event = Event.new(home_team_id: #home_team.id)
end
it 'should return the name of the home team' do
#event.home_team_name.should == 'The Home Team'
end
end
This would be a great example of testing the behavior of the association, without directly testing the structure of your application.
Also, as a point, Rails expects that home_team is of class 'Team', and there is no need to test the framework, it is well tested and documented. The only way that I could see doing this would be on a temporary basis, if you needed to improve your understanding of the way that assocaitions work.
you can refer this answer with optional true in belongs_to
association
https://stackoverflow.com/a/60630840/9490901

Drools rule iterate collections and verify property

With Drools Rules "mvel" how to iterate over a collection and verify a property for each object in the collection?
Look for the forall keyword in the reference manual (follow documentation on the drools page).
Here's the code for going over the collection of Interests inside a Person object and checking if one of them is contains an interestName field "Running":
rule "likes running?"
when
$p : Person()
$inter : Interest ( interestName == "Running" ) from $p.interests
then
System.out.println("I like running too.");
end

Resources