value of the variable - nil? - ruby-on-rails-3

It looks like the error I'm receiving in my application is caused by the fact that #ad object is somehow becomes nil. The only thing I have in mind at the moment is to see step-by-step what's going on in rails console.
This is the code from the controller:
def edit
#ad=Ad.find(params[:id])
end
So first step I want to check in rails console if the #ad=Ad.find(params[:id]) actually works.
So I type in console
#ad=Ad.find(id=5)
and receive the output
" ←[1m←[36mAd Load (0.0ms)←[0m ←[1mSELECT "ads".* FROM "ads" WHERE "ads"."id" = ? LIMIT 1←[0m [["id", 5]]
=> #<Ad id: 5, name: "Door curtain", description: "Beaded door cu...", price: #<BigDecimal:40be0e8,'0.11E2',4(8)>, selle
r_id: 773, email: "dawn#hotmail....", img_url: "http://www.freewebsit...", created_at: nil, updated_at: nil>"
OK, this step works.
The next step I want to do is to see what happens if #ad is printed on the screen - this way I will be able to see what is exactly is passed to the view.
I type 'print #ad in this is the output that is given:
irb(main):025:0> print #ad
#<Ad:0x40be700>=> nil
irb(main):026:0> puts #ad
#<Ad:0x40be700>
=> nil
Does that really mean that for some reason #ad is passed as nill to the view?
Is there any problem with my logic here? (newbe)

When you run print #ad Rails actually calls print #ad.to_s (to convert the Ad to a string). You need to define your .to_s method in the Ad model
class Ad < ActiveRecord::Base
def to_s
name
end
end
Or if you're just debugging:
print #ad.inspect

#<Ad:0x40be700> means that this an active_record hash.
If you puts #ad.name or puts #ad.inspect in console, you'll see your values

Related

Accessing an attribute on a foreign table by joining two tables in Rails ActiveRecord

