In my app, I have four models - Users > Clients > Jobs > Tasks
I have all of the associations set up fine (as per here --> Advice on RoR database schema and associations), but I'm stuck with a query.
Basically, what I'm doing is:
#potentialjobs = current_user.jobs.where(:status => "potential")
But in the results, I also want to include the client attrs in addition to the job attrs.
Can anyone point me in the right direction?
Thanks.
UPDATE
Appreciate the suggestions below.
I thought this should have been pretty straightforward, but I'm beginning to think the problem must lie somewhere else in my codebase.
Whenever I try to include or join the client model in this query or as a second-order association in the model itself, I get the following error:
uninitialized constant Job::Clients
...and I'm not sure why. So, can anyone shed some light on this for me?
ANOTHER UPDATE
Solved - I had a pluralisation error in one of my models. Gah. Thanks all.
You can access the client's fields through the association in both ways.
<% #potential_jobs.each do |job| %>
<%= job.client.name %>
<% end %>
Related
I'm having a few problems with multi file uploads in rails 4, I've got it working using carrierwave and polymorphic associations but its creating a file filed for every image in the view. This makes sense as its creating fields for the associated model.
If there is a better or more standard way of doing this in rails 4 I'd be grateful for your advise.
Here is a gist to what I'm doing: https://gist.github.com/lperry65/5805b5f41495f8a820b7
Screen Shot
http://cl.ly/image/3y3w203z3G1f
There seems to be lots of ways to accomplish this, but most of the info I found while googling is for rails 3. It's my intention to use UploadiFive for the front end once I iron out the wrinkles.
http://www.uploadify.com/download/download-uploadifive-standard/
Changing <%= f.fields_for :images do |i| %> to <%= f.fields_for :images[0] do |i| %> stopped the file input from being duplicated for every image. I can't say I'm happy with it but it works for now.
I'll update the gist to reflect any other changes, it's all working now so I'll leave it until I find a better solution.
I have "quick add" form that is responsible for creating a Foobar. Once it submits/saves, you are returned to the form to add the next Foobar. I now have polymorphic Tasks that I'm wanting to add to the Foobar as it's being created. The Tasks require no details in this context, so I've opted to have a checkbox on the form that says "Do This Task". If checked when the form is submitted, I'd like to have a Task created and associated to the Foobar.
Doing it isn't hard, but I'm struggling to find what seems to be the "right" way of doing it.
Option 1: The Foobar accepts_nested_attributes_for Tasks so I can create a nested form, but there's really nothing to nest. The checkbox doesn't represent a valid field on the Task, only that I want the task created. I could use #foobar.build_task and put some hidden fields in the form for the task, but I'd have to use JS voodoo to prevent the fields from submitting if the checkbox isn't checked. This just seems dirty and wrong.
Option 2: I can put some logic in FoobarController#create that looks for the checkbox and builds the task onto the Foobar before save. The issue here is that the Task is polymorphic and could be tied to other things, too. There may even be multiple "types" of tasks tied to the single Foobar being created. This solution is better than Option 1, I think, but isn't very DRY. Any such logic in the controller would end up being duplicated in the controllers for other taskable things.
Option 3: Have a before_save on Foobar that looks for the presence of a pseudo-field called "create_task" and then builds the task. This moves the duplication out of controllers and into taskable models, but it's no more a duplication than the duplicated "has_many :tasks" line in each model. Still, it doesn't seem like it's the model's job to look for such a field and act on it.
so.... I'd really appreciate some thoughts.
UPDATE #1: A little extra info...
A Task also has a creator and an assignee, both are users in the system. A creator should be automatically assigned based on a current_user method, which of course is available in the View and Controller, but not the model. I think the excludes right away the possibility of the answer being purely model based (such as option 3). I think it also hints at the answer not being view based (such as option 1), as the user should be set server side where it can't be tampered with. So perhaps the answer lies somewhere in the Controller? Perhaps some sort of helper method to wrap up the logic to be duplicated in each Controller that handles taskable things?
UPDATE #2: My current leaning...
I spent some time speaking with a respected developer friend and am further convinced the answer is closest to option 2. Both the view and model seem wrong. The controller makes sense, but the main problem is the potential of repeated code. I think the answer is going to be in finding the best way to factor out the controller code that handles the attachment of Tasks (or other polymorphic things like comments, file uploads, etc.) to the object that controller is responsible for. When I have a solution I'm happy with, I'll try and post it here. Thanks for the input, everyone!
I would go with something that is a derivative of Option 1. There are actually two solution I might use though.
Solution 1
This one is much simpler but isn't quite as extensible.
Using the existing accepts_nested_attributes_for :tasks, make sure you have this option though:
accepts_nested_attributes_for :tasks, :allow_destory => true
Then in your in your form use (assuming task_collection is a collection of prebuilt tasks):
<%= form_for(#record) do |form| %>
...
<%= form.fields_for :tasks, task_collection do |task_fields| %>
<%= task_fields.check_box(:_destroy,{},0,1) %> Do This Task
<% end %>
...
<% end %>
Basically this is going to take Task association-object and if the box is checked persist it, otherwise mark it for destruction. This should prevent any so called "JS voodoo" since any such logic is handled in the model.
Solution 2
The other option, but the much more complex option, I might use is to:
def tasks_attributes=(tasks_attributes)
Doing that in each applicable model(or an included module) then handling all the tasks attributes when they're submitted from the form.
It involves handling the task_attributes in the model. which means you have to build your forms a certain way and some other subtle details. But using this approach you wouldn't have to build a Task object then destroy it, you could just handle the submission data to create tasks.
The details of doing this is pretty in-depth and not something I really want to go into. But you seem resourceful enough that just knowing it's there could help you out.
More info on this is in the fields_for documentation and the accepts_attributes_for implementation.
In this situation I would go like this:
class Foobar
has_many :tasks
attr_accessor :add_task
after_create :create_task, if: add_task == true
private
def create_task
tasks.create(...)
end
end
I feel like there should be a simple answer for this question, but I haven't been able to manage.
I have 3 models: User, Course, and Textbook. My model associations are working just fine, but I will include them if necessary. In my application, I want a view to display the courses for which the user owns textbooks and all other courses for which the user does NOT own the textbooks. In pseudocode, it should look like
#courses_with_books = current_user.textbooks
#courses_without_books = current_user.courses.where(:id != #courses_with_books.course_ids)
I can complete that second line using complicated loops, but the processes seemed silly so I've been researching a way to gather the information I need with a single query and have yet come up with nothing. Thanks in advance :D
In general, if you want to check that some attribute is not inside of some given collection, try 'NOT IN':
current_user.courses.where("id NOT IN ?", #courses_with_books.course_ids)
For more on Active Record Queries, check out the Active Record Query Interface Guide.
rathrio is on the right path. I think for the first part you could do
#courses_with_books = current_user.textbooks.collect(&:course)
If you're trying to display their titles, do
<% #courses_with_books.each do |cwb| %>
<%= cwb.title %>
<% end %>
I have created a database of researchers and the papers they have written in Rails. I need to be able to filter it by author in such a way that information is drawn from the database onto a page in the persons name (for example if there is a researcher called Dr. A. Researcher, I need to be able to go to his page, and that page will be populated with papers that he/she has written automatically). I have been working on this for a while now, and have gone round in circles so many times, Im not exactly sure what I am looking for (though I think its probably going to be AJAX based). Filtering the database seems quite straightforward, but I cant seem to find any information about sending the results of that filter to a specific page.
As I say, Im not totally sure what Im looking for here, so someone may have had a similar issue that has already been answered. If that is the case, I apologise. Any help anyone has about this would be very gratefully received.
Cheers
Seems like you would just want to use the show action.
In your controllers/researchers.rb controller add
def show
#reseacher = Reseacher.find(params[:id])
end
or possibly
def show
#reseacher = Reseacher.find(params[:id], include: [:papers])
end
then in your views/show.html.erb view you can just add
<% #reseacher.papers.each do |p| %>
<%= p.title %>
<%= p.otherattribute %>
<% end %>
Also you will need to ensure your relationships are setup correctly in your model
in models/researcher.rb
add
has_many :papers
to the Researcher Class
and in models/papers.rb
add
belongs_to :researcher
to the Paper Class
localhost:3000/reseachers/1 where 1 is the id of the researcher should then return the papers for that researcher
I am implementing in Ruby on Rails and I am trying to work with the collection_select, I'm a newbie. I just want to do, I have a list with groups and a list with roles. These are both models. So, I list my groups, and next to that, I have a dropdown list with the role for the group. each group has 1 role.
I implemented some code already, but the collection_select always only remembers the last item. So I want a list with groups, connected with the desired role. But, now I only have 1 item. This is my view:
<% #groups.each do |group| %>
<li>
<%= collection_select('group', 'role_id', #roles, 'id', 'name') %>
</li>
<% end %>
I don't really know what to do now? Someone who knows what I am doing wrong?
Thanks
So, I assume that you're doing a form? What model does the form belong to?
To help debug this sort of thing, usually it'd be a good idea to check your development.log file to see what parameters the form is passing to the controller. Something like:
Parameters: {"commit"=>"Save", "action"=>"update", "_method"=>"put",
"id"=>"6168", "group"=>{"role_id"=>"2", ...}, "controller"=>"groups"}
Now, usually a Rails controller is expecting a form with the data for a single model. If you're wanting to update multiple models or rows at the same time, you're going to have to get creative.
First thing to do might be to try returning an array of groups. Your form at the moment is not using an array. I doubt that these Rails helpers will help you though. Helpers like these are designed to update one ActiveRecord object at once.
It's possible you may need to rethink the design of your app to better fit the Rails way, or roll your own form and iterate over the array that it passes through. Doing it the Rails way is the recommended option, it just might take some brain bending from your end to figure that part out. If you need help, maybe provide more information on what you're actually trying to achieve.