Rails 5: Many-to-Many relationships and Controllers - ruby-on-rails

Per a previous post , I understand how to set up my tables/Models so that I can setup a Many-to-Many relationship
However, what I am trying to do is to implement all of this on 1 page with 1 form. (The only other page the user will see is a confirmation page after they have submitted the form, possibly just displaying the details of what they submitted)
The User only needs to be able to update the quantities of any of the available Meals. I will then make a backup of the database on a certain day/time and that will be every User's order for the week. Because of this, I have restructured my tables as follows...
User stores the user's information.
user.rb
class User < ApplicationRecord
has_many :mealselections
has_many :meals, through: :mealselections
accepts_nested_attributes_for :mealselections
end
Meal is used to display the information of the meals to all users. (meal_name, description, img_url)
meal.rb
class Meal < ApplicationRecord
has_many :mealselections
has_many :users, through: :mealselections
end
MealSelection is the joined table that references the Meals the User chose, and then an additional integer column is added to this table that denotes the qty of meals they want for each meal selection
mealselection.rb
class MealSelection < ApplicationRecord
belongs_to :user
belongs_to :meals
end
So where I am lost is how to utilize the controller to be able to perform CRUD functionality from a single form. This made more sense when I had a 1-to-1 relationship as I was just updating the columns (meal1, meal2, meal3) for the related user and each meal# column was created with a default value of 0.
However now because of how Many-to-Many relationships work, I realize that the user at minimum has to create and update columns from the same form.
Since I am showing this on one page (homepage), how do I make this happen in the respective HomeController with one form/request?

Though a little dated, the content in http://railscasts.com/episodes/196-nested-model-form-revised demonstrates a common technique which involves modifying the form as the user is making selections to create, remove, or modify the fields of the nested model(s) using javascript. This basic principle is still commonly used, as it leans on the default nested attribute logic in the controller and model mass-update mechanisms. There are some minor tweaks you may have to make with strong parameters being a factor on more modern apps than was common at the time the content was produced. A look at the code for the form and controller action(s) in question might help with a more specific answer as well.

Related

User, Order, Meal, Item and their ActiveRecord associations

I'm trying to figure out what the appropriate ActiveRecord associations would be for my models. I am building a meal customization and ordering system for a website where Users can select from a number of Items and build a Meal and repeat this multiple times for a single Order.
My current setup is as follow:
User
has_many :orders, :dependent => :destroy
has_many :meals, through: :orders
Order
belongs_to :user
has_and_belongs_to_many :meals
Meal
has_and_belongs_to_many :orders
has_and_belongs_to_many :items
Item
has_and_belongs_to_many :meals
I suppose my question then would come in two parts:
1) does my current setup allow for multiple items to be assigned to a single meal, and possibly to other meals for a single order.
2) will I be able to access a user's previous meals to provide a shortcut when making new orders.
thanks a bunch in advance from a first time question asker!
To your first question, yes, you have set up a many-to-many relationship between your meals and items (assuming you have the correctly named database columns as well).
To your second question, you may have to wright a custom query for it as I'm not sure if active record is setup to do the multi layer query you're asking it to do (i.e. get all the meals from all the orders for a given user). Something like
past_meals = Set.new
users.orders.each {|o| past_meals += o.meals} would certainly work but could be made much more efficient if you needed it to.
However, even though has_many_and_belongs_to does work for what you're doing, using it isn't recommended. The community is much more in favor of making a join table doing a has_many_through relationship with that.
You in no means have to do that but most people would suggest it and it could save you some work down the road.

Rails: Marking content as complete for individual users, when content is common across them

I'm relatively new to Rails, so apologies in advance if this is an obvious question. I could not find an answer through searching.
I'm building a basic application which acts as an educational course - users can view lessons, take in the content, and mark lessons as 'complete' accordingly.
I would like users to be able to see which lessons are complete, by marking them as such in the course overview.
I have a Users model and a Lessons model, and the lessons are identical per user at present. If lessons were unique per user, this would presumably be solvable with a boolean 'complete' column for each lesson. This is not the case in this application, however - some users will have completed a lesson; others will not have.
How would I best go about a solution to this? All suggestions and ideas welcome.
Use many-many association and establish relationship among the 3 models.
class Student < ActiveRecord::Base
has_many :progresses
has_many :subjects, through: :progresses
end
class Subject < ActiveRecord::Base
has_many :progresses
has_many :students, through: :progresses
end
class Progress < ActiveRecord::Base
belongs_to :student
belongs_to :subject
end
To be precise use this link to get good understanding on many-many association :)
Third model, say Progress or Completion or Grades or UserLessons... that will belong to user and lesson, and have a field called complete or score or grade....
It's a classic case of many-to-many relation.
User can read multiple lessons
Lessons could be read/complete by multiple users
So to do this is to create another model with column user_id lesson_id as a foreign key for user and lesson and create an additional column completed boolean

How to construct a Rails view to edit an associated data set

I am developing a Rails app to keep track of product manufacturing runs. Each run has a group of products that are made at varying quantities for each run. I have a model, Run, that has many product_run objects which consist of a parameter 'quantity' and a has_one product. I am having trouble constructing a view to enter all of the quantities for a run. Simply display all products with a box to enter a quantity. Any help on the correct Rails way to do this would be appreciated.
Take a look at NestedAttributes ClassMethods
everything that you need should be there.
Active Record Nested Attributes
Nested attributes allow you to save attributes on associated records through the parent. By default nested attribute updating is turned off and you can enable it using the #accepts_nested_attributes_for class method. When you enable nested attributes an attribute writer is defined on the model.
The attribute writer is named after the association, which means that in the following example, two new methods are added to your model:
author_attributes=(attributes) and pages_attributes=(attributes).
#app/model/book.rb
class Book < ActiveRecord::Base
has_one :author
has_many :pages
accepts_nested_attributes_for :author, :pages
end

