I have two models Run and Patient. Run belongs_to Patient and Patient has_many runs.
On the Run model I'm using accepts_nested_attributes in which to enter a patient's information into a run via a regular Rails form using fields_for.
Right now I have a basic form (stripped down version) that looks like this:
<%= form_for(#run) do |f| %>
<%= f.fields_for :patient do |p| %>
<%= p.text_field :patient_name, placeholder: 'John Doe', class: 'form-control' %>
<% end %>
<% end %>
I'm able to create a patient inside of the form and reject the associated/nested object created inside of the model. But what i'm looking to do is:
1.) Have a search/select box where I can type a patient name in and it will autocomplete
2.) If it finds the patient, it selects the patient and uses it for the run.
3.) If it does not find the patient or it's not the right patient, I'd like to be able to use first_or_create somehow to create the new patient record tied to the run.
I have searched for some examples on this and have come up short except an old Railscast espisode which wasn't very helpful and uses jQuery autocomplete which I'd like to avoid (use selectize or select2 instead).
I will continue working on examples that I find online, but any suggestions on how to do this is what I'm looking for. I feel that I can instantiate the patients from a collection within the controller and use those in a selectize/select2 box to choose the patient and the associated nested field of patient_id. So selecting the patient would not be a problem, but I'm unsure as to how to tackle the creation of a patient that does not match.
This answered my question:
https://gorails.com/episodes/select-or-create-with-selectize-js
I was able to get the behavior down that I needed using this.
Related
I'm currently pretty new to Ruby on Rails, but right now I'm trying to set up a simple platform to create events, manage those events, and purchase tickets to those events. I have two different user types:
Manager:
has_many: events
(with params):
email
password
organization_name
Fan:
has_many: tickets
(with params):
email
password
name
cell_phone
I have two different partials containing sign-up forms for both Managers and Fans. My thought process right now is to have a param called #is_manager in the session that allows my sign-up form to dynamically hide/reveal the partials and to handle logic in the controller.
The sign-in form for both models will be identical, as they can both login using their emails and passwords. My current thought for this is to either include an additional checkbox which filters attempted logins to either the Fan or Manager database, or to require emails to be unique across both databases.
I've looked at a large number of other stack overflow questions, and have looked into Devise (which I was cautioned against while I still don't have a strong handling of Ruby on Rails), as well as some JQuery solutions to dynamically changing this session param, but I haven't found a solution which I feel applies well to me.
Thoughts?
(My current sign-up form code is something like below:)
<h1>Signup</h1>
<h3>Are you a manager?</h3>
<%= link_to_function "Yes", "magic_javascript_function" %>
<%= link_to_function "No", "magic_javascript_function" %>
<%= form_for :session, url: signup_path, method: :post do |f| %>
<%= render 'manager_signup', :f => f if #is_manager %>
<%= render 'user_signup', :f => f unless #is_manager %>
<%= f.submit 'Submit', class: "btn btn-primary" %>
<% end %>
If your new to RoR I highly advise going to The Rails Tutorial by Michael Hartl's railstutorial.org.
I recomend this tutorial because he shows how to create a user model with login sessions etc. without using devise or cancan and this gives excelent insight into what those programs are used for and how they work so you can use them later.
In regards to your specific case I would argue this: What if a member who has only acted as a manger wants to go to another managers event. Would he then need a separate fan account. Alternatively what if a member who has only been a fan wants to organize a local event for his garage band.
See where I am going with this. It might be best for a login/signup page to be agnostic towards these roles.
Where you could use these roles however is in you relationships
here you could do something like this
User.rb
has_many: events
has_many: tickets
Event.rb
belongs_to: manager, class_name: "User"
has_many: tickets
Ticket.rb
belongs_to: event
belongs_to: fan, class_name: "User"
Check the belongs_to api if it this gives you trouble you may need to explicitly set the foreign key.
I have four tables in my database. One is users, another is organizations. One user can have many organizations, and one organization can have many users. This relationship is stored in a third table, called user_organizations, with columns user_id and organization_id.
The fourth table is called organization_details, where I store additional, multi-row information about the organization.
What I want to happen is this: when a signed in user wants to add organization details to an org they are linked to through user_organizations, only the organizations they are linked to should appear in the dropdown list.
I am unsure of how to go about this. The system returns information about the signed in user through current_user, for example <%= current_user.first_name %>.
So I'm trying to do something like this:
collection_select(:organization_detail, :organization_id, Organization.where({id: current_user.id...something something about user_organization being here too}), :id, :name_and_state)
What is the best way to approach this? Thank you very much!
You should be able to use the built in association. Since User has_many Organizations you can call current_user.organizations like this:
collection_select(:organization_detail, :organization_id, current_user.organizations, :id, :name_and_state)
This assumes you have everything hooked up correctly in the models.
You should also check out the Rails Guide to associations if you are new to them.
current_user.organizations will do the trick.
your dropdown would look something like this:
<ul>
<%- current_user.organizations.each do |organization| -%>
<li><%= link_to organization.name, your_path_here %></li>
<%- end -%>
</ul>
Rails gurus, do you know of a standard solution to this problem I've been struggling with?
In my app, the user can define properties for his objects. So before generating his list of objects (let's say they are books), he can specify which properties he cares about and their potential values, and then for each book he will have to input a legal value for each property. So say I put in for my properties: length (legal values "long", "short") and difficulty ("easy", "hard"). On a different bookshelf, a different list of books could have different properties (cover_color "blue" or "red")
So now I am in my book form. "Add new book on this bookshelf." On the partial, I come up with the list of properties relevant to a new book on this bookshelf (length, and difficulty). Then I look up the legal values for each property. I have a select dropdown in which the user can choose one:
<% for prop in #book.properties %>
<%= prop %> :
<%= f.collection_select :prop_value_select, prop.legal_property_values, :id, :name %>
<%end %>
In my book model, I defined a virtual attribute that will create the "join record" PropertyValue. PropertyValue has legal_property_value_id and book_id.
def prop_value_select=(incoming_id_from_form)
PropertyValue.create!(:legal_property_value_id => incoming_id_from_form, :book=> self)
end
The whole scheme works, except my method is only getting called once, for the first property when the form submits, instead of once for each property.
I am racking my brain... seems very simple, but what's the standard rails way to do something like this?
collect all of the properties into an array and generate the models as a callback?
some magic with a partial for each property?
Thank you!
I think the problem is that you are using a nested model, and all your fields will have the same id's, so rails will only store one nested element.
You should be using fields_for which allows you to handle a nested model.
First you need to specify in your model that it will accept nested attributes. Add the following line
class Book
has_many :properties
accept_nested_attributes_for :properties
end
and in your view you would write something like
<% fields_for :properties do |prop| %>
<%= prop %> :
<%= f.collection_select ...
<% end %>
Hope this helps.
I am a .NET guy and I try to understand the concept behind Rails and its Active Record stuff.
As I can see in all examples they always assume that your view is a 1:1 copy of your model. In reality frequently that´s not true.
Like a view that holds a customer and contact person(s) that are not related to that customer. User should be able to edit both (customer and contact person(s) in one view e.g.)
In every example I see that they bind the view directly to ONE activerecord object. All the stuff like the model, validation and so on bind to one object that is mapped directly to the database.
Could a Rails guy explain what´s an elegant way to work with Active Record in real life applications in complex model situations? In the first moment I was thinking about DTOs but I could not imagine that this is the way to go with Rails.
Agree with John....
You asked: "Like a view that holds a customer and contact person(s) that are not related to that customer. User should be able to edit both (customer and contact person(s) in one view e.g.)"
Ok, so this is a Customer model that has some employees, right? If not, replace "Employee" with "Person"
/app/model/customer.rb
Class Customer < ActiveRecord::Base
has_many :employees
accepts_nested_attributes_for :employees
end
/app/model/employee.rb
Class Employee < ActiveRecord::Base
belongs_to :customer
end
Then in your view of the customer
/app/views/customers/show.html.erb
<%= form_for(#customer) do |f| %>
<%= f.text_field :name %>
.... yada yada ....
<%= f.fields_for(:employees) do |ef| } %>
<%= ef.text_field :first_name%>
<%= ef.text_field :phone %>
<% end %>
<%= f.submit %>
<% end %>
The above has 1 form that lets you save the customer and it's employees. Called Nested Form, and I think does the job of needing "view models".
If you just keep it grouped how real-life is grouped, it goes pretty simple.
Because Rails uses an MVC architecture, it's perfectly possible—and often usual—to have a controller that co-ordinates multiple models and provides them to the view for rendering.
I think that thinking about Data Transfer Objects is a blind alley because they're just dumb data holders and ActiveRecord models in Rails have more smarts. They have associated models (I know DTOs can have structural relationships with other DTOs), custom finder methods and validation logic for a start.
Given
As the User, I am at a nested new vendors/5/reviews/new. In addition to :params that will get written to the Review model, I need to be able to include tags that belong to the Vendor model.
I have used acts_as_taggable_on (http://github.com/mbleigh/acts-as-taggable-on):
class Vendor....
acts_as_taggable_on :tags, :competitors
I use formtastic to submit the tags and field_for to make sure that I write to vendor even though the form is on a CREATE Review:
semantic_form_for ....
<% fields_for :vendor do |vendor| %>
<p>
<%= vendor.label :tags %><br />
<%= vendor.text_field :tag_list %>
</p>
<% end %>
I try to display the tags for the Vendor with the following:
Tags: <%=h #vendor.tag_list %>
My outcome: NOTHING.
1) Am I correctly writing the tags? It looks like it is create the right SQL in the console
2) Am I doing the right approach to display the tag list using acts_as_taggable_on?
First, I'm a bit confused why you're using Formtastic (semantic_form_for) when all of the helpers in the form are standard rails helpers (fields_for, label, text_field), so this really doesn't have much to do with Formtastic.
Second, if the form is for a Vendor record (form_for(#vendor)), then fields_for(:vendor) doesn't make any sense. Using fields_for inside a form_for creates a nested form with nested attributes (useful to create a parent record and an associated record at the same time).
I'd need to see a complete sample of the form code to really get a grip on what you're trying to do, but I think you've over complicated something quite simple. Either way, my advice is to correctly understand form_for before using semantic_form_for.