Is this any possible?
I'd like to have something like
User.avatar.to_url
which would then print the full URL address for the user's avatar image.
=> "http://url.com/images/avatars/1262694724.jpeg"
Of course, the avatar attribute would be an existing column on the users table which contains a long integer.
The to_url method im thinking on would be defined as:
def to_url
"http://url.com/images/avatars/#{self}.jpeg"
end
If avatar is an attribute (as opposed to another model/association) then you're going to save yourself a world of trouble by just doing:
def avatar_url
"http://url.com/images/avatars/#{avatar}.jpeg"
end
Related
I have the following hash holding a user's name and items_sold:
{"dave"=>9, "steve"=>20}
I created it in my Rawdatum Index action through:
#consolidated_rawdata = Rawdatum.all.group(:user).sum(:items_sold)
What I want to do now is to save both objects from that hash (dave & steve) with a single action (a single click on a button) to a table called reports with two columns: user and items_sold like so:
How can I achieve that?
Don't know if that counts as a single action, but you can iterate through the hash like this:
#consolidated_rawdata.each {|name, items_sold| Report.create(user:
name, items_sold: items_sold)}
if a action is just a single click then its really simple. We can just loop threw the hash and save the record
I would put this in a model like Reports
class Report < ApplicationRecord
#Report.create_consolidated_rawdata
def self.create_consolidated_rawdata
#consolidated_rawdata = Rawdatum.all.group(:user).sum(:items_sold)
#consolidated_rawdata.do |name, items_sold|
Report.create(user: name, items_sold: items_sold)
end
end
end
I hope that this works
so i need to create an image that belongs to my model (string with the url of the image) in the models create method.
the problem is, that this image is a QR-Code that should contain the url of the object that gets created.
but the URL (of course) is unknown in the create method because no id exists at that point for the given object.
any ideas how to solve this problem?
I don't see an obvious way of doing this, beyond using a non id column within the URL (e.g. make a call to generate a UDID/GUID, and use that in the url http://mysite.com/obj/#{udid}), or saving in two stages, using the after_create callback to set the image once the record has been saved:
class MyModel < ActiveRecord::Base
after_create :set_image
def set_image
if image_attribute == nil
image_attribute = generate_a_qr_code(self)
self.save
end
end
end
Use two-pass saving :-)
def create
model = Model.new params[:model]
if model.save
# at this point you have an id
model.qr = generate_qr model
model.save
# proceed as usual
end
end
This is for traditional databases with auto-increment column as primary key. In some databases, keys are generated using sequences that you can query to get a new value (before saving your object). In some databases (MongoDB) keys can be generated on the client completely.
Hey,
Not a Rails noob but this has stumped me.
With has many through associations in Rails. When I mass assign wines to a winebar through a winelist association (or through) table with something like this.
class WineBarController
def update
#winebar = WineBar.find(params[:id])
#winebar.wines = Wine.find(params[:wine_bar][:wine_ids].split(",")) // Mass assign wines.
render (#winebar.update_attributes(params[:wine_bar]) ? :update_success : :update_failure)
end
end
This will delete every winelist row associated with that winebar. Then it finds all of the wines in wine_ids, which we presume is a comma separated string of wine ids. Then it inserts back into the winelist a new association. This would be expensive, but fine if the destroyed association rows didn't have metadata such as the individual wine bar's price per glass and bottle.
Is there a way to have it not blow everything away, just do an enumerable comparison of the arrays and insert delete whatever changes. I feel like that's something rails does and I'm just missing something obvious.
Thanks.
Your problem looks like it's with your first statement in the update method - you're creating a new wine bar record, instead of loading an existing record and updating it. That's why when you examine the record, there's nothing showing of the relationship. Rails is smart enough not to drop/create every record on the list, so don't worry about that.
If you're using the standard rails setup for your forms:
<% form_for #wine_bar do |f| %>
Then you can call your update like this:
class WineBarController
def update
#winebar = WineBar.find(params[:id])
render (#winebar.update_attributes(params[:wine_bar]) ? :update_success : :update_failure)
end
end
You don't need to explicitly update your record with params[:wine_bar][:wine_ids], because when you updated it with params[:wine_bar], the wine_ids were included as part of that. I hope this helps!
UPDATE: You mentioned that this doesn't work because of how the forms are setup, but you can fix it easily. In your form, you'll want to rename the input field from wine_bar[wine_ids] to wine_bar[wine_ids_string]. Then you just need to create the accessors in your model, like so:
class WineBar < ActiveRecord::Base
def wine_ids_string
wines.map(&:id).join(',')
end
def wine_ids_string= id_string
self.wine_ids = id_string.split(/,/)
end
end
The first method above is the "getter" - it takes the list of associated wine ids and converts them to a string that the form can use. The next method is the "setter", and it accepts a comma-delimited string of ids, and breaks it up into the array that wine_ids= accepts.
You might also be interested in my article Dynamic Form Elements in Rails, which outlines how rails form inputs aren't limited to the attributes in the database record. Any pair of accessor methods can be used.
I'm trying to override the way rails apply and id to an associated object, for example:
There are 2 simple models:
class Album < ActiveRecord::Base
has_many :photos
end
class Photo < ActiveRecord::Base
belongs_to :album
end
And then I want to do this:
album = Album.new :title => 'First Album'
album.photos.build
album.save #=> true
On this case I've created a plugin that overrides the id property and replaces it to a hashed string, so what I want to do is find the methods where this album_id is being replaced for my custom method instead of the int and be able to converted before it's saved.
But I want to act globally inside Rails structure because since it will be a sort of plugin I want to make this action work on dynamic models, that's why I can't create an before_save validation on the model.
I'm not sure if it's easy to understand, but I hope someone could help me on that..
Here's a screenshot of my current table so you can see what is happening:
SQLite3 DB http://cl.ly/1j3U/content
So as you can see the album_id it's being replaced for my custom ruby object when its saved...I've disabled the plugin and then it saved normally with records 11 and 12...
I want just act on a rails action and converted with my custom methods, something like
def rails_association_replaced_method(record)
#take the record associations and apply a to_i custom method before save
super(record)
end
something like this :)
Well I hope this didn't get too complicated
Cheers
It seems if I only override theActiveRecord::Base save method do the job if handled properly
define_method 'save' do
int_fields = self.class.columns.find_all { |column| column.type == :integer }
int_fields.each do |field|
if self.attributes[field.name]
self.attributes[field.name] = self.attributes[field.name].to_i
end
end
super
end
And this shall replace all the integer fields from the Current Model applying a to_i method over the result.
Rails is unfriendly to that kind of change to the defaults. What's your end goal here?
I have a user model which has multiple addresses. Now for my application in rails, address is not mandatory. So, if someone wants to create a user and enter the address after the user has been created, my application should allow that. My problem is, for Address model I have validations for Address Line 1, City and Postal Code. These fields cannot be blank. When, editing a user, the following code fails:
user.addresses << Address.new
Rails tries to create a new Address and fires an Insert command. This is going to fail because of the validations that is required in the model. The above code doesn't fail if the user is not present in the database. One solution to this problem is to create a separate form_for binding for the edit partial for user. I don't want to do that solution. Is there any solution that allows me to bind an empty Address object for an already existing User object in the database ?
Why attempt to add an empty Address object to the user.addresses collection? I think you could simply do something like:
user.addresses << Address.new unless (conditions)
I unfortunately don't know what your conditions are here, so it could be something like
user.addresses << Address.new unless params[:address].nil?
...although my guess is that you have a real Address object instead of just passing in a blank Address.new...
user.addresses << Address.new
This code isn't going to work anyway if your Address model requires its fields to be set, because you're not supplying a hash to Address.new
If you want to add the address conditionally, you probably want something like this:
if !params[:address].blank?
user.addresses.create(params[:address])
end
or
user.addresses << Address.new(params[:address]) unless params[:address].blank
If you really want to create an "empty" address object for each user (instead of just having users without addresses), you can change your validations so they only fire if the fields are filled out.
Something like this:
class Address < ActiveRecord::Base
validates_presence_of :address1, :if => :non_empty_address?
# etc
private
def non_empty_address?
!address1.blank? || !address2.blank || !city.blank? # etc
end
end
The restful_authentication plugin uses a similar approach to determine if the user's password is required.