Rails Nested Form and dependent relationships - ruby-on-rails

I currently have a few models, users, clients, addresses and contacts.
I used scaffold to create my client model which only contains name, leadsource and DBA. It is currently working just fine.
My address and contact was created separately as a client can have many addresses and contacts and they require a client_id to set up the relationship.
Assuming I am using your standard crud operations, is there any way to set up a single nested form that will allow me to add all 3 at once?

Sure, the standard way is fields_for.
But normally you also want to dynamically add and remove associated objects (i.e. addresses) and that's a bit more advanced.
There are gems to help you. i.e. cocoon and a great railscast: episode 403.
Unfortunately it's a pro episode, but investing the $9 is well worth it, as the railscasts really are a source of inspiration (at least for me).
I assume, you already have the associations or create them:
rails generate migration AddClientReferenceToAddress client:references
rake db:migrate
and in models:
class Client < ActiveRecord::Base
has_many :addresses
end
class Address < ActiveRecord::Base
belongs_to :client
end

Related

Rails: list all attributes that can't be mass assigned

I am working through an old legacy project that has recently been updated. The models to the project are in an engine running separate from the controllers and views etc. The engine is running on rails 4.1.6 while the controllers etc are on Rails 3.
This has led to many issues with mass-assignment. I have created a little module that reads the db columns and white lists the attributes for that model. However in a case such as this NewsItem model which has associations and needs to accept attributes for those associations, the module doesn't work.
class Newsitem < ActiveRecord::Base
include MyAttrAccessibleModule
has_and_belongs_to_many :assets
has_and_belongs_to_many :boroughs
has_and_belongs_to_many :venues
I need to add
attr_accessible :asset1_attachment_remove,
:asset1_attachment_title,
:asset2_attachment_title,
:asset3_attachment_title,
:asset4_attachment_title,
:borough_ids,
:venue_ids
But finding all models that require this is a bit of a pain, seeing as there are well over 100.
Is there a way to highlight, find, test, discover in what other models this error might occur in also?
I think what you're looking for could be this:
Object.attributes.keys - Object.accessible_attributes
This should subtract all the whitelisted attributes from all of the available ones.
Thanks to #Stefan Dorunga for his suggestion. It led me in the right direction.
if reflect_on_all_associations(:has_and_belongs_to_many).any?
association = reflect_on_all_associations(:has_and_belongs_to_many)
association.each {|model| attr_accessible model.plural_name.singularize + "_id"}
association.each {|model| attr_accessible model.plural_name}
end
I query the model to see if it has a relationship where the relation id isnt explicitly listed and generate it dynamically.
The only downside is that I have to include the module after all the listed associations. I usually include modules at the top of a class. Whether this is standard practice or not I do not know.

What kind of Ruby on Rails model association for a "simple" lookup?

I have the following scenario I am trying to configure in a Ruby on Rails app (warning: I'm a beginner here)...
I have SupportType model that defines different levels of customer support options (Silver, Gold etc) with details about what that support type covers (24/7, business day only etc).
I have another model, Client that contains all of the basic customer information data.
I need to associate a Client to a SupportType (Client Jones has Gold-level support) but can't understand the "proper" way to set up this relationship. Neither "has_many" or "has_one" seems to apply in this case.
How do I set this up with the goal of being able to display all client details and the support parameters in one view?
TIA!
class Client < ActiveRecord::Base
belongs_to :support_type
end
class SupportType < ActiveRecord::Base
has_many :clients
end
This way you can access client's support type with a_client.support_type and see all the clients having gold support type with gold_support.clients
You can't use has_one in the Client model because in that case Rails aspects to find a client_id in the support_types DB table and it's not the case if I understood well since many clients can have the same SupportType.
PS: Remember to add a support_type_id column to your clients DB table

Id's in rails application

In my application I have a user model and a address model. How do I have the address form to include the id of the user id. (i.e my address model has a id and a id_user)?
Your address model should contain a user_id field, not a id_user field. It seems like you're just getting started with Rails, so I would recommend reading the official Getting Started and Association basics guides to learn the basics.
You probably want to look into record associations. I strongly recommend the guide on that very subject on the Rails website.
Since you took the time of creating two separate models (one for users and one for addresses) I figure it's because you can have one or more adresse per user. So I would recommend using a has_many association
In your migration file for your address model you should have a column name user_id of type integer. By convention, rails will use columns named model_id for an association with a model. So in your case, the model user can be linked with an address through the column user_id.
Having the column is not enough however. You also need to tell Rails about the association in the model. So add the following to the top of your user model (app/model/user.rb I would presume)
has_many :addresses
Then, tell your address model it belongs to a user. Doing so is again very straight forward. Add the following at the top of your address model (app/model/address.rb)
belongs_to :user
From there, you can do all sort of wonderful things. To create your forms, you may want to look at Nested model forms. There's two Railscast on it Part 1 and Part 2
As your experience with Rails seems limited at the time. I'd recommend also looking into the getting started guide, looking at the series of tutorial from Envy Labs (comically named Rails for Zombies) and when you get rolling browse through the Railscasts by Ryans Bates

Ruby on Rails working with pre-existing database. Rails makes everything plural

What is the deal with this? I'm working with a pre-existing that I did not do myself. Everything in the database is labeled in singular form. user, security, spec, etc. I guess the right way would be users, securities, specs. At least that's what ruby on rails try's to lookup when I generate a scaffold .
How do I specifically state to use user instead of users in the sql. I don't see anywhere in my project where it is looking up the sql. I mean if my model is user you would think it would try to lookup user. Instead of users.
Thanks for any help.
You need set_table_name :name_of_the_table in your model (source).
So:
class User < ActiveRecord::Base
set_table_name :user
end
The reason they use plural for the table and singular for the model is because an instance of the model represents one user, whereas the table contains all the users. It's just to make it more readable and logical.
You can specifiy the table name:
How do I explicitly specify a Model's table-name mapping in Rails?

How to create a view to manage associations between HABTM models? (Rails)

I am using Ruby on Rails and need to create a view that allows the creation of records through a HABTM relationship to another model. Specifically, I have the following models: Customer and ServiceOverride, and a join table customers_serviceoverrides. Using the customer view for create/update, I need to be able to create, update and delete ServiceOverrides and manage the attributes of the associated model(s) from the same view.
Visually I'd prefer to have something like a plus/minus sign to add/delete service overrides, and each serviceoverride record has two string entities which need to be displayed and editable as well. However, if I could just get the code (a kind of nested form, I'm assuming?) working, I could work out the UI aspects.
The models are pretty simple:
class ServiceOverride < ActiveRecord::Base
has_and_belongs_to_many :customers
end
class Customer < ActiveRecord::Base
has_and_belongs_to_many :serviceoverrides
end
The closest thing I've found explaining this online is on this blog but it doesn't really address what I'm trying to do (both manage the linkages to the other model, and edit attributes of that model.
Any help is appreciated. Thanks in advance.
Chris
The ascii cast at http://asciicasts.com/episodes/17-habtm-checkboxes has a simple and functional example.

Resources