I am trying to have a many to many relationship between players and fixtures. So when a player has played in a fixture I can see what fixtures the players have played in and who has played in the fixtures.
I am trying to then track if the player has paid for the game using a "sub_paid" column with boolean. I am having a hard time setting this to true or false. I can create a player/fixture record but not have a sub_paid attribute.
Models
class Fixture < ActiveRecord::Base
has_many :player_fixtures
has_many :players, :through => :player_fixtures
class Player < ActiveRecord::Base
has_many :player_fixtures
has_many :fixtures, :through => :player_fixtures
class PlayerFixture < ActiveRecord::Base
belongs_to :player
belongs_to :fixture
Migrations
class CreatePlayerFixtures < ActiveRecord::Migration
def change
create_table :player_fixtures do |t|
t.integer "player_id"
t.integer "fixture_id"
t.boolean "sub_paid"
t.timestamps
end
Controller
Not sure what to put here as I have none specificity one for player_fixture
View
I have this at the moment.
<%=form_for(#fixtures, :url => {:action =>'create'}) do |f| %>
questions
Could someone point me in the right direction!
My big questions that I am really stuck on at the moment.
Saving this to the database with sub_paid = false when form is first submitted then being able to change this at a later date to true.
Being able to sort all players by sub_paid = false on a fixture view. EG on my player list sort them so it only shows false.
I have another question here that is still un answered about forms and checkboxes. HABTM Form not submitting more than one value in rails
I understand this is alot but this is for a project I am doing and have been looking at a screen trying everything for 3 weeks now. I need to get this done.
Try adding the following to your form:
<%= check_box_tag :sub_paid %>
<%= select_tag :player_id, options_for_select(Player.all.map{|p| [p.name, p.id] %>
Note that these are ordinary check_box_tag and select_tag and not f.check_box or f.select. We don't want these parameters to be in your :fixture parameter. Now the create action in your FixtureController should look something like this:
def create
#fixture = Fixture.new(params[:fixture])
if #fixture.save
#player = Player.find(params[:player_id])
#fixture.player_fixtures << PlayerFixture.new(:sub_paid => params[:sub_paid], :player => #player)
# other stuff, redirect, etc.
else
# error handling, render, etc.
end
end
You should probably do some checks to make sure the PlayerFixture saving part goes well, but you get the idea. Hope that helps or at least gives you some ideas.
Related
I want the users to be able to write down their skills as hashtags in a text_field. I already can store a string and split it up like (btw: a user has one account)
<% #user.account.hashtag.split('#').reject { |c| c.empty? }.each do |d| %>
<p><%= d %></p>
<% end %>
But that is not elegant as it's processed in the view right now and since its just one string which is displayed as an array, I cant iterate. What I want to achieve is explained in this video.
A user should write down his skills in one field, the string should be split up at every '#' symbol and stored in a field which should belong to the user, so I can do something like url.com/user/hashtag/xyz while xyz is the hashtag.
The video tutorial is made well, but it does not work for rails 5+ since find_by is not available anymore; also I don't want to create some new tables, because later I want to do the same with other models than account. Later I want to add a autocomplete function in a search field via gems like select2. That is why it might help to add another table for the tags? :S
thanks in advance!
so there are lots of things in this short question.
The first thing that I would do would be to create a hashtag table
class CreateHashtags < ActiveRecord::Migration[5.0]
def change
create_table :hashtags do |t|
t.string :hashtag
t.references :hashtagsable, polymorphic: true
t.timestamps null: false
end
end
end
This line is critical
t.references :hashtagsable, polymorphic: true
This will create 2 new field
:hashtagsable_type => :string, # This reference the model of the assiciation
:hashtagsable_id => :integer, # This reference the id of the assiciation
This new model should look like
# app/models/hashtag.rb
class Hashtag < ApplicationRecord
belongs_to :hashtagsable, polymorphic: true
end
Now your user model you should add this line
class User < ApplicationRecord
has_many :hashtags, as: :hashtagsable # User.last.hashtags
end
class Account < ApplicationRecord
has_many :hashtags, as: :hashtagsable # Account.last.hashtags
end
in your view should look like
<% #user.account.hashtags.each do |hashtag| %>
<p><%= hashtags.hashtag %> </p>
<% end %>
I hope that this helps and set you in the right path
I have generated two models tour and tourcategories in my application. Now I want to associate these two models using has_many and belongs_to. Where tour can relate with single tourcategory but tourcategory can have more than one tours. So definition of the tour model is following:
class Tour < ActiveRecord::Base
belongs_to :tourcategory
attr_accessible :content, :element_id, :job_id, :title, :priority, :tourcategory
end
this is the definition of tourcategory model:
class Tourcategory < ActiveRecord::Base
has_many :tours
attr_accessible :title
end
this is the definition of the tours migration file:
class CreateTours < ActiveRecord::Migration
def change
create_table :tours do |t|
t.string :element_id
t.string :title
t.text :content
t.integer :job_id
t.integer :priority
t.belongs_to :tourcategory, index:true
t.timestamps
end
end
end
this is the definition of the tours controller :
def new
#tourcategories = Tourcategory.all
#tour = Tour.new
#tour.build_tour
respond_to do |format|
format.html
format.json { render json: #tour }
end
end
Now I am getting an error
undefined method `tourcategories'
When I access the _form.html.haml view for editing and for adding new tour.
this the code where error is encountered.
.field
= label_tag "tour Categories"
%br/
= select_tag "tourcategory", options_from_collection_for_select(Tourcategory.all, 'id', 'title', #tour.tourcategories.map{ |j| j.id })
= f.submit
You defined,
Tourcategory has multiple tours. has_many :tours
Tour belongs to one Tourcategory. belongs_to :tourcategory
So, you can not call tourcategories from #tour. you can call tourcategory from #tour
Additionaly,
#tour.build_tour <- makes error maybe.
you can use build_* method for belongs_to relation.
I think you should try #tour.build_tourcategory
Read "Action Record Association" section in Rails Guide: http://guides.rubyonrails.org/association_basics.html
You can't call #tour.tourcategories, because a Tour belongs to a single Tourcategory, so that method wouldn't be generated by Rails. You may call #tour.tourcategory or #tourcategory.tours.
Why are you passing a fourth argument to options_for_collection_from_select anyway? That map method will return a collection, but you want an element. Try omitting it and see if it works.
A couple more issues with your code:
#tour.build_tour won't work unless you have explicitly defined that method (and if you have, it might be better to name it something else). All build_something methods are generated for has_one relationships. Maybe you're looking for #tourcategory.tours.build.
You shouldn't call Tourcategory.all from your view, instead use the #tourcategories variable you defined in the controller. Views should never call models directly.
If you're using Rails 4, you shouldn't be using attr_accessible, but rather define strong parameters in the controller.
Hope that helps.
You actually need to use HABTM (Has And Belongs To Many) - please check out Rails documentation for more details
So, I have read through quite a few rails active records pages, stack O questions and answers (about 12 hours of time) trying to figure out how the heck to tie all of these things together into a single query to display them on my page.
Here is my page view
Secrets with owner info
</h3>
<% #secretInfo.each do |i| %>
<p><%= i.content %> - <%= i.first_name %></p>
<p><%= i.created_at %></p>
--> "this is where I'd like to have likes for post" <--
<% end %>
and here is my controller
def show
#user = User.find(params[:id])
#secrets = Gossip.all
#mySecrets = Gossip.where(user_id: [params[:id]])
#secretInfo = Gossip.joins(:user).select("content", "first_name", "created_at")
#secretWLikesNInfo = WTF MATE?
end
Also, may help to see my models and schema so here are those
class User < ActiveRecord::Base
attr_accessor :password
has_many :gossips
has_many :likes
has_many :liked_secrets, :through => :gossips, :source => :gossip
class Like < ActiveRecord::Base
belongs_to :user
belongs_to :gossip
class Gossip < ActiveRecord::Base
belongs_to :user
has_many :likes
has_many :liking_users, :through => :likes, :source => :user
I don't know why this seems so impossible or it could be something very simple that I am just overlooking. This all was very easy in PHP/MySQL. All help is appreciated.
Additional points for coming up with a query that allows me to see all posts that I as a user has created AND liked!
Well, what you want to do is eager loading: load data associated with a record in a single roundtrip to the database. For example, i think you can load all your data like this:
#user = User.where(id: params[:id])
.joins(:liked_secrets)
.includes(:liked_secrets => :likes)
.first!
#secretInfo = #user.liked_secrets.map do |secret|
OpenStruct.new(
content: secret.content,
first_name: user.first_name,
created_at: secret.created_at,
likes: secret.likes
)
end
This works by including in the data fetched from the database in the first query all the data associated included in the include parameter. So, calling #user.liked_secrets will return the secrets but won't call the database because that information already came from the database in the first query. The same happens if you do #user.liked_secrets.first.likes because of the :linked_secrets => :likes parameter on the initial query.
I'll let a link to a good blog post about this here:
http://blog.arkency.com/2013/12/rails4-preloading/.
And, if you feel the Rails ORM (ActiveRecord) doesn't really works for your use case, you can just use sql in a string or fallback to use another Ruby ORM out there (like Sequel).
My models are setup as follows:
class Contract <ActiveRecord::Base
has_many :contract_upgrades
has_many :upgrades, through: :contract_upgrades
end
My Upgrade model
class Upgrade < ActiveRecord::Base
has_many :contract_upgrades
has_many :contracts, through: :contract_upgrades
end
my ContractUpgrade model
# schema
t.integer :contract_id
t.integer :upgrade_id
t.integer :qty
class ContractUpgrade < ActiveRecord::Base
belongs_to :contract
belongs_to :upgrade
end
My contract form looks like this...
- #upgrades.available.each do |upgrade|
%tr{class: "#{upgrade.id}", id: 'upgrade-checkboxes'}
%td
.upgrade-checkboxes
= check_box_tag "contract[upgrade_ids][]", upgrade.id, #contract.upgrades.include?(upgrade), { upgrade_id: upgrade.id }
= label_tag "contract_upgrade_#{upgrade.id}", upgrade.name
%td
= number_to_currency("#{upgrade.price}")
- if upgrade.allow_each
here is where it gets a little tricky...
%td
%input{type: 'text', placeholder: 'Qty'} # displays text_field box
= number_field_tag # displays text_field box
When the upgrade check_box is checked the upgrade.id and contract.id save as it should and works perfectly. I need to be able to input a quantity on those upgrades that can have multiple. In my Contracts controller the upgrade_ids are whitelisted via {upgrade_ids: []}, and no matter what I've done whenever anything is in the qty field I get an unpermitted_parameter :qty...
UPDATE
I'd be able to figure out what/how to do what I essentially need to do if someone can get Rails Guides Associations: has_many_through example to work. In this example directly from the rails guides the join table has an appointment_date attribute.
There's probably a simple answer to this, but I'm lost.
I created my first Polymorphic Association today to create an activity field.
Here's the activity.rb:
class Activity < ActiveRecord::Base
belongs_to :trackable, :polymorphic => true
end
In the database for activities, I have the columns:
id
name
trackable_id
trackable_type
created_at
updated_at
Here's the note.rb:
class Note < ActiveRecord::Base
has_many :activities, :as => :trackable
after_create :create_an_activity
def create_an_activity
self.activities.build(:name => candidate_id)
end
end
In my index.html.erb view I have:
<% #activities.each do |activity| %>
<p>activity.name</p>
<% end >
My question is:
Currently, activity.name in the view is outputting the id because I have :name => candidate_id. A note is created for a candidate. But, what I really want it to output is candidate.full_name (which is in the candidates table). However, this doesn't work because full_name is not in the notes table. It's in the candidates table. Is there any way to access that? Candidates has_many notes and a note belongs_to a candidate.
enjoyed your skill share with Vin a couple months ago!
I believe what you're looking for can be accessed by going through the parent association, by calling self -> parent -> attribute:
def create_an_activity
self.activities.create(:name => self.candidate.full_name)
end
Also correct me if i'm wrong, but unless you are calling a save later on, it seems like self.activities.create is what you are looking for instead of .build