I'm new to RoR, so please be gentile. I'm not sure, if I search for the right topic. However, I've spent the whole day trying to figure out, how to work with the has_man, belongs_to and so forth asset associations.
Right now I have two assets:
sqlite> pragma table_info(meetups);
0|id|INTEGER|1||1
1|name|varchar(255)|0||0
2|owner|integer|0||0
3|dateOfInception|datetime|0||0
4|homeTown|varchar(255)|0||0
5|created_at|datetime|0||0
6|updated_at|datetime|0||0
7|activity_id|integer|0||0
sqlite> pragma table_info(activities);
0|id|INTEGER|1||1
1|name|varchar(255)|0||0
2|location|varchar(255)|0||0
3|startDate|datetime|0||0
4|duration|integer|0||0
5|description|varchar(255)|0||0
6|created_at|datetime|0||0
7|updated_at|datetime|0||0
8|image|varchar(255)|0||0
9|meetup_id|integer|0||0
So I can create a new meetup and select multiple saved activities. For every meetup we can select a multiple activities. If I create a meetup, they corresponding activities are also stored correctly, as you can see in the image below:
Image
However, it's not useful to output them just like an array. It would be great, if the activity name would appear. But how is that possible? I tried so many things, renaming the db foreign keys, create a find method in the meetup controller... but nothing worked. Please help me out here - I think I'm very near but someting I dont know doesnt work.
<% #meetups.each do |meetup| %>
<tr>
<td><%= meetup.name %></td>
<td><%= meetup.owner %></td>
<td><%= meetup.dateOfInception %></td>
<td><%= meetup.homeTown %></td>
<td><%= meetup.activity_ids %></td>
<td><%= link_to 'Show', meetup %></td>
<td><%= link_to 'Edit', edit_meetup_path(meetup) %></td>
<td><%= link_to 'Destroy', meetup, method: :delete, data: { confirm: 'Are you sure?' } %></td>
</tr>
<% end %>
class MeetupsController < ApplicationController
before_action :set_meetup, only: [:show, :edit, :update, :destroy]
# GET /meetups
# GET /meetups.json
def index
#meetups = Meetup.all
end
Many thanks for your help!
Try this in your view:
meetup.activities.map(&:name).join(',')
That should show the data you want. For performance reasons, you'll want to add .include(:activities) to
the controller action that loads your list of meetups.
It sounds like you're trying to model a Has And Belongs To Many relationship, though? You'll need a third table to model that correctly.
If that's not what you're wanting to model, you should remove the activity_id column from the meetups table.
Related
I am new to Rails 5 and working on a project where in there is a page for each categories and will only show the blog items with specific or same categories.
For instance: Blog Title 1 to Blog Title 5 has a category "Tech" and Blog Title 6 to Blog Title 8 has a category "Business".
If I click on http://localhost:3000/blogs/tech it will show the Blog Title 1 to 5 and if I click on http://localhost:3000/blogs/business it will show the Blog Title 6 to 8.
To do these what I've tried is create custom scope on my blogs controller:
class BlogsController < ApplicationController
def index
#blogs = Blog.all
end
def business
#blogs = Blog.business
end
end
And then on my blog model:
class Blog < ApplicationRecord
def self.business
where(post_category: 1)
end
end
I also created a new view for my business method to show all the business type category blog items and just copied the same content on my index.html.erb file:
<p id="notice"><%= notice %></p>
<h1>Post Category 0</h1>
<table>
<thead>
<tr>
<th>Title</th>
<th>Body</th>
<th colspan="3"></th>
</tr>
</thead>
<tbody>
<% #blogs.each do |blog| %>
<tr>
<td><%= blog.title %></td>
<td><%= blog.body %></td>
<td><%= link_to blog.status, toggle_status_blog_path(blog) %></td>
<td><%= blog.post_category.title %></td>
<td><%= link_to 'Show', blog %></td>
<td><%= link_to 'Edit', edit_blog_path(blog) %></td>
<td><%= link_to 'Destroy', blog, method: :delete, data: { confirm: 'Are you sure?' } %></td>
</tr>
<% end %>
</tbody>
</table>
<br>
<%= link_to 'New Blog', new_blog_path %>
And finally I updated my routes:
get 'blogs/business', to: 'blogs#business'
While this will work for single items. Putting it manually wont work if each time I create a new category plus I don't know exactly what will be the user of the app will add on the category title. How can I do this programmatically so it will create new pages each time a new category is being created instead of adding manually and creating views each time?
Are there any ways to do these?
Side Note: Blog and PostCategory table are related to each each other via post_category_id.
You do not have to use scopes here. Just use BlogsController#show to display posts from a given category.
Start with adding a slug field for the PostCategory (in the database). Right now you are using title in the URL, but it has to be changed to escaped value (without spaces, special characters, etc.).
You can probably do it with a gem, or you can use the code from my gist. Just remember to adjust it to your model and fields.
Then, add a route (routes.rb):
get 'blog/:slug', to: 'blogs#show', as: :blog_category
Finally, in your BlogsController, add show method:
def show
category = PostCategory.find_by(slug: params[:slug])
#blogs = Blog.where(post_category: category.id)
end
That's all. Of course, you can modify show by permitting params, adding joins and doing a single query for fetching blogs, but this can be done later.
Using Rails' resources directive, I have created a set of routes for a controller (contacts). I'm now editing the default views they come with to include some of my own content. However, the link_to method is failing, telling me that I'm missing a required parameter.
No route matches {:action => 'show', :controller => 'contacts', :id => nil} missing required keys [:id]
It's obvious why this is happening - the link_to method is not being supplied with an ID, instead it's getting nil. However, the code I'm using matches the documentation for link_to.
This is the view in question:
<% #contacts.each do |contact| %>
<tr>
<td><%= contact.first %></td>
<td><%= contact.last %></td>
<td><%= contact.title %></td>
<td><%= contact.city %></td>
<td><%= contact.phone %></td>
<td><%= contact.email %></td>
<td><%= link_to 'Show', contact %></td>
<td><%= link_to 'Edit', edit_contact_path(contact) %></td>
<td><%= link_to 'Delete', contact.id, method: :delete, data: { confirm: 'Are you sure?' } %></td>
</tr>
<% end %>
#contacts is a set of contacts returned from the controller. The line that sets that is:
#contacts = Contact.select("title, first, last, city, phone, email")
.where("created_by" => #current_user.id)
The relevant content of the routes.rb file is simply resources :contacts.
The documentation states:
Because it relies on url_for, link_to supports both older-style controller/action/id arguments and newer RESTful routes. Current Rails style favors RESTful routes whenever possible, so base your application on resources and use [...]
link_to "Profile", #profile
This appears to be what I'm using with link_to 'Show', contact.
Why is the ID not getting passed to link_to?
What can I do to remedy this?
Change
Contact.select("title, first, last, city, phone, email")
to
Contact.select("title, first, last, city, phone, email, id")
the contact's id is nil because it isn't in the select query.
Also, although it doesn't seem to be causing problems right now, I would reccomend using an array of symbols instead of a comma-separated string, so that the sql query is more specific. For example:
Contact.select("title, first").to_sql #=> SELECT title, first FROM contacts
Contact.select(:title,:first).to_sql #=> SELECT "contacts"."title", "contacts"."first" FROM contacts
This way if you do a join with another model, it won't complain about the unspecific id in select. If you feel like you're typing too much, you can use the %i(...) syntax:
Contact.select(*%i(title first last city phone email))
Your code seems fine.
Maybe you have an instance in the #contacts array that is not saved and therefore, has no id?
Another way to put the same (again, your code is fine) would be:
= link_to 'Show', contact_path(contact)
I would suggest posting the routes file.
I followed the "Getting Started" tutorial at http://guides.rubyonrails.org/getting_started.html, and wanted to change what is output on the articles index page.
rather than showing the text of the article in the main table, I want to see the most recent comment made on that article.
Here is the code for the index:
<tr>
<td><%= article.title %></td>
<td><%= article.comments.select(:body).last %></td>
<td><%= link_to 'Show', article_path(article) %></td>
<td><%= link_to 'Edit', edit_article_path(article) %></td>
<td><%= link_to 'Destroy', article_path(article),
method: :delete,
data: { confirm: 'Are you sure?' } %></td>
</tr>
Where 'article.comments.select(:body).last' is meant to show the body of the latest comment made on the article in question (this table iterates for every article).
Instead of seeing the text from the comment however, I see this:
{Comment:0x44f9ec8} (with sharp brackets instead of curly - wont let me post the sharp ones.... <>)
I also tried editing comment.create in the comments_controller with:
#article.text = #comment.body
After setting the index table field to 'article.text' (which works fine), but with no effect.
Anyone have any idea what I'm doing wrong??
Any help is much appreciated.
article.comments.select(:body).last does not do what you expect
the select part uses this select which alters the SQL command you use. It forces selecting only the body field from comments and returns a comment object.
so you need to change your code to article.comments.select(:body).last.body
If you need to have all the body fields and just use one, I suggest that you use pluck if you are on rails > 3.2
article.comments.pluck(:body).last
I'm new to ruby and picking it up a little slower than I would like. I'm working with ruby 3.0. For one of my tables in the database I created I want the primary key to show on the "index" page. I'm having difficulty doing this. I manually put the id in the index view, but it keeps on saying "undefined method `venture_round_id'"
This is what my index.html looks like for the table:
<h1>Listing venture_rounds</h1>
<table>
<tr>
<th>id</th>
<th>company</th>
</tr>
<% #venture_rounds.each do |venture_round| %>
<tr>
<td><%= venture_round.venture_round_id %></td>
<td><%= venture_round.company_id %></td>
<td><% link_to 'show', venture_round %></td>
<td><%= link_to 'Edit', edit_venture_round_path(venture_round) %></td>
<td><%= link_to 'Destroy', venture_round, method: :delete, data: { confirm: 'Are you sure?' } %></td>
</tr>
<% end %>
</table>
I entered "venture_round_id" and "id" in manually.
This is what my controller looks like for the index:
def index
#venture_rounds = VentureRound.all
respond_to do |format|
format.html # index.html.erb
format.json { render json: #venture_rounds }
end
end
I've been researching this problem for two days now and haven't been able to find much about it. I imagine the problem has something to do with accessing the key in its own table. Other parts of my database structure that use venture_round_id as a foreign key work just fine. Any pointers or tips would be greatly appreciated!
Try venture_round.id instead of venture_round.venture_round_id
edit from MrDanA:
a foreign key is usually in the format "table_id" but the table's own primary key is usually just "id". If you ever want to look at what your database tables look like, you can open db/schema.rb to look at the schema. You can also fire up a Rails console and if you just type in the name of your class like VentureRound it will show you its attributes, something like VentureRound(id: integer, company_id: integer, etc)
I'm using Couchrest_model as a Rails ORM to CouchDB. I want to have Rails do a "join" of information from two different CouchDB documents for a view, but can't seem to get Rails to auto-retrieve the joined data.
Here's the two related models:
class Package < CouchRest::Model::Base
belongs_to :vendor
property :shortcode, String
property :pins, Integer
end
class Vendor < CouchRest::Model::Base
property :vendor, String
timestamps!
end
So, now in my index.html.erb for /packages I want to display a table with the data from my two models:
<h1>Listing packages</h1>
<table>
<tr>
<th>Shortcode</th>
<th>Pins</th>
<th>Vendor</th>
<th></th>
</tr>
<% #packages.each do |package| %>
<tr>
<td><%= package.shortcode %></td>
<td><%= package.pins %></td>
<td><%= package.vendor %></td>
<td><%= link_to 'Show', package %></td>
<td><%= link_to 'Edit', edit_package_path(package) %></td>
<td><%= link_to 'Destroy', package, confirm: 'Are you sure?', method: :delete %></td>
</tr>
<% end %>
</table>
<br />
<%= link_to 'New Package', new_package_path %>
I want to display the vendor string from the Vendor model. I've used a selector helper in a view to display "joined" information across models with CouchDB, but I can't figure out how to join in this seemingly simpler case of just printing the string in the view table.
Here's the Package controller that corresponds to the index, which is pretty standard:
class PackagesController < ApplicationController
# GET /packages
# GET /packages.json
def index
#packages = Package.all
respond_to do |format|
format.html # index.html.erb
format.json { render json: #packages }
end
end
I've tried doing the standard
#packages = Package.all(:include => :vendor)
but Couchrest_model doesn't pull in the vendor information that way...
I am not sure if I understand your question, but you want to get the vendor string from the instance of Vendor which is attached to your package instance? Just use #package.vendor.vendor
There is no (easy) way to include the vendor record while fetching all packages, so that you only have to make 1 request. You have to fetch the vendor after you fetched all packages because CouchDD does not support document linking or joins. If you have for example 100 packages and want to fetch the vendor string from all attached vendors you end up with a typical n+1 situation (100+1 requests). 1 request to fetch all packages and 100 for each vendor. A better solution is to get all keys of all vendors after the first request and fetch all vendors in a second request using the "keys" parameter while fetching. (Documentation)
I hope i could help you.