Modelling an application in Rails - mixing STI and polymorphic associations

Please forgive me if this has been answered already but I've searched a lot and still require some clarification.
I'm building a Property Management tool using Rails 3.2. I already have a User model and authorisation/authentication code in place with full tests coverage.
I've just started drawing out the models/classes/tables and have gotten myself a bit confused.
Let's start with Users.
Modelling Users
I plan to have allow multiple companies to use this system. Each will have employees (users). These users will have different roles e.g. Manager, Agent, Accountant, Secretary etc. For the most part the data I plan to store for each of these users will be similar (or so I think at the moment) so I am leaning towards Single Table Inheritance and using the type to define the level of access each employee has.
Secondly, I plan to allow Landlord and Tenants to also log in to the system. Upon logging in they'll be able to view information about the property they are owning or renting - maybe keep their contact details up to date too.
I was thinking of using polymorphic associations to represent these users.
So the plan I have at the moment and would like some feedback on is to have
User < ActiveRecord::BASE
Employee < User (this will have a STI type column and allow for the different employee roles)
Landlord < User
Tenant < User
Is this the best way of approaching this problem or am I shooting myself in the foot?
I've had some people advise me I should have a 'roles' table and assign roles to the users - but I have a feeling this isn't the most elegant way to do this in Rails.
Properties
My next issue is with Properties. Right now I have a model for properties and when I add them they belong_to a User (i.e. they have a user_id foreign key). I then started thinking "what happens if the employee (user) that added the Property leaves the company or has their account deleted for some reason?"
So in this scenario is it best to forgo the User/Employee to Property association and just link the Property to the Company that the employee belongs to? This way I can all employee.company.properties to list out all the properties?
Landlord and Tenant associations
Let's presume we make Properties belong to a Company.
In terms of associations this is what I have in my head. Looking at it now I see that everything belongs to a company because one company using the system shouldn't be able to see the landlords/tenants/employees/properties of another company.
class Landlord < User
belongs_to :company
has_many :properties, :through => :ownerships
end
class Tenant < User
belongs_to :company
has_one :property, :through => tenancies #you can only live at one place at a time right?
end
class Property < ActiveRecord::Base
has_many :tenants, :through => :tenancies
has_many :landlords, :through => :ownerships
belongs_to :company
end
class Company < ActiveRecord::Base
has_many :properties
has_many :employees
has_many :landlords :through => :ownerships #not sure if through is required/works here
has_many :tenants :through => :tenancies #not sure if through is required/works here
end
class Employees < User
belongs_to :company
end
Properties
Also I'm guessing we'll have different types of Properties (Commercial/Residential) and of those there will be whole buildings, apartments within a building (single address) etc.
Like with users I'm planning on using Polymorphic Associations to define two subclasses CommercialProperty and ResidentialProperty and then use sti to define a type. If the type is "multi unit" then have a new model for units and an association whereby Property has_many Units and a Unit belongs_to a property.
Aim
I'm trying to make sure that my code follows best practice as much as possible so that when I come to add new features and expand I'm not left having to re-write large chunks of the app.
I would really appreciate your feedback.
Reference
Some of the posts I've read. Hopefully to help others trying to solve the same problem.
Designing a Rails application: single table inheritance?
Ruby on rails with different user types
Ruby On Rails User Model for multiple types
It's probably too late but you could also use has_and_belongs_to_many on User and Company and thus avoid STI altogether by using gems cancan and rolify.
It allows you to define finely grained access rights (abilities).
I know that it seems more elegant having different classes instead of roles, but it is not viable long-term strategy, it can become messy when logic becomes complex.
Other then that, the rest seems pretty solid, hope that helps :)

Help with rails content filtering

Im creating my own blog managing app in rails (for experimental purposes).... What would the best way to get this done?
I have posts and categories.
I want to have a dropdown of categories for the user to select one when they create a new post.
Now, each user will have different privileges so not all categories should appear for all users....
Right now Im at the point where I can create posts and choose which category I want... I havent added any filter per user support....
please help me on where should I go now??
First you will need to implement authentication and authorization. There are many good Rails tutorials on these subjects so I won't go into more detail here.
At this point you will have models for User, Post, and Category. You need a list per-user of authorized categories. A naive model:
class User < ActiveRecord::Base
has_and_belongs_to_many :categories
end
But that is misleading, because a user isn't actually "in" any categories. You probably want something like a join model like so:
class UserCategoryAuthorization < ActiveRecord::Base
belongs_to :user
belongs_to :category
// More fields here; possibly:
// belongs_to :authorized_by, :class_name => 'User'
end
class User < ActiveRecord::Base
has_many :user_category_authorizations
has_many :authorized_categories,
:through => :user_category_authorizations,
:source => :category
end
To start with I would give Users a has_many categories relationship(Which you could turn into its own model object at some point if this idea gets more complicated..or now if it already makes sense) and then assuming you already have log in functionality you can ask the logged in user for its categories and populate the drop down appropriately.
If this is a security issue rather than just convenience then you will need to validate the chosen category is in the users categories when the form is submitted back to the server.
If you don't already have logins I believe there are several rails plug-ins that attempt to help you get this functionality quickly.

Resources