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.
Related
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
I have an rspec controller with the test:
it "assigns all rate_card_details as #rate_card_details" do
rate_card_detail = FactoryGirl.create(:rate_card_detail)
get :index, {}, valid_session
assigns(:rate_card_details).should eq([rate_card_detail])
end
For most models, this works fine. However, in this case, the rate field is a decimal. This causes the rspec comparison to (for some reason) compare 1 instance of BigDecimal with another, including its location in memory. Here is the error:
Failure/Error: assigns(:rate_card_details).should eq([rate_card_detail])
expected: [#<RateCardDetail rate_card_id: 1, item_id: 1, rate: #<BigDecimal:7f82dcdb0ae0,'0.6941E2',18(18)>, created_at: "2013-06-05 18:12:53", updated_at: "2013-06-05 18:12:53">]
got: [#<RateCardDetail rate_card_id: 1, item_id: 1, rate: #<BigDecimal:7f82dc9a74d0,'0.6941E2',18(18)>, created_at: "2013-06-05 18:12:53", updated_at: "2013-06-05 18:12:53">]
The 2 BigDecimals have the same value, but are different objects. Is there a way to get rspec to treat these as equal when doing a comparison?
it's not pretty but this works with me
it "assigns all rate_card_details as #rate_card_details" do
rate_card_detail = FactoryGirl.create(:rate_card_detail)
get :index, {}, valid_session
assigns(:rate_card_details).first.attributes.values.each_with_index do |rcd,i|
r_c_d = rate_card_detail[i]
if rcd.is_a?BigDecimal
rcd = rcd.to_s
r_c_d = r_c_d.to_s
end
expect(rcd).to eq(r_c_d)
end
end
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.
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
I want to retrieve the maxmimum lenght validation of a ActiveRecord field in one of my views.
The following works fine in rails console and returns the correct value :
irb(main):046:0> micropost = Micropost.new
=> #<Micropost id: nil, content: nil, user_id: nil, created_at: nil, updated_at: nil>
irb(main):047:0> micropost._validators[:content][1].options[:maximum].to_s
=> "140"
However, when I use the same code in my controller it returns nil :
class PagesController < ApplicationController
def home
#title = "Home"
if signed_in?
#micropost = Micropost.new
#feed_items = current_user.feed.paginate(:page => params[:page])
#content_max = #micropost._validators[:content][1].options[:maximum].to_s
end
end
...
end
I also tried to include a method in my ApplicationHelper, which also returns nil ;-(
def content_max
Micropost._validators[:content][1].options[:maximum].to_s
end
What am I doing wrong?
The _validators array might not be in the same order whether you're in the console or in a web request.
Micropost._validators[:content].find {|v| v.class == ActiveModel::Validations::LengthValidator} .options[:maximum].to_s
should do what you want.
IMHO, a better solution would be to store the length in a constant (I somehow doubt the _validators array is part of the official API) :
class Micropost < ActiveRecord::Base
MAX_CONTENT_LENGTH = 140
validates :content, :length => {:maximum => MAX_CONTENT_LENGTH}
# Rest of the code...
end
and get the length with :
Micropost::MAX_CONTENT_LENGTH