I would like to show only one nested form for the one-to-many relationship between user and appointments. A user can only create one appointment and the form should only show fields for one appointment regardless of how many appointments he has.
I've tried the :limit option
class User
has_many :appointments, dependent: :destroy
accepts_nested_attributes_for :appointments, limit: 1
end
I also tried limiting the number of appointments built in the controller
class UsersController
def edit
#user = current_user
1.times { #appointment = #user.appointments.build }
end
end
I always end up with a nested form for each appointment the user has plus an additional nested form. I know I could change the relationship to one-to-one but this is for legacy code and its likely that the relationship will be one-to-many in the future.
Is there a way that I can only show one nested form regardless of how many appointments a user has?
Related
I creating a simple e-commerce for a friend and i want to implement a coupon system. I want coupons to be a new model and admin to be able to create a new coupon from admin panel like a simple scaffold.
My models are this for now.
class Order < ActiveRecord::Base
has_many :order_items
class OrderItem < ActiveRecord::Base
belongs_to :product
belongs_to :order
I know that i need an association Orders -> Belongs_to :coupon and Coupons -> has_many :orders or Orders -> has_one :coupon and Coupons -> belongs_to :orders. I want any order to have only one coupon.
But my main problem is how to create a form , to check if a coupon exists.
I know how to update the total_price etc.
Thank you.
Simply make sure that the name or some other attribute of the coupon is unique in the Coupon.rb model. See the link below for more information.
http://guides.rubyonrails.org/active_record_validations.html#uniqueness
Then you can index the Coupons by Coupon.name. This is will help two ways 1) if your admin attempts to create a coupon with a duplicate name or code they will get an error saying that coupon exits. 2) When a consumer enters a coupon you can simply check if it exits by calling Coupon.find_by_name('NAME') where NAME is what the consumer entered. If that returns nil then clearly they entered a coupon that was not created.
I have a parent User model, and each user has_one Contact which hold's the user's contact info.
One of the contact fields is the email. For various legacy reasons and reasons outside the context of this question, I'd love to be able to call #email directly as if it were a property of User
In other words I'd like to do this -
user.email
user.email = "foo#example.com"
Instead of this -
user.contact.email
user.contact.email = "foo#example.com"
I laid out my models as follows, overriding the child's getter/setter from the parent User -
class User < ActiveRecord::Base
has_one :contact
def email
contact.email
end
def email=(value)
contact.email = value
end
end
class Contact < ActiveRecord::Base
belongs_to :user
end
You may have already noticed the problem with the setter - when the User is saved, it doesn't save the child model.
What's the most robust to work around this?
Thanks!
Ok, found the solution for anyone curious - auto-saving
ActiveRecord::AutosaveAssociation is a module that helps with exactly this - saving child associations properly when the parent is saved.
Just need to include an autosave: true. Example -
has_one :contact, autosave: true
It also takes care of destroying records marked for deletion, and a few other fancy things.
I also did a quick check, and it smartly doesn't hit the DB unless it really needs to. That is, if you update the parent only it doesn't bother saving the child association with an other SQL UPDATE statement.
Check out the documentation here.
In Ruby on Rails 4, I've these models:
def User < ActiveRecord::Base
has_one :company, dependent: :destroy
end
def Company < ActiveRecord::Base
belongs_to :user
end
So now, I want User as Employer to be able to have a company, and this Company can have many Users(Employees).
And when I log a User as Employee, I want to able to list all the companies he works.
What is the best way to do this?
I'm not sure I could give you a full working code file without some more information, but I think this is the best way to proceed.
class User < ActiveRecord::Base
self.table_name = "users"
#Define shared associations/methods
end
class Employee < User
has_and_belongs_to_many :companies
#Employee only associations/methods
end
class Employer < User
has_one :company
#Employer only associations/methods
end
class Company < ActiveRecord::Base
has_and_belongs_to_many :employees
belongs_to :employer
end
Since both inherit from the same User model, they will share a table. Since both derived models only use has_x, the foreign key will be in the other table, meaning they can share a table schema without a ton of null values.
Again I'm not sure this will work by itself, but I think it's a good start. Another advantage is that by segregating the code like this, you can independently change functions by the type of person (e.g. you could have a generic log function on user, but make it more specific on Employee and Employer - such as including the company or companies they are tied to).
I realized after the fact that there is another way of doing this. You can make User have a polymorphic association to either Employee or Employer. Then you would check the user record for which type it is, then pull the association and call the methods on that record (Employee or Employer).
The only thing I don't like about this solution is that it involves 3 tables and from what I've seen you can get by with 1.
Short explanation:
I seek architectural advice and help in implementing multiple Devise models in a single app.
More detailed explanation:
My application needs to perform the following behavior:
There are 3 types of users (Partner, Attendee, Speaker) which have some common fields and some unique ones (also, the fields might have different permissions, i.e. Attendee must have a username whereas the Speaker might have it but they don't have to necessarily fill this field in). And moreover, the different user models must have different associations with other tables in the db.
The users need to be able to log in through single log-in form, but the sign-up forms should be different.
So, my first thought was that I should divide the users by roles using Pundit or declarative_authorization or something, but the users don't really have different roles (i.e. permissions) in the app, they rather have different behavior, they might see different content and stuff, so I continued thinking.
My second though was implementing STI and after reading several articles about it, I tried to do that in code.
I generated a Devise User model by doing rails g devise User and after that ran rails g model Attendee and the same for other two users.
Then, I inherited my models from User:
class Attendee < User
end
My User migration looks like this:
create_table :users do |t|
t.string :first_name
t.string :last_name
t.string :type
# Devise stuff ...
..................
t.timestamps null: false
end
And other migrations are like this:
create_table :attendees do |t|
t.string :username
t.string :company_name
t.boolean :subscription
t.timestamps null: false
end
Now I realize it was wrong to create separate tables.
I had to put all the possible fields into the User table, is that correct?
Because now when I try to create any new Attendee or Speaker or Partner in rails console, all of these three models have the exact same fields, those the User model has.
But if I add all the possible fields in the User model, how would I perform validations on field presence?
I've read quite a few articles and questions here on SO, but still can't really wrap my head around how to implement all that.
Anyway, is that a correct way to do what I need?
Could anybody explain me in a detailed way how I should implement this kind of behavior and functionality from start to finish, and how should I work with the models after having implemented them?
PS: here's the history of my migrations and the whole github repo
Update
Remembered another issue that stopped my from doing just role separation:
How should I sign up the different users with different sign-up forms? Different routes? I cannot make the user choose their role from the combobox.
You can create conditional validation rules based on the role, but the first place you need to address this is in the new/edit User form, only showing the allowed fields dynamically based on the role:
class User < ActiveRecord::Base
validates :company, presence: true, if: :is_company?
def is_company
# check for the role
self.role == 'company'
end
end
UPDATE: You can pass an extra parameter to the same registration form and use that to differentiate the type of form you display. That's the nicest way. You can also create separate methods in the UserController -> def register_user, def register_company, def register_xxxx
I have a rails 4 application whereby I've set up a User model. I want the User to have a has_many association with a user profile model, but here's the catch:
My user profile model needs to be polymorphic - the
User model can have multiple (different) user profiles associated
with it (e.g. ProfileTypeA, ProfileTypeB, ProfileTypeC, etc.)
I want my User model to have one association, say, user_profiles, that
would return the all the user's user profiles associated with it.
I believe I'm on the right track (or am I?), but how would this be accomplished using the rails generator? The part that is most confusing to me, is how to do bullet #2 above.
P.S. I took a look at STI's, but it seems to me that my User model would have to have a hard-association with each user profile type model, which I don't like because it would change the User model with each new user profile type I add to the data model.
You sound on right track,try below
#The polymorphic models
class User
has_many :user_profiles, as: :profileable
end
class UserProfile
belongs_to :profileable, polymorphic: true
end
The Migrations below
#migrations
class CreateUserProfiles < ActiveRecord::Migration
def change
create_table :user_profiles do |t|
t.integer :profileable_id
t.string :profileable_type
t.timestamps null: false
end
add_index :user_profiles, :profileable_id
end
end