This question already has an answer here:
Can not call my associate table in my view
(1 answer)
Closed 8 years ago.
Can any kind person look at this and see what is wrong with the code. I really must not withdraw my fields in the associative table! what is my problem?
view:
<% #playersname.each do |p|%>
<ul>
<li><%= p.name %></li>
<li><%= p.result.inspect %></li>
</ul>
controller:
class ResultsController < ApplicationController
def index
#playersname = Player.all
end
end
model:
class Player < ActiveRecord::Base
attr_accessible :name
belongs_to :result
end
class Result < ActiveRecord::Base
# attr_accessible :title, :body
has_many :player
end
migrations:
class CreatePlayers < ActiveRecord::Migration
def change
create_table :players do |t|
t.string "name"
t.references :results
t.timestamps
end
end
end
class CreateResults < ActiveRecord::Migration
def change
create_table :results do |t|
t.string "result", :limit => 40
t.string "cal", :limit => 40
t.string "sum",:limit => 300
t.timestamps
end
end
end
You will need to pluralize player, here in your code:
has_many :player
should be
has_many :players
Also, in your view you should change:
<li><%= p.result.inspect %></li>
to something else. It won't work because a) there is no "result" method for p there is only a results method for it. And when you call .inspect on results you will get something you probably don't want to send to the browser.
Once you get the association figured out, you probably want something like the following in your view:
<h1>Results</h1>
<%= render :partial => "result", :collection => #results %>
and then you will create a partial in your views folder named _result.rb and containing code like this
<h3>Result: <%= result.title %></h3>
<p><%= result.body %></p>
Related
I am new to Rails and working on a blog project.
I have articles and categories. Each article can have multiple categories and each category can belong to multiple articles.
I also have a join table articles_categories
My migrations:
class CreateArticles < ActiveRecord::Migration[5.2]
def change
create_table :articles do |t|
t.string :title
t.text :body
t.timestamps
end
end
end
class CreateCategories < ActiveRecord::Migration[5.2]
def change
create_table :categories do |t|
t.string :name
t.timestamps
end
end
end
class CreateArticlesCategoriesJoinTable < ActiveRecord::Migration[5.2]
def change
create_join_table :articles, :categories do |t|
t.index :article_id
t.index :category_id
end
end
end
My model associations:
class Article < ApplicationRecord
has_and_belongs_to_many :categories
end
class Category < ApplicationRecord
has_and_belongs_to_many :articles
end
This all makes sense so far.
What I am struggling with now, is how do I add categories when creating a new Article? I want to be able to select pre-defined categories from a list (stored in Category table) through a form.
What model and/or URL (if any) do I use in the form_with helper?
Is the following anywhere close?
<% form_with model: ???, url: ??? do |f| %>
<%= f.collection_select :category_id, Category.order(:name), :id, :name %>
<% end %>
UPDATE: Problem solved, thanks to Sebastian and Gabriel for the helpful pointers.
The relevant changes to my code are as follows:
app/controllers/pomodoro_cycles_controller.rb
def pomodoro_collections
{
pomodoro_collection_0: Pomodoro.offset(0).first(100),
pomodoro_collection_1: Pomodoro.offset(100).first(100)
}
end
app/views/pomodoro_cycles/show.html.erb
<% #pomodoros_collections.each do |pomodoros_collection_hash| %>
<h2><%= pomodoros_collection_hash[0] %></h2>
<% pomodoros_collection_hash[1].each do |pomodoro| %>
<p>
<%= pomodoro.id %>
<%= pomodoro.color %>
</p>
<% end %>
<% end %>
NOTA BENE:
The #first method in ActiveRecord returns an Array, so the keys in my original Hash were nested Arrays. Instead, the following was sufficient to return an Array of Pomodoro objects:
Pomodoro.offset(0).first(100)
DESCRIPTION OF ORIGINAL PROBLEM
Rails 5, PostgreSQL
PROBLEM: I cannot access Pomodoro.all from within PomodoroCycleController
I have two scaffolds: Pomodoro and PomodoroCycle, and I want to access the full list of Pomodoros within the PomdoroCycle controller.
The following code is kept simple, in order to make as clear as possible what I'm trying to do. If I can do these things, then I'll be able to do much more, but one step at a time.
Regarding the db migration files, I have already run bundle exec rails db:migrate
I want to display a full list of Pomodoros in the PomodoroCycle Show View (later to be displayed in Index), but I don't know what is missing.
From app/controllers/pomodoro_cycles_controller.rb
def show
#pomodoros_collections = pomodoro_collections
end
def pomodoro_collections
{
pomodoro_collection_0 => [Pomodoro.offset(0).first(100)],
pomodoro_collection_1 => [Pomodoro.offset(100).first(100)]
}
end
From app/views/pomodoro_cycles/show.html.erb
<% #pomodoros_collections.each do |collection| %>
<p><%= collection %></p>
<% end %>
However, this displays nothing in the browser.
app/models/pomodoro_cycle.rb
class PomodoroCycle < ApplicationRecord
has_many :pomodoros
end
app/models/pomodoro.rb
class Pomodoro < ApplicationRecord
belongs_to :pomodoro_cycle
end
Updated db/migrate/20180103032759_create_pomodoro_cycles.rb:
class CreatePomodoroCycles < ActiveRecord::Migration[5.1]
def change
create_table :pomodoro_cycles do |t|
t.string :activity
t.integer :iteration
t.integer :matrix_side_length
t.datetime :created_at
t.datetime :completed_at
t.string :category_labels, array:true, default: []
t.string :category_colors, array:true, default: []
t.string :username
t.timestamps
end
create table :pomodoros do |t|
t.belongs_to :pomodoro_cycle, index: true
t.datetime :completed_at
t.timestamps
end
add_index :pomodoros, :pomodoro_cycle_id
end
end
Untouched db/migrate/20180103054425_create_pomodoros.rb
class CreatePomodoros < ActiveRecord::Migration[5.1]
def change
create_table :pomodoros do |t|
t.boolean :status
t.string :category
t.string :color
t.datetime :completed_at
t.string :username
t.timestamps
end
end
end
First of all, as #SebastianPalma pointed out in the comments, the syntax is wrong
def pomodoro_collections
{
pomodoro_collection_0 => [Pomodoro.offset(0).first(100)],
pomodoro_collection_1 => [Pomodoro.offset(100).first(100)]
}
end
should be:
def pomodoro_collections
{
pomodoro_collection_0: [Pomodoro.offset(0).first(100)],
pomodoro_collection_1: [Pomodoro.offset(100).first(100)]
}
end
Make the keys in the hash symbols
Then to display each Pomodoro put something like:
<% #pomodoros_collections.each do |pomodoros_collection_hash| %>
<h2><%= pomodoros_collection_hash[0] %></h2>
<% pomodoros_collection_hash[1].each do |pomodoro| %>
<p><%= pomodoro.id %></p> #Or the attribute you want to display
<% end %>
<% end %>
Hope this help
I want to create a Rails app that allows "users" to follow other users. I am semi-new to more complex relationships and am attempting to set up has_many through for the first time. I want friends to be able to follow other users.
Here is my join table:
class Following < ApplicationRecord
belongs_to :user
belongs_to :follower, class_name: "User"
end
Here is my users table:
class User < ApplicationRecord
has_many :followings
has_many :followers, through: :followings
end
Here is my schema:
create_table "followings", force: :cascade do |t|
t.integer "user_id"
t.integer "follower_id"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
end
create_table "users", force: :cascade do |t|
t.string "name"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
end
I don't know how to set up a form to actually create the relationship. In a users view, I have this, but it doesn't work.
<%= form_for #following do |f| %>
<%= f.hidden_field :follower_id, :value => #user %>
<%= f.select :user_id, #users.collect { |u| [u.name, u.id] } %>
<%= f.submit %>
<% end %>
As I said, I am very new to this type of relationship. I need help. I don't know how to link records through a form.
I am following this tutorial: https://teamtreehouse.com/library/what-is-a-hasmany-through-association-in-ruby-on-rails
I am assuming you have a current_user method that returns the logged in user - like what Devise provides. If not you need to setup authentication first.
Create a nested route:
# config/routes.rb
resources :users, only: [] do
resources :followings, only: [:create, :destroy], shallow: true
end
Add a validation to Following to avoid duplicates:
class Following < ApplicationRecord
belongs_to :user
belongs_to :follower, class_name: "User"
validates_uniqueness_of :user_id, scope: 'follower_id'
end
Add a utility method to User to see if he is following another user:
class User < ApplicationRecord
has_many :followings
has_many :followers, through: :followings
def following?(user)
followings.exist?(user: user)
end
def find_following(user)
followings.find_by(user: user)
end
end
We can then add Follow and Unfollow buttons (they are actually forms) to the /users/show.html.erb view.
<% if current_user.following?(#user) %>
<%= button_to "Unfollow", current_user.find_following(#user), method: :delete %>
<% else %>
<%= button_to "Follow", [#user, #user.followings.new] %>
<% end %>
Note that we don't need any form params since we are using a nested route (POST /users/:user_id/followings) to pass the user id (who gets followed) and we are getting the current user from the session.
We can then setup our controller:
class FollowingsController < ApplicationController
# POST /users/:user_id/followings
def create
#user = User.find(params[:user_id])
#following = Following.new(user: #user, follower: current_user)
if #following.save
redirect_to #user, success: "You are now following #{ #user.name }"
else
redirect_to #user, error: "Could not create following"
end
end
# DELETE /followings/:id
def destroy
#following = Following.find(params[:id])
#following.destroy
redirect_to #following.user, success: "You are no longer following #{ #user.name }"
end
end
I'm very new to ruby on rails. Thanks for your patience in advance.
<div class="field">
<%= #pin.image_url if #pin.image? %>
<%= f.file_field :image %>
<%= f.hidden_field :image_cache %>
</div>
What does #pin.image? do?
There is not image? method in my controller. I'm guessing it's one of the helper functions provided by rails for every controller? Is that right?
What is f ?
here is my model for pin
class Pin < ActiveRecord::Base
extend FriendlyId
friendly_id :name, use: :slugged
belongs_to :board
end
and its schema
class CreatePins < ActiveRecord::Migration
def change
create_table :pins do |t|
t.string :name
t.string :image
t.integer :board_id
t.timestamps null: false
end
end
end
class AddImageToPins < ActiveRecord::Migration
def change
add_column :pins, :image, :string
end
end
There is not image? method in my controller.
You don't call this method on your controller, but on your object assigned to #pin variable, which is probably your Pin model. And your model does have image? method.
What is f ?
It's the form builder object, passed into form_for block.
I need (or I think) implement polymorphic association in my model but I have something wrong. Let see my situation, it's a simple question/answers system, and the logic is the following:
- a question can be ansewered by N answers.
- An answer can be only a "text" XOR (one or other, not both) a "picture".
Migrations:
class CreateAnswers < ActiveRecord::Migration
def change
create_table :answers do |t|
t.integer :question_id
t.references :answerable, :polymorphic => true
t.timestamps
end
end
end
class CreateAnswerTexts < ActiveRecord::Migration
def change
create_table :answer_texts do |t|
t.text :content
t.timestamps
end
end
end
class CreateAnswerPictures < ActiveRecord::Migration
def change
create_table :answer_pictures do |t|
t.string :content
t.timestamps
end
end
end
Models
*answer.rb*
class Answer < ActiveRecord::Base
belongs_to :user_id
belongs_to :question_id
belongs_to :answerable, :polymorphic => true
attr_accessible :answerable_type
end
answer_text.rb
class AnswerText < ActiveRecord::Base
TYPE = "text"
has_one :answer, :as => :answerable
attr_accessible :content
end
answer_picture.rb
class AnswerPicture < ActiveRecord::Base
TYPE = "picture"
has_one :answer, :as => :answerable
attr_accessible :content
end
Controller
answers_controller.rb:
...
def create
post = params[:answer]
create_answerable(post[:answerable_type], post[:answerable])
#answer = #answerable.answer.new()
end
private
def create_answerable(type, content)
#answerable = ('Answer' + type.capitalize).classify.constantize.new(:content => content)
#answerable.save
end
...
And view form (Only have these fields):
...
<div class="field">
<%= f.label :answerable_type %><br />
<%= select("answer", "answerable_type", Answer::Types, {:include_blank => true}) %>
</div>
<div class="field">
<%= f.label :answerable %><br />
<%= f.text_field :answerable %>
</div>
...
So, the problem is when I submit form I get this error:
undefined method new' for nil:NilClass
app/controllers/answers_controller.rb:52:increate'
Answers? :)
on a has_one relationship, you have to use :
#answerable.build_answer
or
#answerable.create_answer
instead of
#answerable.answer.new
see the reference for more info.