Context:
Category has many Products and dependent destroy is set in Category model for products.
First Case:
c = Category.last
c.destroy
c => record persists as expected because it is already loaded in c variable
Second Case:
p = Category.last.products
Category.last.destory
p => records persisted as expected in p variable as already loaded in this.
Third Case:
c = Category.last
p = c.products
c.destroy
p => [] .. Why??
c => record persisted as expected in c variable
In third case, Why i am getting blank array for p variable ?
Refer SS.doubt_file
Related
I have performed the following test:
irb(main):023:0> a=[]
=> []
irb(main):024:0> b="1"
=> "1"
irb(main):025:0> a.push(b)
=> ["1"]
irb(main):026:0> a
=> ["1"]
irb(main):027:0> b="2"
=> "2"
irb(main):028:0> a
=> ["1"]
So far so good. Now, but as soon as I change b into a hash:
irb(main):012:0> a=[]
=> []
irb(main):013:0> b={}
=> {}
irb(main):014:0> b[:file]="one"
=> "one"
irb(main):015:0> a.push(b)
=> [{:file=>"one"}]
irb(main):016:0> a
=> [{:file=>"one"}]
irb(main):017:0> b[:file]="two"
=> "two"
irb(main):018:0> a
**=> [{:file=>"two"}]**
I didn't even push the b value into the a array. What happened here?
b is not a hash. It is a reference to a hash. And pushing a reference somewhere else won't make it point to a new instance.
Copy your hashes explicitly where you want to, using b.dup.
Sometimes even that might not be enough, as the same applies to values inside a hash: the new hash will have the same references inside, it's a so-called "shallow copy".
(Here I was claiming that strings are immutable in Ruby, but #BroiSatse pointed out that it's not true, and he's right, follow the link in the comments.)
Regardless, the explaination is similar: assignment of a new string into a variable produces a new reference to a string (doesn't mutate existing one), writing a new value into a hash doesn't produce a new hash reference (mutates existing hash instead).
You need to understand how ruby variables and Arrays works. Variable holds a reference to the object, which means that if you do:
a = b = []
Both a and b are referencing exactly some object!
a << 1
b #=> [1]
Array is nothing else but an object which holds many references at the same time. But again, they just reference objects, so if you do:
a = {}
b = [a]
Then b[0] and a variable are referencing to the same object.
a[:foo] = :bar
b #=> [{:foo => :bar}]
Now the reason why it seemed to work differently in your first example is that assignment does not modify the object, but rather changes the reference itself.
a = []
b = '1'
a.push(b)
Now both a[0] and b are pointing to the very same object. However if you do:
b = '2'
You create a new string and changes the reference for variable b, but a[0] is still referencing the old string. However, if instead of changeng the reference you execute some modifying method:
b.replace('2')
You'll see it will give you:
a #=> ['2']
I was playing with Rails Console. By chance, I accidentally convert an object into a string.
Below are my codes.
Rails Console
user = User.find(1)
user.to_s # returns <User:0x00000103ada530>
My question is, What is <User:0x00000103ada530> ? Is it like an ID of User? Is I enter <User:0x00000103ada530> will I get back User.find(1)
Thanks
I could be wrong, but
0x00000103ada530
is address in memory
where you call User.new which is allocates memory space and the space has address: 0x00000103ada530
For example 2 instances of one class are not stores in the same place
class Test
end
t1 = Test.allocate # the same as Test.new, but just allocates a memory space for t1
t2 = Test.allocate
p t1 === t2 # false
p t1.inspect # "#<Test:0x007f17555ff398>"
p t2.inspect # "#<Test:0x007f17555ff370>"
If you need #to_s method for User you can set method
class User < ActiveRecord::Base
. . .
def to_s
"#{first_name} #{last_name}"
end
. . .
end
User.first.to_s # => John Doe
The #to_s method encodes the object's id as follows:
(obj.object_id * 2).to_s(16)
If you want to get from the result of #to_s back to the object, you could use ObjectSpace if you are on MRI:
o = Object.new
o2 = ObjectSpace._id2ref(o.to_s.split(":").last.hex / 2)
o and o2 will now be references to the same object.
Conditions: Have to use web based solution (HTML/CSS), Have to use Ruby on Rails, no use of database.
Imagine we have a list of jobs, each represented by a character. Because certain jobs must be done before others, a job may have a dependency on another job. For example, a may depend on b, meaning the final sequence of jobs should place b before a. If a has no dependency, the position of a in the final sequence does not matter. These jobs would be input with a simple text box (also how does one store multiple variables)
Given the following job structure:
a =>
b =>
c =>
The result should be a sequence containing all three jobs abc in no significant order.
Given the following job structure:
a =>
b => c
c => f
d => a
e => b
f =>
The result should be a sequence that positions f before c, c before b, b before e and a before d containing all six jobs abcdef.
Given the following job structure:
a =>
b => c
c => f
d => a
e =>
f => b
The result should be an error stating that jobs can’t have circular dependencies.
This should work:
module JobDependenciesResolver
def self.organize(dependencies)
unresolved_dependencies = dependencies.dup
sorted_jobs = []
until unresolved_dependencies.empty? do
doable_jobs = get_doable_jobs unresolved_dependencies, sorted_jobs
raise Exception.new("Not able to resolve dependencies") if doable_jobs.empty?
sorted_jobs += doable_jobs
unresolved_dependencies.delete_if {|key,value| sorted_jobs.include? key}
end
sorted_jobs
end
private
def self.get_doable_jobs(dependencies, job_array)
dependencies.select {|job, dependency| ([*dependency]-job_array).empty? }.keys
end
end
Sometimes this works, and sometimes it doesn't:
class Foo
has_many :bars
end
class Bar
belongs_to :foo
end
foo = Foo.create
bar1 = Bar.create
bar2 = Bar.create
foo.bars << [bar1, bar2]
The fix is to assign them individually:
foo.bars << bar1
foo.bars << bar2
updated:
in the cases i'm experimenting with, foo and the bars are not new objects.
I haven't see a pattern in when it does or doesn't work. What's more, it seems like how rails deals with mass assignment (attr_accessible) here is odd. If I have code in place to raise an exception if mass assignment is attempted (to help me catch bugs during development), it doesn't work. But if I'm not raising those exceptions, it does work, even though foo_id is not on the attr_accessible list in either case.
Normally if you do "<< [x, y]" you don't push x and y to the array but rather a new array containing x and y (making it a multidimensional array):
> test = Array.new
=> []
> test << [1, 2]
=> [[1, 2]]
You might want to use "<< x << y" instead:
> test = Array.new
=> []
> test << 1 << 2
=> [1, 2]
For newly created objects, I'd recommend using the has_many association helper methods build or create:
foo = Foo.create
bar1 = foo.bars.create # saves the record
bar2 = foo.bars.build # does not save the record
bar2.save! # actually creates the object
These helpers can take a hash of attributes, just like regular create and new - the only difference is they automatically set up the association for you.
If the Bar object you are trying to add to foo already exists, my preference would be to set the association in the bar object:
foo = Foo.create # alternately Foo.find(1)
bar = Bar.find(1) # alternately Bar.new, but then use Foo.bars.build
bar.foo = foo
bar.save!
This way, it's a lot easier to track down problems, e.g. you can easily handle a validation error. The only difference with << is it keeps foo.bars up to date without reloading it - so if you need foo.bars to be immediately up to date with full list of bars (the old bars and the newly associated bars), you might want to use <<.
As a final footnote, you can also use the build helpers to create the whole thing at once:
foo = Foo.new
bar1 = Foo.bars.build
bar2 = Foo.bars.build
foo.save! # saves foo, bar1, and bar2 in one transaction,
# provided they are all valid
There's nothing wrong with the syntax foo.bars << [bar1,bar2]. Regarding the << method as defined on a has_many association, the Rails API says:
collection<<(object, …)
Adds one or more objects to the
collection by setting their foreign
keys to the collection’s primary key.
Note that this operation instantly
fires update sql without waiting for
the save or update call on the parent
object.
That may give you some clues as to the (apparently) inconsistent behavior.
I know these are the basics of rails but i still don't know the full difference between = sign and => and the difference between #some_variable, ##some_variable and :some_variable in rails.
Thanks.
OK.
The difference between the = and the => operators is that the first is assignment, the second represents an association in a hash (associative array). So { :key => 'val' } is saying "create an associative array, with :key being the key, and 'val' being the value". If you want to sound like a Rubyist, we call this the "hashrocket". (Believe it or not, this isn't the most strange operator in Ruby; we also have the <=>, or "spaceship operator".)
You may be confused because there is a bit of a shortcut you can use in methods, if the last parameter is a hash, you can omit the squiggly brackets ({}). so calling render :partial => 'foo' is basically calling the render method, passing in a hash with a single key/value pair. Because of this, you often see a hash as the last parameter to sort of have a poor man's optional parameters (you see something similar done in JavaScript too).
In Ruby, any normal word is a local variable. So foo inside a method is a variable scoped to the method level. Prefixing a variable with # means scope the variable to the instance. So #foo in a method is an instance level.
## means a class variable, meaning that ## variables are in scope of the class, and all instances.
: means symbol. A symbol in Ruby is a special kind of string that implies that it will be used as a key. If you are coming from C#/Java, they are similar in use to the key part of an enum. There are some other differences too, but basically any time you are going to treat a string as any sort of key, you use a symbol instead.
Wow, a that's a lot of different concepts together.
1) = is plain old assignment.
a = 4;
puts a
2) => is used to declare hashes
hash = {'a' => 1, 'b' => 2, 'c' => 3}
puts hash['b'] # prints 2
3) #var lets you access object instance variable.
class MyObject
def set_x(x)
#x = x
end
def get_x
#x
end
end
o = MyObject.new
o.set_x 3
puts o.get_x # prints 3
4) ##var lets you access class ('static') variables.
class MyObject
def set_x(x)
##x = x # now you can access '##x' from other MyObject instance
end
def get_x
##x
end
end
o1 = MyObject.new
o1.set_x 3
o2 = MyObject.new
puts o2.get_x # prints 3, even though 'set_x' was invoked on different object
5) I usually think of :var as special 'label' class. Example 2 can be rephrased like this
hash = {:a => 1, :b => 2, :c => 3}
puts hash[:b] # prints 2