I feel the need to apologize for asking such a simplistic question, but I'm getting increasingly frustrated with the Rails Guides. I'm sure they answer my question, but they don't provide enough context for me to really understand how to apply what they're giving me. Nor is Google much help, though I may just be searching the wrong terms/phrases. Given that disclaimer, I'm just going to go ahead and ask:
I have an Image that HABTM Album. To support that, I have an albums_images table with image_id and album_id fields (no others). For the life of me, I can't figure out how to populate my image form partial so that the user can select the albums a newly uploaded image should belong to.
I'm learning Rails, so I really just want the basics. I'm sure there are fancy plugins to do this a hundred ways, but I'd like to learn the basics first and build from there. My form partial is pretty much textbook:
<% form_for( #image, :html => { :multipart => true } ) do |f| %>
# All the basics you'd expect to see.
<% end %>
My most recent attempt doesn't work any better than any other variation I've tried, but it looks like this:
<p>
<%= f.label :album_id %>
<%= f.select( :album_id, current_user.albums, :id, :name ) -%>
</p>
Again, I recognize the simplicity of the question I'm asking and I've read what I can find, but I haven't been able to put it together into a complete solution. There seem to be many ways to do it, but no real discussion of each one, their pros/cons or how to really use them in a larger context.
Thanks.
UPDATE: A couple of keys to note and a code correction. First, there's a HABTM relationship between images and albums. Neither model table has a FK directly referencing the other. Second, the album collection should be accessed as current_user.albums (corrected above). A user has_many albums and an album belongs_to user.
UPDATE: At the request of theIV below, at the moment, with this code:
22: <p>
23: <%= f.label :album_id %>
24: <%= f.select( :album_id, current_user.albums.collect {|a| [a.name, a.id]}) -%>
25: </p>
I get this error:
undefined method `album_id' for #<Image:0x1042ec110>
I get the error in line 24.
I think that select elements are one of the more confusing aspects of Rails, because as you said there seem to be a number of ways to do it.
Try this:
<%= f.select(:album_id, #image.albums.all.collect {|a| [a.name, a.id]}) -%>
Well, I'm not sure it's the best way, the Rails way or, frankly, even an elegant way, but here's the code I've used that seems to be working so far.
<%= f.label 'Albums' -%>
<%= collection_select( :image, :album_ids, current_user.albums, :id, :name, {}, { :multiple => true } ) -%>
At this point, when I say "working", all I can really attest to is that the page renders with no errors and the appropriate album or albums are selected when I edit an image. I'm still shocked at how difficult it was to cobble together a "full" solution from a lot of disparate sources.
Related
Seeing as the documentation for this gem is absolutely useless for beginners like myself (they the docs it doesn't say which code needs to go in which file), I figured I might get some better help here for my Rails 4 app instead of the official docs.
I'm not sure if acts-as-taggable-on is the best solution for my problem, but here's what I'm trying to do: I'm creating a business directory that works with tags instead of categories so that a bar/lounge can belong to both a bar, and a lounge. Perhaps someone knows a better solution instead of using acts-as-taggable-on?
There are no errors when I try to create or view the tags, but the problem is that the tags arent' being saved. When I try to view the business which has tags, it shows up empty. Same thing when I try to edit it.
This is what my model looks like:
class Business < ActiveRecord::Base
validates :name, uniqueness: true
acts_as_taggable
acts_as_taggable_on :tag_list
end
The form:
<%= form_for(#business) do |f| %>
...
<div class="field">
<%= f.label :tag_list, "Tags (seperated by commas)" %><br>
<%= f.text_field :tag_list %>
</div>
...
<% end %>
The view:
<p>
<strong>Tags:</strong>
<%= #business.tag_list %>
</p>
Anyone know what is preventing the tags from being viewed/saved?
Perhaps there's better documentation out there that someone could provide.
update: I'm also using Active_Admin, which seems to be causing some problem according to Matt Boldt. After following his tutorial my problem remains unsolved.
possible it is an array issue? not sure. what version of acts_as_taggable are you using?
try adding to your strong params to ask for an array.
def business_params
params.require(:business).permit(:xxx, :xxx, :tag_list => [])
end
I had the same problem and changing :tag_list => [] with :tag_list fixed it
I guess it depends by the type of input you use in your form, in my case was a text input
def business_params
params.require(:business).permit(:xxx, :xxx, :tag_list)
end
I was having the same problem and checked Terminal to see where the error had occurred, I got this
Unpermitted parameters: tag_list
I had forgotten to add :tag_list to the strong params accepted attributes in the controller for the model I was using tags with. Try that!
A quick warning: I am pretty new to Rails, and my knowledge is somewhat cookie-cutter-esque. I know how to do certain things, but I lack that vital understanding of why they always work.
I currently have a User model that has in it a bunch of information, like address, email, etc. In addition, it also has a hash called visible. The keys in that hash are each of the pieces of information, and the value is either true or false for whether the user wishes that information to be publicly visible. While I'm not sure if this is the best way to go, I can't think of any other way other than making a whole ton of boolean variables for each bit of information. Finally, I serialize :visible for storage in the database
What I would like is in my edit view to have a checkbox beside each field of info that represents the visible attribute. After reading tons of other posts related to this topic and trying numerous variations of code, I always end up with some kind of an error. The code that looks most intuitively correct to me is as follows:
<%= form_for(#user, :id => "form-info-personal") do |f| %>
...
<%= f.label :name %>
<%= f.text_field :name %>
<%= f.check_box :visible[:name] %>
But I get an error message saying that a Symbol cannot be parsed into an integer. I'm not sure where this parse is even trying to happen, unless its viewing :visible as an array and trying to use :name as an index.
I apologize in advance if this question is trivial/seemingly nonsensical/lacking vital information/etc. Any tips, suggestions, links, or what have you would be very appreciated, even if they're along the lines of "you're doing this fundamentally wrong, go back and do it this way".
-Nick
Rails 3.2 introduces a nice addition to ActiveRecord, which allows you to store arbitrary settings in a single field.
class User < ActiveRecord::Base
store :settings, accessors: [ :color, :homepage ]
end
u = User.new(color: 'black', homepage: '37signals.com')
u.color # Accessor stored attribute
u.settings[:country] = 'Denmark' # Any attribute, even if not specified with an accessor
So, your code could look like this:
# model
class User < ActiveRecord::Base
store :settings, accessors: [ :name_visible, :email_visible ]
end
# view
<%= f.label :name %>
<%= f.text_field :name %>
<%= f.check_box :name_visible %>
I'm creating an application that tracks users and achievements (think, xbox live, etc.) These tables are linked via a join table. I would like to have a search form on my index that lets users type in a users name and a new page is loaded with a list of all achievements that user has earned. I'm not entirely sure how to set up this search form, on the index, to actually search the user table and return the results on a new page. Any help would be greatly appreciated. If you require more information then I'll be happy to provide it.
Here's a bit of skeleton code to get you started based off what I think you need from what you have said. I hope this is useful.
For the search bit you could do something like this in your index view:
<%= form_for User.new, :url => "search" do |f| %>
<%= f.label :name %>
<%- f.text_field :name %>
<%- end %>
In your controller:
def search
q = params[:user][:name]
#users = User.find(:all, :conditions => ["name LIKE %?%",q])
end
and in your search view:
<%-#users.each do |user| %>
Name: <%=user.name %>
<%- user.achievements.each do |achievement| %>
<%= achievement.name %>
<%- end %>
<%- end %>
You would, of course, need to ensure the users and achievement models are correctly linked:
class User << ActiveRecord::Base
has_many :achievements
end
There are plenty of tutorials and things about this e.g.:
http://blog.devinterface.com/2010/05/how-to-model-a-custom-search-form-in-rails/
Look the thing is every basic explanation in Rails3 starting with the Initial Tutorial provided by them explains you how to setup a new Controller/Model. The example was only one of thousands explaining the same problem.
It is a very broad range of different things you can do to achieve this. Basically you have to put some code in the controller:
which handles the search (including the activerecord stuff or whichever technique you use to access your model)
which sets some variables necessary for the search form
Setup two routes etc... Its to broad and completely covered even by the basic official rails3 tutorial.
Here is an application based on searchlogic is very useful and you can search by whatever you want
https://github.com/railscasts/176-searchlogic
You may want to check out the Ransack gem. https://github.com/activerecord-hackery/ransack
This is probably a very simple fix but I've been unable to find an answer just yet.
My application has orders and tasks. Orders have many tasks. When a user clicks new task in the show order view, it passes the order.id:
<%= link_to "New Task", new_task_path(:order_id=> #order.id) %>
The url shows:
/tasks/new?order_id=1
I just don't know how to extract this and use it in my form? I have tried:
<%= f.text_field :order_id, :value => #order_id %>
But it's not working.
You can do:
<%= f.text_field :order_id, :value => params[:order_id] %>
Alternately, capture the value (with params) in the controller and assign it to #order_id there.
You are doing this wrong, which is a big deal in Rails where convention-over-configuration is such an important ideal.
If an order has many tasks, your route should look like this:
/orders/:order_id/tasks/new
And your routes should be configured thusly:
resources :orders do
resources :tasks
end
You should [almost] never find yourself passing around record ids in the query string. In fact, you should almost never find yourself using query strings at all in Rails.
I have created a form that needs to show data from 2 tables (parent and child). When the form is submitted only the child fields are updated (the parent fields are meant to be display only). While the parent model fields are displayed these need to be protected from updates (preferably via the formbuilder, rather than via css).
FWIW this is a pretty common master/detail use case. However I have not been able to find any examples of this - most of the examples I've seen seem to be trivial/single model display/update where all displayed fields are updateable).
Any ideas/samples/suggestion/tutorials/examples of real world, multi model Rails forms would be helpful.
TIA
Just out of interest, why bother going through the motions of creating a multi-model form when you only want to update the child record? My advice would be keep your form simple, I.e. make it a child form and just display the data from the parent record. If needs be, you could even style that display to look like part of the form, although I think that may throw the user off.
If you really need to do what you are doing, I would still use CSS to disable/readonly the input fields and in your controller update action, only pass the attributes you want to update into the update_attributes method call.
Finally, maybe look into the attr_protected method to prevent the fields you may want protecting from accidental mass-assignment.
I agree with tsdbrown, I don't think a complex form is required. If you'd like to learn more about complex forms or you really have your heart set on using a complex form I'd recommend watching the Railscasts episodes (73 - 75).
As tsdbrown said before, you are adding a complexity layer to your forms that's not need. If all you want is to update a detail model, while showing some info of it's parent, you could just do so with something like:
Order number: <%= #line_item.order.number %>
Order date: <%= #line_item.order.order_date %>
<% form_for #line_item do |f| %>
<%= f.label :quantity %>
<%= f.text_edit :quantity %>
<% end %>
When you'd like to edit both, then you can research on the field_for and nested forms methods (the Railscasts suggestion mentioned before it's great).
Thx for the responses which helped resolve my problem/question. Just want to close this out in case it helps others in the future.
Turns out I had been getting an error trying to reference my parent data element (patients.lname) as it was being passed in an array of results, rather than as a single result. In my view controller I had:
#visit = Visit.all(:select => "visits.id, visits.visittype, visits.visitdate, events.patient_id, patients.lname",
:conditions => ["visits.id = ?",params[:id] ],
:joins => "INNER JOIN events on events.id = visits.event_id INNER JOIN patients on patients.id = events.patient_id" )
In my view I had (this was giving me an invalid reference as I was doing a find all above):
<h1>Editing visit for patient :
<%= #visit.lname %> # should be <%= #visit[0].lname %>
</h1>
Below is the improved (and simpler) version where I find the specific record I need (basically replacing find all with find first):
#visit = Visit.find(:first, :select => "visits.id, visits.visittype, visits.visitdate, events.patient_id, patients.lname",
:conditions => ["visits.id = ?",params[:id] ],
:joins => "INNER JOIN events on events.id = visits.event_id INNER JOIN patients on patients.id = events.patient_id" )
And in the view:
<% form_for(#visit, :builder => LabelFormBuilder) do |f| %>
<%= f.error_messages %>
Name: <%= #visit.lname %>
<%= f.text_field :visittype %>
<%= f.date_select :visitdate %>
<p>
<%= f.submit 'Update' %>
</p>
<% end %>
Sometimes it's hard to see the wood for the trees! Hope this helps someone else.