I have a Rails app, with 2 models : a User model and a Micropost model, from the RoR tutorial.
I implemented the whole Twitter app, to get started with a Rails.
Now I wanted to use the code I have to create a ride share application : people posting rides that they are going to make (when they drive), apply to a ride when they want to be a passenger, following users to get their rides on their feed (instead of just posts) and being followed by other users. We see that a “user” actually plays 2 roles : driver and passenger. I’m good with the driver : it’s just the author of the post, no change to make.
But not passenger…
What I want : have a “Hop in” button on each ride post — user clicks, the button turns to “Jump off” and we have a record that gets created in the db, in the PassengerRide table (ride_id, passenger_id) // when we click on “Jump off” the button turns to “Hop in” and the record that had been saved gets deleted from the PassengerRide table.
What I did : I tried to mimic the implementation of the following and adapt to what I want
1) generated the PassengerRide table (many to many relation between a User and a Micropost)
with
rails generate model PassengerRide ride_id:integer passenger_id:integer
2) in passenger_ride.rb :
attr_accessible :ride_id
EDIT: I removed this hoping it’d fix the problem and it didn’t solve the problem.
3)established the associations! (remember: I only have a User table and a Micropost table)
in user.rb
has_many :passenger_rides, foreign_key: "passenger_id", dependent: :destroy
has_many :rides, through: :passenger_rides, class_name: "Micropost"
in passenger_ride.rb
belongs_to :passenger, class_name: "User"
belongs_to :ride, class_name: "Micropost"
in micropost.rb
has_many :passenger_rides, foreign_key: "ride_id", dependent: :destroy
has_many :passengers, through: :passenger_rides, source: :passenger, class_name: "User"
4) methods in the user model to create the passenger_ride records
def hopped_in?(ride)
self.passenger_rides.find_by_ride_id(ride.id)
end
def hop_in!(ride)
self.passenger_rides.create!(ride_id: ride.id)
end
def jump_off!(ride)
self.passenger_rides.find_by_ride_id(ride.id).destroy
end
5) add rides to the user controller
in routes.rb
resource :users do
member do
get :rides
end
end
6) views :
in app/views/microposts/_hopin.html.erb
<%= form_for(current_user.rides.build(ride_id: @micropost.id)) do |f| %>
<div><%= f.hidden_field :ride_id %></div>
<%= f.submit "Hop in", :class => "btn btn-large btn-primary" %>
<% end %>
in app/views/microposts/_jumpoff.html.erb
<%= form_for(current_user.rides.find_by_ride_id(@micropost),
html: { method: :delete }) do |f| %>
<%= f.submit "Jump off", :class => "btn btn-large" %>
<% end %>
in app/views/microposts/_ride_form.html.erb
<div id="ride_form">
<% if current_user.hopped_in?(@micropost) %>
<%= render 'microposts/jumpoff' %>
<% else %>
<%= render 'microposts/hopin' %>
<% end %>
</div>
The local server rendered the following :
Started GET "/" for 127.0.0.1 at 2012-03-30 21:39:06 -0400
Processing by PagesController#home as HTML
←[1m←[36mUser Load (0.0ms)←[0m ←[1mSELECT "users".* FROM "users" WHERE "users
"."remember_token" = 'R8o1mYu49bhrsrIyIPO-ow' LIMIT 1←[0m
←[1m←[35m (0.0ms)←[0m SELECT DISTINCT "users".id FROM "users" INNER JOIN "rel
ationships" ON "users"."id" = "relationships"."followed_id" WHERE "relationships
"."follower_id" = 3
←[1m←[36m (1.0ms)←[0m ←[1mSELECT COUNT(*) FROM "microposts" WHERE "microposts
"."user_id" = 3←[0m
Rendered shared/_user_info.html.erb (4.0ms)
←[1m←[35m (0.0ms)←[0m SELECT COUNT(*) FROM "users" INNER JOIN "relationships"
ON "users"."id" = "relationships"."followed_id" WHERE "relationships"."follower
_id" = 3
←[1m←[36m (0.0ms)←[0m ←[1mSELECT COUNT(*) FROM "users" INNER JOIN "relationsh
ips" ON "users"."id" = "relationships"."follower_id" WHERE "relationships"."foll
owed_id" = 3←[0m
←[1m←[35m (0.0ms)←[0m SELECT COUNT(*) FROM "microposts" INNER JOIN "passenger
_rides" ON "microposts"."id" = "passenger_rides"."ride_id" WHERE "passenger_ride
s"."passenger_id" = 3
Rendered shared/_stats.html.erb (15.0ms)
←[1m←[36m (0.0ms)←[0m ←[1mSELECT COUNT(*) FROM "microposts" WHERE (user_id IN
(1) OR user_id = 3)←[0m
←[1m←[35mMicropost Load (0.0ms)←[0m SELECT "microposts".* FROM "microposts" W
HERE (user_id IN (1) OR user_id = 3) ORDER BY microposts.created_at DESC LIMIT 3
0 OFFSET 0
←[1m←[36mUser Load (0.0ms)←[0m ←[1mSELECT "users".* FROM "users" WHERE "users
"."id" = 3 LIMIT 1←[0m
←[1m←[35mPassengerRide Load (0.0ms)←[0m SELECT "passenger_rides".* FROM "pass
enger_rides" WHERE "passenger_rides"."passenger_id" = 3 AND "passenger_rides"."r
ide_id" IS NULL LIMIT 1
WARNING: Can't mass-assign protected attributes: ride_id
Rendered microposts/_hopin.html.erb (4.0ms)
Rendered microposts/_ride_form.html.erb (9.0ms)
Rendered shared/_feed_item.html.erb (15.0ms)
Rendered shared/_feed.html.erb (20.0ms)
Rendered pages/home.html.erb within layouts/application (46.0ms)
Completed 500 Internal Server Error in 155ms
ActionView::Template::Error (undefined method `ride_id' for #<Micropost:0x5f53a1
0>):
1: <%= form_for(current_user.rides.build(ride_id: @micropost.id)) do |f| %>
2: <div><%= f.hidden_field :ride_id %></div>
3: <%= f.submit "Hop in", :class => "btn btn-large btn-primary" %>
4: <% end %>
app/views/microposts/_hopin.html.erb:2:in `block in _app_views_microposts__hop
in_html_erb___661389729_52209444'
app/views/microposts/_hopin.html.erb:1:in `_app_views_microposts__hopin_html_e
rb___661389729_52209444'
app/views/microposts/_ride_form.html.erb:6:in `_app_views_microposts__ride_for
m_html_erb___54007412_52167144'
app/views/shared/_feed_item.html.erb:12:in `_app_views_shared__feed_item_html_
erb___851424678_48417588'
app/views/shared/_feed.html.erb:3:in `_app_views_shared__feed_html_erb___10631
41135_48687708'
app/views/pages/home.html.erb:19:in `_app_views_pages_home_html_erb__74940785_
48176280'
Thank you so much for taking time to read that, I couldn’t be more thorough !
Shouldn’t it be
passenger_ridesinstead ofridesin the_hopin.html.erbpartial? I.e.: