Display values in model B that belongs to A - ruby-on-rails

I have a Company.rb model that has_many :applications what I am trying to now is to show all applications the company has created.
When a Company creates an application I store their id inside Application.rb in the column called company_id by using merge on #create.
What I am trying now is to make it so that I can have a page where they can see the applications they have created. How do I only show applications that match current_company.id with the company_id in the Application.rb ?

Try this;
#applications = current_company.applications
Then use #applications in your views.

Related

Working with extended models in rails 5.0?

Theme:
I'm working in a rails app where I have extended a existing model called profile into two models called person and organization. I want to get organizations only when I use Organization.all and people only when I call Person.all.
Problem:
But when I use Organization.all or Person.all it returns all records without removing person form Organization.all and organization form Person.all.
What your looking for is Single Table Inheritance. You want Profile to be a base class of Person and Organisation so class Person < Profile etc.
You then want a migration to add a type field to profile
add_column :profiles, :type, :string, reference: true
Then you simply call Person.all to get all the people, and Organisation.all to get all the organisations.
https://samurails.com/tutorial/single-table-inheritance-with-rails-4-part-1/ for reference if you have more trouble.

Rails associations - orders

So I have been trying to create a dummy application to try and learn Rails. The app I thought I could create is a coffee ordering app for a group of people in work.
So the website will have many users.
A user can create a coffee_order.
A coffee order contains orders for other individual users.
Each user can have one or more coffee_shop_items (e.g. latte,
cappuccino,danish, muffin, etc)
A coffee order also has an assignee, this is the person who is tasked
with going and getting the order.
So as a user, I create a coffee order, select an assignee, add users to the order, and add one or more coffee shop items to each user,
I am really struggling with how the database should be, and what the associations need to be, along with any join tables?
I am also trying to use nested attributes for the form entry.
Thanks in advance for help.
Update with some code I have tried to create a coffee order:
#coffee_order = CoffeeOrder.new(coffee_order_params)
params[:coffee_order][:user_coffee_orders_attributes].each do |user_order|
order = #coffee_order.user_coffee_orders.new(user_id: user_order[1][:user_id].to_i)
user_order[1][:coffee_shop_items].each do |item|
coffee_shop_item = CoffeeShopItems.find(item) if item != ""
# this line fails! see error below
#coffee_order.user_coffee_orders.coffee_shop_items << coffee_shop_item if coffee_shop_item != nil
end
end
error:
NoMethodError (undefined method `coffee_shop_items' for #<UserCoffeeOrder::ActiveRecord_Associations_CollectionProxy:0x42c6180>):
The coffee_shop_items belong to the order, not the user. After all, a user could probably create another order another day? You should probably also check out the rails documentation, which, IIRC actually contains a walk-through of a shopping cart application.
User has_many :coffes_orders
User has_many :coffee_orders_he_needs_to_get, class_name: "CoffeeOrder", foreign_key: "assignee_id"
CoffeeOrder belongs_to :user
CoffeeOrder belongs_to :assignee, class_name: "User"
CoffeeOrder has_and_belongs_to_many :coffee_shop_items
Coffee_shop_items has_and_belongs_to_many :coffee_orders

Rails default data

Every time I create a new company record in rails, I need to add some default (blank) contact records at that company. Front Desk, Receiving, HR, IT and so on...they won't have any data in them besides the name, just a placeholder for the user to fill in later.
So, my company model has_many contacts, and contacts belong_to company. The contact records are static and the same for every new company that gets added, but I need to pre-populate the contacts table with data, so my users don't have to.
I've read a lot about seeding the database, but I won't be able to use the terminal every time a user dynamically creates a company, and it needs to be dynamically tied to that company, the records are not agnostic. Seeding doesn't seem to be the right thing. How should this be done?
you should use a before_save filter, which checks if an attribute is empty, and otherwise set it to the default.
Using a before_save will guard against deletions later on.
But be careful only to do this for fields which will never be empty.
class Company < ActiveRecord::Base
has_many :contacts
before_save :add_defaults
def add_defaults
contacts ||= Contact.default_list # this only sets it if it's nil
# you can implement Contact#default_list as a method, or as a scope in the contacts model
end
end
What about after_create callback in Company Model?
Smth like this:
class Company < ActiveRecord::Base
has_many :contacts
after_create :add_contacts
def add_contacts
contacts.create(name: "Some name", phone: "...", ....)
end
end
Although it notionally exists for generating test data, the FactoryGirl gem is very useful for this purpose. Use it in conjunction with the after_save approach mentioned here, and you'll have a nice place to centrally define your blank records.

Ruby on Rails Associations

I am starting to create my sites in Ruby on Rails these days instead of PHP.
I have picked up the language easily but still not 100% confident with associations :)
I have this situation:
User Model
has_and_belongs_to_many :roles
Roles Model
has_and_belongs_to_many :users
Journal Model
has_and_belongs_to_many :roles
So I have a roles_users table and a journals_roles table
I can access the user roles like so:
user = User.find(1)
User.roles
This gives me the roles assigned to the user, I can then access the journal model like so:
journals = user.roles.first.journals
This gets me the journals associated with the user based on the roles. I want to be able to access the journals like so user.journals
In my user model I have tried this:
def journals
self.roles.collect { |role| role.journals }.flatten
end
This gets me the journals in a flatten array but unfortunately I am unable to access anything associated with journals in this case, e.g in the journals model it has:
has_many :items
When I try to access user.journals.items it does not work as it is a flatten array which I am trying to access the has_many association.
Is it possible to get the user.journals another way other than the way I have shown above with the collect method?
Hope you guys understand what I mean, if not let me know and ill try to explain it better.
Cheers
Eef
If you want to have user.journals you should write query by hand. As far as I know Rails does has_many :through associations (habtm is a kind of has_many :through) one level deep. You can use has_many with finder_sql.
user.journals.items in your example doesn't work, becouse journals is an array and it doesn't have items method associated. So, you need to select one journal and then call items:
user.journals.first.items
I would also modify your journals method:
def journals
self.roles(:include => :journals).collect { |role| role.journals }.flatten.uniq
end
uniq removes duplicates and :inlcude => :journals should improve sql queries.
Similar question https://stackoverflow.com/questions/2802539/ruby-on-rails-join-table-associations
You can use Journal.scoped to create scope with conditions you need. As you have many-to-many association for journals-roles, you need to access joining table either with separate query or with inner select:
def journals
Journal.scoped(:conditions => ["journals.id in (Select journal_id from journals_roles where role_id in (?))", role_ids])
end
Then you can use user.journals.all(:include => :items) etc

What is the best way to do scoped finds based on access control rules in Rails?

I need to find an elegant solution to scoped finds based on access control rules. Essentially I have the following setup:
Users
Customers
AccessControl - Defines which user has access to another users data
Users need to be able to access not just their own customers but also shared customers of other users.
Obviously something like a simple association will not work:
has_many :customers
and neither will this:
has_many :customers, :conditions => 'user_id in (1,2,3,4,5)'
because the association uses with_scope and the added condition is an AND condition not an OR condition.
I also tried overriding the find and method_missing methods with the association extension like this:
has_many :customers do
def find(*args)
#get the user_id and retrieve access conditions based on the id
#do a find based on the access conditions and passed args
end
def method_missing(*args)
#get the user_id and retrieve access conditions based on the id
#do a find based on the access conditions and passed args
end
end
but the issue is that I don't have access to the user object / parent object inside the extension methods and it just does not work as planned.
I also tried default_scope but as posted here before you can't pass a block to a default scope.
Anyhow, I know that data segmentation and data access controls have been done before using rails and am wondering if somebody found an elegant way to do it.
UPDATE:
The AccessControl table has the following layout
user_id
shared_user_id
The customer table has this structure:
id
account_id
user_id
first_name
last_name
Assuming the the following data would be in the AccessControl table:
1 1
1 3
1 4
2 2
2 13
and so on...
And the account_id for user 1 is 13 I need to be able to retrieve customers that can be best described with the following sql statement:
select * from customers where (account_id = 13 and user_id = null) or (user_id in (1,3,4))
Sorry if I've completely missed the point here but I'm not 100% sure of what you want to do. Is AccessControl a relationship between User and Customer? If so looks like you just need to setup a many-to-many relationship.
class User
has_and_belongs_to_many :customers
# or this if you need to store meta data in the join table
has_many :customers
has_many :access_controls
has_many :accessible_customers, through => :access_controls
end

Resources