I was building a rails app. I want to all post on a page. I am able to show posts title and body but i am not able users name(to whom post belongs -owner of post).
Post-Model
class Post < ApplicationRecord
belongs_to :user
end
User-Model
class User < ApplicationRecord
has_many :posts
end
Posts-Controller
class PostsController < ApplicationController
def index
#posts = Post.all
end
end
Posts-View index.html.erb
<h1> All article </h1>
<% #posts.each do |post| %>
<ul>
<div class="row">
<div class="col-md-offset-3 col-md-5">
<h5><b><%= post.title %></b> by <%= %></h5>
<p><%= post.body %></p>
</div>
</div>
</ul>
<% end %>
Schema looks like
create_table "posts", force: :cascade do |t|
t.string "title"
t.text "body"
t.datetime "created_at", precision: 6, null: false
t.datetime "updated_at", precision: 6, null: false
t.integer "user_id"
end
create_table "users", force: :cascade do |t|
t.string "name"
t.string "email"
t.string "password_digest"
t.datetime "created_at", precision: 6, null: false
t.datetime "updated_at", precision: 6, null: false
end
Display name of user who posted that post
Since you have a relation to the User in the Post as belongs_to :user, So, you can simply use post.user.name to get the name of the user like.
<h1> All article </h1>
<% #posts.each do |post| %>
<ul>
<div class="row">
<div class="col-md-offset-3 col-md-5">
<h5><b><%= post.title %></b> by <%= post.user.name %></h5>
<p><%= post.body %></p>
</div>
</div>
</ul>
<% end %>
bonus
If you want to eager load the user in a single query you might wanna use. Post.includes(:user).all, its better if you always use the user, saves you extra query. Mind that it has some downsides to it as well.
Try post.user to get user object. Then you can print any attribute from the user object.
<p><%= post.user.name %></p>
And use includes method to avoid N + 1 queries problem.
def index
#posts = Post.includes(:user)
end
Reference: https://guides.rubyonrails.org/active_record_querying.html
It's quite easy to access. Try post.user.name and you will get name of associated user.
Read here about all standard methods available for belongs_to association
https://guides.rubyonrails.org/association_basics.html#methods-added-by-belongs-to
Related
I have successfully integrated my application with omniauth and my twitter account. I was able to grab the name, provider, uID, location, avatar and URL for each user that logs in.
But when I try to grab a list of the users followers I am not able to. I have tried using this documentation https://github.com/arunagw/omniauth-twitter#authentication-hash
my User.rb
class User < ApplicationRecord
class << self
def from_omniauth(auth_hash)
user = find_or_create_by(uid: auth_hash['uid'], provider: auth_hash['provider'])
user.name = auth_hash['info']['name']
user.location = auth_hash['info']['location']
user.image_url = auth_hash['info']['image']
user.url = auth_hash['info']['urls']['Twitter']
user.save!
user
end
end
end
I tried adding this to my user.rb unsuccessfully
# user.followers = auth_hash['extra']['raw_info']['followers_count']
in my index.html.erb
<% if current_user %>
<div class="page-header">
<h1 class="">Here is some info about you...</h1>
</div>
<div class="panel panel-default">
<div class="panel-body">
<ul>
<span><strong>Name:</strong> <%= current_user.name %></span><br>
<span><strong>Provider:</strong> <%= current_user.provider %></span>
<li><strong>uID:</strong> <%= current_user.uid %></li>
<li><strong>Location:</strong> <%= current_user.location %></li>
<li><strong>Avatar URL:</strong> <%= image_tag current_user.image_url, alt: current_user.name %></li>
<li><strong>URL:</strong> <%= current_user.url %></li>
**<li><strong>Followers:</strong> <%= current_user.followers_count %></li>**
</ul>
</div>
</div>
<% else %>
<div class="jumbotron">
<h1 class="text-center">Welcome!</h1>
<p>Authenticate via twitter to get started.</p>
</div>
<% end %>
Ive tried first taking the Followers_count as-well just for testing but was unable to.
Any insights on how I should proceed? or what I should add to my users model?
schema.rb
create_table "users", force: :cascade do |t|
t.string "provider", null: false
t.string "uid", null: false
t.string "name"
t.string "location"
t.string "image_url"
t.string "url"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.string "followers_count"
end
end
How to display values from a database on a page for display, I do not try how much I get this error.
undefined method `email' for nil:NilClass
development.erb.html
<% #development.each do |developer| %>
<p><% #developer.email %></p>
<% end %>
welcome_controller.rb
class WelcomeController < ApplicationController
def index
#development = TeamMember.all
end
end
model.rb
class TeamMember < ApplicationRecord
end
db schema.rb
create_table "team_members", force: :cascade do |t|
t.string "email"
t.string "first_name"
t.string "last_name"
t.string "team_text"
t.string "image_url"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
end
It should be <%= developer.email %> instead of <% #developer.email %>
Try to change the file name inside the welcome folder to index.html.erb instead of development.erb.html
You should change your .erb file to:
<% #development.each do |developer| %>
<p><%= developer.email %></p>
<% end %>
When you use <% %> to run ruby code inline, it won't output the result (ideal for .each), however when you want the resulting value (the developer's email) to be output into the HTML, you should use <%= %>.
In addition, the file should be found at /views/welcome/index.erb.html
Hope this helps.
I have two models: project and todo. Project has many todos.
So I wanna create a form, where I select project category from the combobox and then I add a todo to it.
For instance:
I have following categories: family, work, study.
In form in the combobox I select 'study', and then in textfield I spell a todo like 'make homework for monday' and press submit button.
project.rb
class Project < ActiveRecord::Base
has_many :todos
end
todo.rb
class Todo < ActiveRecord::Base
belongs_to :project
end
my data schema:
create_table "projects", force: :cascade do |t|
t.string "title"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
end
create_table "todos", force: :cascade do |t|
t.string "text"
t.boolean "isCompleted"
t.integer "project_id"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
end
_form.html.erb
<%= form_for #project do |f| %>
<div class="form_control">
<%= f.select :title, options_for_select([["Work", "w"],
["Family", "f"],
["Study", "f"],
["TheRest", "t"]]) %>
</div>
<div class="form_control">
*** HERE I NEED TO FIGURE OUT HOW TO ADD SOME DATA TO todo.text ***
</div>
<div class="form_control">
<%= f.submit 'Add' %>
</div>
<% end %>
this is how I show all the projects with their todos:
<% #projects.each do |project| %>
<h2> <%= project.title %> </h2>
<% project.todos.all.each do |todo| %>
<p><%= todo.text %> <%= check_box('tag', todo.__id__, {checked: todo.isCompleted}) %></p>
<% end %>
<% end %>
GitHub link : https://github.com/NanoBreaker/taskmanager
In your todo form, you could have a select box to choose the project the todo belongs to:
# todos/_todo_form.html.erb
<%= select_tag "project_id", options_for_select(Project.pluck(:title, :id)) %>
And in your todos_controller create action:
def create
#project = Project.find(params[:project_id])
#todo = #project.todos.new(todo_params)
if #todo.save
# success
else
# error
end
end
finally, permit the project_id in todo_params:
def todo_params
params.require(:todo).permit(:text, :project_id) # add any other attributes you want
end
How to access customer's name from Customer table onto my Order's action view index. And vice versa.
I am getting this error:
NoMethodError in Customers#index.
Undefined method `order' for #Customer:0x24f4...
class Customer < ActiveRecord::Base
has_many :orders, foreign_key: "customer_id"
end
class Order < ActiveRecord::Base
belongs_to :customer
end
In my migration:
create_table "customers", force: :cascade do |t|
t.string "name"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
end
create_table "orders", force: :cascade do |t|
t.integer "customer_id"
t.datetime "orderdate"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
end
add_index "orders", ["customer_id"], name: "index_orders_on_customer_id", using: :btree
end
In customer's index.html.erb
<% #customers.each do |customer| %>
<%= customer.name %>
<%= customer.order.orderdate %>
<% end %>
In orders's index.html.erb
<% #orders.each do |order| %>
<%= order.orderdate %>
<%= order.customer.name %>
<% end %>
you have has many relation with customer and order so
In customer's index.html.erb
<% #customers.each do |customer| %>
<%= customer.name %>
<!-- this will display customers all order and fetch first and then show that order's orderdate -->
<%= customer.orders.first.orderdate %>
<% end %>
Try a different approach to setting the relationships between your models in the migration:
t.belongs_to :customer, index: true
See http://guides.rubyonrails.org/association_basics.html#the-belongs-to-association
I am trying to use includes in my controller(just learned the concept), however for some reason it is not being accepted by rails in the each loop inside of my index view.
<% #articles.each do |latest|%>
<div class="row homepage_article text-left">
<div class="col-md-3">
<% if latest.photos.present? %>
<%= image_tag latest.photos.first.image.url(:medium),:class => 'img- responsive' %>
<% else %>
<img src="http://placehold.it/400x300" class="img-responsive">
<% end %>
</div>
<div class="col-md-9">
<h2 class="title"><%= latest.title %></h2>
<p class="byline"><%= latest.author %></p>
<p class="summary"><%= latest.content.split(/\s+/)[0..100].join(' ') %></p>
</div>
</div>
<hr>
<% end %>
Controller:
def index
#articles=Article.includes(:content).all.order(created_at: :desc).paginate(:page => params[:page], :per_page => 3)
#carousel_article=Article.all.order(created_at: :desc).limit(3)
##carousel_article=Article.all.order(created_at: :desc).paginate(:page => params[:page], :per_page => 3)
#user=current_user
end
ERROR:
Association named 'content' was not found on Article; perhaps you misspelled it?
Extracted source (around line #39):
<% #articles.each do |latest|%>
<div class="row homepage_article text-left">
<div class="col-md-3">
<% if latest.photos.present? %>
EDITED HERE TO INCLUDES MODELS. AS YOU CAN SEE CONTENT IS A FIELD. THANKS!
create_table "articles", force: true do |t|
t.string "title"
t.text "content"
t.string "category"
t.datetime "created_at"
t.datetime "updated_at"
t.integer "user_id"
end
create_table "users", force: true do |t|
t.string "first_name"
t.string "last_name"
t.string "email"
t.text "bio"
t.string "password"
t.datetime "created_at"
t.datetime "updated_at"
t.string "avatar_file_name"
t.string "avatar_content_type"
t.integer "avatar_file_size"
t.datetime "avatar_updated_at"
end
The ActiveRecord includes method is for associations not attributes. I gather from your code examples that content is a field in your articles table therefore, content is not an association on Article but rather an attribute and is already available when you call Article.all.
Now, if your Article model had an association such as Author:
class Article < ActiveRecord::Base
belongs_to :author # author_id field needs to be present in the articles table
end
Then you can include it: Article.includes(:author).all. This will form SQL queries that will load results from both the articles table and its related authors records. Then in your view you'd be able to add latest.author.name without incurring further queries to the db to get each related author separately.