Search two models with Ransack Parameters - ruby-on-rails

I have two models: Patient and Facility.
Creating a new patient I have a modal that opens and does a search on the number of patients. Then, I have 4 fields that the usr can fill in and search for a specific patient. Then, when an existing patient is selected some values are passed to a main form. If a patient is not found, the data is passed also to the main form to create a new patient, based on those values...
I'm using Rails 3.2 and Ransack. Here's an example of the parameters returned on one basic search:
Parameters: {"utf8"=>"✓", "authenticity_token"=>"gT8RPTlPiO6Wf3oLcU5+qSzVOZTjBZyX1Y0qNijT5oo=", "q"=>{"nid_cont"=>"2/14", "province_id_eq"=>"2", "district_id_eq"=>"2", "facility_id_eq"=>"146"}}
Then, on patient controller I have this code:
def patient_samples
#search_patients = Patient.includes(:gender, :province, :district, :facility).search(params[:q])
#patients = #search_patients.result
respond_to do |format|
format.html
format.js
format.json { render json: #patients }
end
end
This code is run when I open the modal and it returns all existing patients. Then, the user is also able to do the search that will only returns the respective rows.
When I select one of the existing patients, I can get all values from it and all the related models, for example:
patient.facility.printer_type
But when the search doesn't find a patient, I would also like to search the printer_type from the facility that I choose on the search parameters.
What I would like to do is to access one of the q: values, in this case
"facility_id_eq" => "146"
And then do something like:
#facility = Facility.find("146")
#facility.printer_type
But I can't seem to be able to access that value... I've read a lot of similar questions here in Stackoverflow, I've read the gem docs on github, I've tried several things, but haven't been able to do it...
I know it's a simple solution, but I'm blocked on it :(
Can you help me?

You can access that value with
facility_id = params[:q]['facility_id_eq']
#facility = Facility.find(facility_id)

Related

Query a list of records with ActiveRecord where foreign keys of each item are present in a hash

I have four models - User, Agency, Listing and Inquiry.
A User has_one Agency, an Agency has_many Listings, and a Listing has_many Inquiries.
I have a query where I get a :user_id, so I can get its Agency and the collection of Listings.
I need the Inquiries that belong to a certain Listing.
My approach is the following, obviously I'm looking for a replacement for all. I'd like to make a query where I can list all the inquiries where :listing_id is the id of one of the listings in #listings.
def index
#agency = User.find(params[:user_id]).agency
#listings = #agency.listings
#inquiries = Inquiry
.all
render json: #inquiries
end
I tried combining various select, includes, where, etc. methods but couldn't come up with a working solution.
Thank you for your help, much appreciated!
We can use mutiple joins in a single query to reach till the resulted association.
def index
#inquiries = Inquiry.joins(listing: { agency: :user }).where(users: { id: params[:user_id] })
render json: #inquiries
end
First off, if you are using something like RuboCop it will probably warn you that you usually only pass one, possibly two instance variables in a method like this. Not that I haven't done it, it's just not considers optimal Rails. That said:
One way might be this:
def index
#agency = User.find(params[:user_id]).agency
#listings = #agency.listings
#inquiries = Inquiry.where(listing_id: #listings.pluck(:id))
render json: #inquiries
end
You can pass an array of things to match with where. pluck gives you an array of what ever columns you pass to it.

Connecting a user model and event model in rails with foreign key?

--UPDATE: I've been doing some more reading and it looks like I should be adding a foreign key - could someone show me how I'd go about doing this? Should I be removing those extra fields I created?
--
I'm new to Ruby on Rails and I'm having trouble with some basic concepts. I've just finished Michael Hartl's book, and I'm using a RailsApps bootstrap-devise-cancan template to start on my first app.
I have a User model and an Event model. I want users to be able to post many events and also attend many events. I added the fields events_attending and created_events to the User table, and the Event table includes users_attending and user_created. I am trying to make it so that when the 'create an event' form is submitted, the user_created field is filled with whichever user posted the event, and that event id is recorded in the users table under created_events.
I've added to the Event model:
belongs_to :user
has_many :users
and to the User model (although I'm not sure if this is correct given that users can belong to multiple events. I looked into has_and_belongs_to_many and thought maybe that was the way to go..):
has_many :events
belongs_to :event
I'm lost as to what to put in the controllers to achieve the desired affect. This is what is currently in the events controller:
def create
#event = Event.new(params[:event])
respond_to do |format|
if #event.save
format.html { redirect_to #event, notice: 'Event was successfully created.' }
format.json { render json: #event, status: :created, location: #event }
else
format.html { render action: "new" }
format.json { render json: #event.errors, status: :unprocessable_entity }
end
end
What should I be adding to the controller, and what else am I missing? Let me know if any more code needs to be seen. Thanks!
The answer to this question is available in the Rails guides and other places. It's clear that you have not grasped the basics of model relations and you should read up on it a bit more. I'll try to help you:
The Users has_many events is the relation for an event that a user has created. That relation is modeld in the database as a user_id column on the Event table. So when a user creates an event that users id is saved in the event record as user_id. Rails then gives you helper methods such as user.events to get all the events that the user has created.
The other relation, users attending events, needs a separate table. You can see why by examining the relation. The one between user and event above is a one to many relation, A user can cerate many events but each event belongs to exactly one user. The relation here is a many to many relation, an event can be visited by many users and each user can visit many events. There is no way to store that information in a normalized way in a relational database. No matter what side of the relation you look at, user or event, the data is an array...
The solution to this is a join table, a table where you have pairs of user_ids and event_ids. Rails can handle this kind of relation as well, it's called a has_and_belongs_to_many relation or habtm for short. Googling that will give you information on how to set it up and work with it.
I'll throw in another note: If you only want to look at the relation from one point of view, as in you will be calling user.event_visits but never event.visiting_users you can get away with a column in the user model and skip the join table. What you need is a serialized column of event_ids that you can then use to get all the events that user will visit. Working with the data this way is not normalized (and thus frowned upon by DBAs) but can be reasonable depending on your needs. It will require a bit more work on your part thoguh.

Rails: spliting table between two forms

The Rails application I'm working on, has two central pieces: users and groups. A user registers through a form, and is added to the users table.
The groups table has four primary columns: name, title, description, and membership.
Groups are handled in two steps.
Step1: the admin creates the group (name, title, description).
Step2: Membership is a JSON field. Admin needs to log in using a second form, and add/edit that JSON structure's fields: group owner, group admins, members, parse / re-parse into a JSON and update the groups table.
The user signup, and groups creation form are working fine. The problem is the second form: creating the group's membership. I am not really sure how to proceed.
What I did is create the link and routes to properly select from the groups, and produce a REST call with the correct params by adding additional routes and links on the Show page. I verified that the l ink is correct, when I hover over it, I see http://myapp.com/groups/3/admin (3 is the correct ID in the groups table).
The methods in my groups_controller.rb are similar to the following:
def show
#group = Group.find(params[:id])
respond_to do |format|
format.html # show.html.erb
format.json { render json: #group }
end
end
I created a groups_admin.html.erb and put it in the views/groups folder. It has in it the logic to construct a set of drop down boxes, allowing the admin to pick from the users list to fill the group membership (the functions are in the groups helper).
What I don't know is how to complete it with a form declaration, etc. in groups_admin.html.erb and what to add to the groups_controller.rb to cause an UPDATE to that particular row (after I turn the returned fields into a JSON). So far, here's what I have added to it
def admins
end
Changing the groups table schema and creating additional groups_admins, groups_owners, groups_members tables is not an option. Any ideas?
You're looking for associations. In this case you probably want a group has_many users and a user has_many groups. Or if you want a user to be able to be in multiple groups you're looking for a has_and_belongs_to_many association. You can read up on this here: http://guides.rubyonrails.org/association_basics.html

Rails, MongoID and embedded relations

I have a few question about MongoID and embedded relations in Rails.
In my model I have:
class Board
include Mongoid::Document
attr_accessible :title
field :title, :type => String
#has_and_belongs_to_many :users
embeds_many :items
end
when I call
Board.all
it returns the whole collection, including also :items.
I've read in many articles/forums that using MongoDB embedded relations should be preferred over referenced ones but I have some questions:
What about performaces? each time i want to retrieve a board i'll also retrieve items inside it: it may be useful sometimes but in the case i want only board's information and not items inside it I should create a new method for not retrieving items.
When I want to update an item the DB will reload the whole document and not only the item I want to retrive, right?
Up to now I've noticed that the only advantage in using embedded document is for something like what in SQL are called "joins" but I also see a lot of performaces problem, there are important reason to use embedded relations over referenced relations?
EDIT
As pointed out by Adam C my thoughts are releated to situations like these:
as explained before I will have Boards each one with many Items inside it and using Rails scaffolding it generates methods that retrieve the whole Board document from the database but many times (for example when editing a Board) i want to load the document without the Items part.
Since I will be using mostly JSON calls my idea was to add an optional parameter to the url like "?get_items" to be set to TRUE in case I want also to get items, in other situations I would use Mongoid's:
Model.without
For example let's take the index action:
def index
#boards = Board.all
respond_to do |format|
format.html # index.html.erb
format.json { render json: #boards }
end
end
I'll need to get only fields specified in Board Model (in that case only :title) without items so I may use:
def index
#boards = Board.without :items
respond_to do |format|
format.html # index.html.erb
format.json { render json: #boards }
end
end
That my cause some problems?
If you need to retrieve items separately, then you should not embed them.
My rules of thumb:
Top-level domain objects (things that you work with one their own, that don't always appear in the context of their "parent") should get their own collections.
Embed when the related things
a. Don't grow unbounded. That is, in the 1-N relation, N is bounded.
b. Always (or nearly always) appear with their parent.
You can also embed if you can prove to yourself that the performance improvements to be gained by embedding outweigh the costs of the multiple queries required to obtain all objects.
Neither embedding nor relating should be preferred. They should be considered equally.

Create join table record automatically, rails 3

Right now my Posts model has_many :tags, :through => :tag_joins
When I add tags, while creating a post, the tag_join records are automatically created.
Now here is what I'm trying to accomplish: While viewing the show view of posts I want to be able to add a new tag.
I tried #post.tag = Tag.new didn't work (returns a "nomethoderror" for tag=)
So I'm trying to figure out how I can add tags and still create those joins automatically.
I am using accepts_nested_attributes etc.
UPDATE: I originally asked how to do this on the index view, but I have changed it to the show view - because I expect it to be a little easier.
You're not too far off with #posts.tags = Tag.new. Here's a couple of ways to do it;
#post.tags << Tag.create(params[:tag])
#post.tags.create params[:tag]
I see a couple of approaches to this problem.. One is to pass through the id of the post with the tag form using either a hidden_field or by using nested routes for tags. Then you can use that in the controller to retrieve the post and use a syntax similar to above.
While that would work, the problem is that it's a bit ugly.. It means your tag controller would be dealing with finding a post (which isn't necessarily wrong, but it shouldn't need to worry about posts. Unless tags can only be associated with posts, that is).
The more graceful way of dealing with it would be to make the form you're showing be a form for the post instance, not a tag. Then you could use nested attributes to create the tag as part of a post.
Take a look at the build_xxx or create_xxx methods that the association (belongs_to, has_many etc) add to the models. You need to create your tag through the post for rails to 'connect' it automatically.
The key observation here is the difference between .new and .create. For my Devour.space application, I was running into the same issue. If you create the object in memory using:
tag = #post.tags.new(tag_params)
tag.save
There will be no tag_joins entry saved to the database. #post.tags will not return your new tag. You must use .create at the moment of instantiation or the association will not be recorded in the JOIN table:
tag = #post.tags.create(tag_params)
#post.tags.last # tag
In my situation, this required a change in how my create action handled requests and errors:
has_many :deck_shares
has_many :decks, through: :deck_shares
....
deck = current_user.decks.new(deck_params)
if deck.save # Does not create entry in DeckShares table
render json: deck
else
render json: deck.errors, as: :unprocessable_entity
end
This became:
begin
deck = current_user.decks.create(deck_params) # creates DeckShare
rescue Exception => e
render json: e, as: :unprocessable_entity
end
render json: deck unless e

Resources