I have an Article model, with a dependent model Photocup. Each Photocup instance has an image attached (using paperclip/imagemagick). I followed the rails guide for adding a second model, the same way Comments are associated with an Article.
http://guides.rubyonrails.org/getting_started.html#adding-a-second-model
It works fine. But I want more control over how the Photocups are displayed. I've created a partial _gallery.html.erb in Views/Article. The gallery partial looks like this:
Photo Gallery
<table class="table2">
<%= render #article.photocups %>
</table>
_photocup.html.erb in Views/Photocup looks like this"
<td>
<%= photocup.label %>
<br>
<%= image_tag photocup.image(:small) %>
<br>
<%= link_to 'Remove Photo', [photocup.article, photocup],
method: :delete,
data: { confirm: 'Are you sure?' } %>
</td>
Works fine, but I can't figure out how to add in a row!
Is there anyway to display the Photocups for the Article I'm looking at the way one does with non-dependent model? For example, an index page would typically have something like this"
<table>
<tr>
<th>Title</th>
</tr>
<%= #photocups.each do |photocup| %>
</tr>
<td><%= photocup.title %></td>
<% end %>
</table>
Could this be done on the show.html.erb page for the article somehow? Could it be done if I created a partial in Views/Photocup?
If it matters, the route looks like this:
resources :articles do
resources :comments
resources :photocups
get 'gallery'
get 'showall'
get 'feature', on: :collection
end
Thank you in advance for any help.
It can be on the articles#show page. Provided your associations are done correctly, you have a:
#article.rb
Class Article > ActiveRecord::Base
has_many :photocups
end
and
#photocup.rb
Class Photocup > ActiveRecord::Base
belongs_to :article
end
You'll have to declare an instance variable under the show action in the Articles controller. It'll look something like this:
#articles_controller.rb
def show
#article=Article.find(params[:id])
#photocups=#article.photocups
end
Then use the code for your example index view in your show view and it should show the rows you are seeking.
Also, side note, this line:
<%= #photocups.each do |photocup| %>
in your example index page does not need an =. Those should be reserved for things you want the user to see in the view, it should be:
<% #photocups.each do |photocup| %>.
Related
I am currently creating a nested form using cocoon. I have a table that takes in information for everyone in a household. the form dynamically creates a new line when the user clicks on add new member. The problem that I am having is that when the form is submitted, only the last line of the table is passed through.
I have tried many different things including changing the attributes of the members and also trying to isolate just the household members so I can see what is happening. I have tried giving them unique id's, but that didn't work. It might be something to do with the rails sever or just some bad code that I can't see.
Here is where I am nesting the form
<tbody class="members">
<%= f.fields_for :household_members do |ff|%>
<%= render 'household_member_fields', :f => ff %>
<%end%>
</tbody>
</table>
<%= link_to_add_association 'Add household member', f, :household_members, data: {association_insertion_node: '.members',
association_insertion_method: :append} %>
This is the beginning of the households_member_fields:
<tr class= "nested-fields">
<% f.hidden_field :id%>
<td><% f.label(:name)%>
<%= text_field(:household_members, :name) %></td>
<td><% f.label(:birthdate)%>
<%= date_field(:household_members, :birthdate) %></td>
<td><% f.label(:ssn)%>
This is my controller
def create
addresses = params[:addresses].permit([:county]).to_h
contact_info = params[:contact_info].permit(params[:contact_info].keys).to_h
household = params[:household_type].permit([:house_type]).to_h
household_members = member_params
#workflow = CreatesUser.new(address_info: addresses,
contact: contact_info, household: household)
#workflow.create
redirect_to users_path
end
private
def member_params
params.require(:user).permit(household_members_attributes: [:id, :name, :birthdate, :ssn, :gender, :hispanic, :race, :or_tribe, :education, :_destroy])
end
When I currently submit two or more household members I only ever get one of them like this:
"household_members"=>{"name"=>"Fake2", "birthdate"=>"2019-07-21", "ssn"=>"fake2", "gender"=>"Female", "hispanic"=>"0", "race"=>"Alaska Native", "or_tribe"=>"0", "education"=>"Some college"}, "disablility_assistances"=>{"disabled"=>"0", "homebound"=>"0", "snap"=>"0", "ohp"=>"0", "med_insurance"=>"fake2"}, "veteran_statuses"=>{"veteran"=>"0"}
I am expecting to get multiple of these. If you have any incite into what I am doing wrong I would greatly appreciate it!
Thanks,
Aala95
After looking at what my code is returning a little more it looks like the nested form is being submitted but only with an ID and delete:
"user"=>{"household_members_attributes"=>{"0"=>{"_destroy"=>"false"}, "1"=>{"_destroy"=>"false"}}}
You have to fix your nested items partial: remove the scoped name --now it will be double scoped, this explains why some attributes are in household_members (your scope and blocked by the strong parameters definition) and some in household_members_attributes (the expected scope). Also there is no need to add the hidden field :id (that will be automatically handled by the index in the array).
So write your partial as follows:
<tr class= "nested-fields">
<td><% f.label(:name)%>
<%= text_field(:name) %></td>
<td><% f.label(:birthdate)%>
<%= date_field(:birthdate) %></td>
<td><% f.label(:ssn)%>
I am a beginner in ruby. I have a table in a view, that when I click on the line / item it should pick up the ID of the selected line and move to the other view that will be triggered, I am 3 days searching on and I can not implement.
The view that should take the ID or another parameter so that in the other I can treat the select to bring more detailed information >>:
<td>
<%= link_to pedido.id, detalhes_backoffice_pedidos_path(:pedido_id =>
pedido.id) , :onclick=>"window.open(this.href,'create_company',
'height=600,
width=600');return false;" %>
</td>
The view ("popup") that is called when clicked on the request id. Obs.:Tried in countless ways, and at the moment she is like this ... >>>>
<div class='container-fluid'>
<div style='display: block;' class="col-xs-6 esquerdo ">
<label>Num.pedido<%= pedido.id %></label> <br>
<label>nome</label> <br>
<label>telefone</label> <br>
</div>
Controller>>
class Backoffice::PedidosController < BackofficeController
.....
def detalhes
render :layout => "application"
#pedido = params[:pedido_id]
end
I am totally lost, after trying so much .... If you can pass some example link for study, it will be very useful too !!
It has become clear that you just need to use AJAX to show the selected pedido details on the page. Rails has an easy way to do this.
First put in a table with a div below it for displaying the pedido info. Each row in the table has a link to the controller action that will do the AJAX. Use remote: true to make the link AJAX, so the user is not taken to another page.
<table>
<tbody>
<% #pedidos.each do |pedido| %>
<tr>
<td><%= link_to 'More info on this Pedido!' fetch_info_pedidos_path(pedido), remote: true %></td>
</tr>
<% end %>
</tbody>
</table>
<div id="pedido-info"></div>
Make the route for the action in the pedido controller. This is in routes.rb
resources :pedidos do
get :fetch_info, on: :member
end
This should create a path that looks like /pedidos/:id/fetch_info with the name fetch_info_pedidos
The link in the table will make a js format request along this route so the controller action must be ready to handle that. The pedido id will come as a parameter called :id
def fetch_info
#pedido = Pedido.find params[:id]
respond_to :js
end
Since it responds to a js format request it will respond with js content, not html - that means we need to have a js file as the view, but before we make that let's make a partial for displaying pedido info. This can be dropped into any view using the render method. It will be in app/views/pedidos/_pedido.html.erb (you have to use an underscore at the start of the file name to show it is a partial) You can put any content in here you like, using the pedido variable to refer to the pedido. Here's an example:
<h2>Pedido!</2>
<p>number: <%= pedido.id %></p>
<p>nom: <%= pedido.nom %></p>
<p>telefone: <%= pedido.fone%></p>
Finally let's make the js that gets passed back to the browser. This will be an erb file like other views. It will just put the _pedido partial as the content to the div under the table. app/views/pedidos/fetch_data.js.erb
$('#pedido-info').html("<%= j render #pedido %>");
That's all you need. The j here escapes the output of the render method so that it plays nicely inside a javascript string.
There's a bit of Rails magic happening here, which I will explain, because, as you would learn at any wizard training school: "don't use any magic you don't completely understand"
The render method expects the name of a partial to render, and optionally some local variables to pass. If it's given only an ActiveRecord object, it will look for the partial that matches the class name of the object (Pedido goes to _pedido.html.erb) and it passes the object as a local variable also with matching name. so render #pedido gets translated to render partial: 'pedido', locals: {pedido: #pedido}
I haven't tried any of the code in this answer, I just wrote it off the top of my head, so you may have to jiggle it a bit to get it to work.
here's a link to a page you might have come across if you had simply Googled how to do this. It says essentially the same as what I have said here, except his AJAX brings in a whole collection of objects, not just one at a time.
I may have misunderstood the question, but it seems to me you just need to link to the detalhes action for each pedido in the table.
here is the table:
<table>
<tbody>
<% #pedidos.each do |pedido| %>
<tr>
<td><%= link_to 'Detalhes this Pedido!' detalhes_path(pedido) %></td>
<td>More table data related to this pedido</td>
</tr>
<% end %>
</tbody>
</table>
and in the routes you would have something like this:
resources :pedidos do
get :detalhes, on: :member, as: 'detalhes'
end
This is how my CategoriesController looks like:
class CategoriesController < ApplicationController
def index
#categories = Category.all
end
def show
#category = Category.find(params[:id])
end
end
inside my show.html.erb I wrote this to display the category name:
<h2><%= #category.name %></h2>
I also have a PagesController which I made relations with the Category
I have few Pages assigned to Category (for example category_id: 1)
When I click on the category link from my homepage:
<%= link_to "category", category_path(cat) %>
It goes to the show page which is great
How can I display on the show.html.erb all the Pages that belongs to this category that I've clicked on?
You should call the pages assosication with the category model as,
<%= #category.name %>
<h1> PAGES </h1>
<table>
<tr>
<% #category.pages.each do |page| %>
<td> <%= page.title %> </td>
<td> <%= page.content %> </td>
<% end %>
</tr>
</table>
This will do for you.
You should use includes for enhanced performance of your application. It will return all expected records from pages also and that's without firing database query again. #category.pages in ERB will not make database query. Hence, you will have efficient code.
In your show action:
def show
#category = Category.find(params[:id]).includes(:pages)
end
In show.html.erb:
<%= "Category: #{#category.name}" %>
<h1> POSTS </h1>
<table>
<tr>
<% #category.pages.each do |page| %>
<td> <%= page.field1 %> </td>
<td> <%= page.field2 %> </td>
<% end %>
</tr>
</table>
Rich Peck edit
Normally, ActiveRecord does something called lazy loading, which means that it will only execute a DB query when it needs to. This is normally highly efficient; unfortunately causes a problem when you call associative data.
When calling #category.pages, you get the n+1 issue, which means that each time you call the Category.find query, an extra query will be used to load the pages:
The above code will execute just 2 queries, as opposed to 11 queries in the previous case:
SELECT * FROM clients LIMIT 10
SELECT addresses.* FROM addresses
WHERE (addresses.client_id IN (1,2,3,4,5,6,7,8,9,10))
So using .includes essentially appends all the pages to your #category, making it much more efficient than letting it load lazily.
Well mostly it depends on how you made your relationships between category and page. With what i can see from your code, you can do something like this.
#pages = Page.where(:category_id => 1)
Update
As per to your relationships
#pages = #category.pages
The default URL generated after a get request in Rails isn't very nice to look at.
Using the meta_search gem in a Rails 3 application, I've created a select menu to filter a list of articles by category. The code looks like this:
<%= form_for #search, :url => articles_path, :html => {:method => :get} do |f| %>
<%= f.label :category_name_equals, "Filter by category:" %>
<%= f.collection_select :category_name_equals,
Category.all(:order => "name"), :name, :name, :include_blank => true %>
<%= f.submit "Search" %>
<% end %>
<table>
<tr>
<th>Title</th>
<th>Category</th>
</tr>
<% for article in #articles %>
<tr>
<td><%= link_to article.title, article %></td>
<td><%= article.category.name %></td>
</tr>
<% end %>
</table>
Right now, when the form is submitted, a lengthy URL is returned containing the params hash:
http://localhost:3000/articles?utf8=%E2%9C%93&search[category_name_equals]=
Reviews&commit=Search
I want to keep the URL as clean as possible, for example:
http://localhost:3000/articles/category/reviews
or
http://localhost:3000/articles?category=reviews
What are some solutions to make the params hash URL more readable by humans?
You can't do that with a form with get method. it's an HTML issue.
You need add some Javascript to convert your URL to pretty URL or you can get URL in your controller in your rails application and redirect to your pretty URL.
Like shingara said, don't use a form at all. Instead use a list of links, and fancy things up with some css/js that makes your list behave/look like a drop-down menu:
<ul>
<% Category.all.each do |c| %>
<li>
<%= link_to(c.name, :controller => :articles, :action => :browse, :category => c.tag) %>
</li>
<% end %>
</ul>
For your routes, you'll want something like this, but DRYer:
routes.connect '/articles/browse/:category', :controller => :articles, :action => :browse
You can find many examples of CSS/JS dropdowns very easily: http://bit.ly/dRtQNd
You can find examples of good CSS/JS dropdown menus with considerably more effort ... unless you give up just ask for advice on stack overflow again :-). (Coding rudimentary versions of standard UI components from scratch is simple these days using jQuery and whatnot, so lots of people do it. Coding ones that "feel right" is actually very hard; fewer people do that!)
P.S. That form_for #search looks utterly weird. This is not what form_for #your_model_object was meant for...
I am trying to add a featured post feature to my Ruby on Rails Blog. So far I have added a featured_post column to my post table and it passes a 1 if the check box is selected and 0 if not.
Now I am attempting to pull out these posts by doing the following:
/views/posts/index.html.erb
<% #featured_post.each do |post| %>
<%= post.title %>
<% end %>
And in the posts_controller.rb I am doing the following in the index action:
#featured_post = Post.all
Obviously this brings in all the post titles which is not what I want. I am assuming I have to add something to the controller to all for this but not sure what that is.
In your post model, write this
named_scope :featured,:conditions => {:featured_post => true }
write this in your controller
#featured_posts = Post.featured
and in view use this,
<% #featured_posts.each do |post| %>
<%= post.title %>
<% end %>
now you should get all the featured posts.