I have a model, Message that belongs to the model User and the User model has an attribute name.
Message:
user_id
message_body
1
"hello world"
User:
user_id
name.
1
"johndoe"
The result I want is a complete list of all the messages and the respective user name that created each of those messages.
the api controller endpoint looks something like:
def index
#messages = Message.all
render json: { messages: #messages }
end
The issue is that when I return #messages it only contains the user_id that each message belongs to. What I really want is the user name
I could loop through every message and construct an entirely new object that looks something like:
#object = [
{
name: #messages[0].user.name,
message_body: #messages[0].body
},
{
name: #messages[1].user.name,
message_body: #messages[1].body
},
etc.
]
and then call render json: { messages: #object }
This would probably work fine, but it seems inefficient. Is there a better method for joining these tables for this result?
name
message body
"johndoe"
"hello world"
I was hoping the above example would be enough to get the answer I'm looking for. This is a simplified version of my architecture. In reality it's a bit more complicated:
LeagueChatMessage belongs_to LeagueChat
LeagueChatMessage belongs_to User
LeagueChat belongs_to League
League has_one LeagueChat
so this is really what the controller looks like
def index
#league = League.find_by(id: 1)
render json: { messages: #league.league_chat.league_chat_messages }
end
it works fine. It returns all the league chat messages for the league with the id: 1 but it returns the user_id for each message instead of the user name
Use following logic
#data = Message.includes(:user)
Now you can use like below
#data.each do |msg|
puts "Message #{msg.body}"
puts "User #{msg.user.name}"
end
I used puts for understanding but you can use this object in views as you want. And your approach leads to an n+1 query problem, so I used the includes, which helps remove the n+1 query. Try this and let me know if you have any queries.

With ActionCable, is there a way to count how many subscribers from inside a channel?

For an app I'm building, I have a "lobby" page where people configure which area they'd like to join. Pretty basic.
I'd like to have a running total of active consumers that are currently subscribed to the channel for this page, so that users know whether or not there's other people around to interact with.
Is there an easy way to do this?
I defined a helper method:
app/channels/application_cable/channel.rb
module ApplicationCable
class Channel < ActionCable::Channel::Base
def connections_info
connections_array = []
connection.server.connections.each do |conn|
conn_hash = {}
conn_hash[:current_user] = conn.current_user
conn_hash[:subscriptions_identifiers] = conn.subscriptions.identifiers.map {|k| JSON.parse k}
connections_array << conn_hash
end
connections_array
end
end
end
Now you can call connections_info anywhere inside your derived channel. The method returns an informational array of data about all the available server socket connections, their respective current_users and all their current subscriptions.
Here is an example of my data connections_info returns:
[1] pry(#<ChatChannel>)> connections_info
=> [{:current_user=>"D8pg2frw5db9PyHzE6Aj8LRf",
:subscriptions_identifiers=>
[{"channel"=>"ChatChannel",
"secret_chat_token"=>"f5a6722dfe04fc883b59922bc99aef4b5ac266af"},
{"channel"=>"AppearanceChannel"}]},
{:current_user=>
#<User id: 2, email: "client1#example.com", created_at: "2017-03-27 13:22:14", updated_at: "2017-04-28 11:13:37", provider: "email", uid: "client1#example.com", first_name: "John", active: nil, last_name: nil, middle_name: nil, email_public: nil, phone: nil, experience: nil, qualification: nil, price: nil, university: nil, faculty: nil, dob_issue: nil, work: nil, staff: nil, dob: nil, balance: nil, online: true>,
:subscriptions_identifiers=>
[{"channel"=>"ChatChannel",
"secret_chat_token"=>"f5a6722dfe04fc883b59922bc99aef4b5ac266af"}]}]
You can then parse this structure the way you want and extract the desired data. You can distinguish your own connection in this list by the same current_user (the current_user method is available inside class Channel < ActionCable::Channel::Base).
If a user connects twice (or more times), then corresponding array elements just double.
Yup there is one :
In your app/channel/what_so_ever_you_called_it.rb:
class WhatSoEverYouCalledItChannel < ApplicationCable::Channel
def subscribed
stream_from "your_streamer_thingy"
#subscriber +=1 #<==== like this
end
def unsubscribed
# Any cleanup needed when channel is unsubscribed
#subscriber -=1 #<===== like this
end
def send_message(data)
your_message_mechanic
end
Setup a variable increasing in subscribed
and decreasing in unsubscribed.
You may want store the value in your 'lobby' model , in this case '#subscriber' may be called #lobby.connected_total, i dont know, make this fit your needs.
But this is a way to keep track of number of stream.
Njoy

Rails difference in exception debug output for same object

I have a User model and a List model in my app.
pages_controller.rb
class PagesController < ApplicationController
def home
if user_signed_in?
#lists = current_user.lists
# raise #lists.inspect
#new_list = current_user.lists.build
end
end
end
pages/home.html.erb
<%= raise #lists.inspect %>
Now, my current user has no lists associated with him .
When I uncomment the 3rd line in "Pages#home" raise #lists.inspect I get the output like so : []
But, when I comment that line out, then the exception inside home.html.erb is raised , and its output is like so : [#<List id: nil, name: nil, description: nil, user_id: 1, created_at: nil, updated_at: nil>]
Why is there a difference in output for the same #lists.inspect line ?
EDIT : When I use #lists = current_user.lists.all instead of #lists = current_user.lists then I get an empty array at both places . Why the difference in behavior between the 2 codes ?
Because you build lists in the controller after the first raise:
#new_list = current_user.lists.build
It's the same code, but the data is different, because you did something to it.

rails slice- what am I doing wrong?

I do the following in the console:
1.9.3p194 :062 > #user = [name: "Joe", age: "17"]
=> [{:name=>"Joe", :age=>"17"}]
1.9.3p194 :063 > #user.slice(:name)
TypeError: can't convert Symbol into Integer
Why isn't slice returning [name: "Joe"]?
You're embedding the hash in an array!
Try like this :
#user = {name: "Joe", age: "17"}
#user.slice(:name)
To get an array of only name and id on User.all :
array = User.all.map { |u| u.attributes.slice(:name, :id) }
map executes what you provide in the code block on each element u and builds an array with it, that is returned and put in the variable array in the above example.
u.attributes gives a Hash containing all attributes of the User model for an instance of User ... everything's that's saved in the DB.
Based on the limited information provided, I'm not sure why you would want the overhead of array operations. Consider using OStruct instead.
http://www.ruby-doc.org/stdlib-1.9.3/libdoc/ostruct/rdoc/OpenStruct.html
The example you provided would look like this in OStruct:
require 'ostruct'
#user = OpenStruct.new
#user.name = "John Smith"
#user.age = 17
puts #user.name # -> "Joe"
puts #user.age # -> 17
No slicing and clean, fast-executing Ruby code.

Rails 3 polymorphic_path - how to change the default route_key

I got a config with Cart and CartItem (belongs_to :cart) models.
What I want to do is to call polymorphic_path([#cart, #cart_item]) so that it uses cart_item_path, instead of cart_cart_item_path.
I know I can change the url generated by the route to /carts/:id/items/:id, but that's not what I'm interested in. Also, renaming CartItem to Item is not an option. I just want to use cart_item_path method throughout the app.
Thanks in advance for any tip on that!
Just to make my point clear:
>> app.polymorphic_path([cart, cart_item])
NoMethodError: undefined method `cart_cart_item_path' for #<ActionDispatch::Integration::Session:0x007fb543e19858>
So, to repeat my question, what can I do in order for polymorphic_path([cart,cart.item]) to look for cart_item_path and not cart_cart_item_path?
After going all the way down the call stack, I came up with this:
module Cart
class Cart < ActiveRecord::Base
end
class Item < ActiveRecord::Base
self.table_name = 'cart_items'
end
def self.use_relative_model_naming?
true
end
# use_relative_model_naming? for rails 3.1
def self._railtie
true
end
end
The relevant Rails code is ActiveModel::Naming#model_name and ActiveModel::Name#initialize.
Now I finally get:
>> cart.class
=> Cart::Cart(id: integer, created_at: datetime, updated_at: datetime)
>> cart_item.class
=> Cart::Item(id: integer, created_at: datetime, updated_at: datetime)
>> app.polymorphic_path([cart, cart_item])
=> "/carts/3/items/1"
>> app.send(:build_named_route_call, [cart, cart_item], :singular)
=> "cart_item_url"
I think the same could work for Cart instead of Cart::Cart, with use_relative_model_naming? on the Cart class level.
You can declare the resources like this in your routes file.
resources :carts do
resources :cart_items, :as => 'items'
end
Refer to this section of the rails guide