Assign image to asset in Spree - ruby-on-rails

If I manually create an image and assign a product. It works great in console:
p = Spree::Product.first
i = Spree::Image.create!(<create info>)
p.images << i
p.save!
When I try to run this in a program. It doesn't do anything. It runs as if the p.images << i never ran.
I tried searching, but didn't know how to search for << very well.
Update
If I add to the program:
p = Spree::Product.first
i = Spree::Image.create!(<create info>)
i = Spree::Image.find(i.id) #this line
p.images << i
p.save!
This works great, but i don't understand what is going on here.
Thanks in advanced!
Justin

So this is pretty common among ORMs.
The collection<< method adds one or more objects to the collection by
setting their foreign keys to the primary key of the calling model.
Per the rails tutorials:
http://guides.rubyonrails.org/association_basics.html
If you go to that page you can do ctrl+f
and search for: <<
That will give you a ton of information on this.
Also I'll recommend one more source. I like the documentation on this ORM a little better:
http://datamapper.org/docs/associations.html
It's NOT active record, but it's very similar. For me, working with datamapper helped me get a better grasp of active record.
Hope that helps.

Related

Join two hash Tables (dynamoDb) with Ruby on Rails

I am new to Ruby for one project only - I need to join two tables with aws dynamodb. Basically the equivalent of sql left join. But since dynamodb apparently doesn't support I need to make it happen at the array level it seems.
Currently I am querying the one just fine, but I need to bring in this other table, but I'm having a heck of a time finding a simple example for ruby with rails without using ActiveRecord (to avoid causing an overhaul on pre-existing code).
client = Aws::DynamoDB::Client.new
response = client.scan(table_name: 'db_current')
#items = response.items
fake output to protect the innocent
db_current
{"machine_id"=>"pc-123435", "type_id"=>"t-56778"}
db_type
{"description"=>"Dell 5 Dev Computer", "Name"=>"Dell", "type_id"=>"t-56778"}
I thought I might have to make two:
client = Aws::DynamoDB::Client.new
db_c = client.scan(table_name: 'db_current')
#c_items = db_c.items
client = Aws::DynamoDB::Client.new
db_t = client.scan(table_name: 'db_type')
#t_items = db_c.joins(db_t['type_id']) <=== then merge them
here.
where I'll ultimately display description/name/machine_id
But sadly no luck.
I'm looking for suggestions. I'd prefer to keep it simple to really
understand (It might sound unreasonable, I don't want to pull in ActiveRecord just yet unless I'll be owning this project going forward).
I ended up doing it this way. There is probably a more elegant solution for those that are familiar with Ruby... that I am not.
basically for each of the items in the first hash array (table), I use the ID from that one to filter on the item for the 2nd hash array. Merging them in the process. then appending to a final destination which I'll use for my UI.
#c_by_id = Array.new
#b_items.each do |item|
pjoin = #c_items.first {|h| h['b_id'] == item['b_id']}
newjoin = item.merge(pjoin)
#c_by_id.append(newjoin)
end

Migrating records from one table column to another table column. (rails)

I'm working on a rails project in which I need to take some records from one table to another table. Its kinda straight forward.....but i've been having problems and I hope someone could help me out with it.
Basically I've got a record column named research_consent that is in a table named state, that I need to move to a new table named configuration.
The research_consent is a string in the state table, and remains a string in the configuration table.
Below I have the migration that I attempted. I attempted to go through where the states where they had research_consent_text and then move them into the configurations table. (I got a feeling that I'm over-thinking this)
def change
State.where.not(research_consent_text: ["", nil]).each do |state|
config = state.research_consent_text
next if state.research_consent_text.present?
configuration.update_attributes(research_consent_text: state.research_consent_text)
config.save
end
end
If anybody could take a quick look at this and either tell me a far better way to move this, or muddle through my pitiful attempt and let me know if there is a better way, I would greatly appreciate this!
I would do something like this
def change
State.where.not(research_consent_text: ["", nil]).each do |state|
configuration.find_or_create_by(research_consent_text: state.research_consent_text) do |configuration|
configuration.anything_else
end
end
end
you can see more on find_or_create_by
I hope that this helps.
Happy hacking

Rails - ActiveRecord Dirty - Getting associated objects from the changes hash

I'm working on an audit trail of sorts for an app so that the user can see what is being changed throughout the system.
I have a hash of changes from ActiveRecord Dirty, like follows:
{"ingredient_type_id"=>[nil, 199575006], "name"=>[nil, "asdfg"], "amount"=>[nil, 3.0], "unit"=>[nil, "x"], "notes"=>[nil, "asdf"]}
This works great and I can parse what I need to output and create database records with the info.
I just have one question - How can I get associated objects from this? In this case, the ingredient_type? I actually want to output something like:
"Ingredient type was changed to #{IngredientType.find(199575006).name}."
But I'm not sure how I would parse that hash on a dynamic basis to do that.
Pretty much the way you've suggested I'd have thought, But you don't need to parse the hash for the changes, Dirty gives you much more than that
if ingredient_type_id_changed?
unless ingredient_type_id.blank?
ingredient_name = IngredientType.find(ingredient_type_id).name
else
ingredient_name = 'blank'
end
end
You might even be able to do ingredient_type.name, Not sure at that point if active record dirty will let you go through the association. If you test it (or if anyone else knows) let me know

Rails named scopes

I was trying to refactoring and optimizing me code. In particular, I wanted to reduce the amount of queries going to the database. In my users controller it worked very well but in an other controller, where I tried the same, it didn't. I've searched for some time now for the answer why it didn't work but I can't really answer it.
I've got users, which can subscribe to courses through enrolments. They are connected through has_many :through etc. relationships. The following works:
#users_courses = current_user.courses
#courses = #users_courses.a_named_scope
But in my courses controller the following wont work:
#all_courses = Course.all
#specific_course = #all_courses.specific_course_scope
The scopes are defined in the respective models and work properly. They are not complicated, just "where ... true/false" definitions. Does someone know the problem here? Thanks!
I'm using rails version 3.2 and ruby version 2.
Until Rails 4 you should use scoped method if you want to have ActiveRecord::Relation instance (on which you can call other scopes) returned instead of Array:
#all_courses = Course.scoped
#specific_course = #all_courses.specific_course_scoped
This should work.
If you want to use includes(:courses), you just do it, for example with:
#specific_course = #all_courses.specific_course_scoped.includes(:courses)

rails/activerecord search eager loaded associations

I have a simple find statement as such:
m = MyModel.find(1, :include => :my_children)
With m.mychildren being an Array; is there anyway to find a particular record from within the array without having to iterate over the entire thing. If I do mychildren.find(1), a new DB query is issues, which doesn't make sense, since they are all loaded already
It looks like there's a little Rails magic going on here. Where Enumerable#find is being overridden by ActiveRecord::Base#find on methods created for associations.
On the upside Enumerable#find is aliased to Enumerable#detect.
Unfortunately Enumerable#find/Enumerable#detect have significantly different syntax from ActiveRecord::Base#find.
So you can't just do mychildren.find(1), instead you've got to do mychildren.detect{|c| c.id == 1} if you want to avoid hitting the database again. You may also want to consider extending Array for a more DRY way of doing this.
class Array
def id_find id
self.detect{|element| element.id == id}
end
end
I'm not quite sure what your asking, but have you tried select:
m.mychildren.select{ |child| child == <<some_statement>> }
This won't hit the database assuming you've used the :include option as you stated in your question.
Alternatively, if you know the number of the child you want, you should be able to just use
m.mychildren[1]

Resources