I'm building a app to manage some products, so I have a Product model.
We sell, buy and when a product breakes, we send it to the manufacturer for repair.
So, I've created a Movimentation model, that will take care of all ins and outs of a product.
When we bought a product, a In record is generated for each product on the Movimentation table. Out for sells and repairs.
I'm trying to make it the more restfull possible, and that's why I'm confused.
How should I do it? A resource :movimentation ? Or should I create a "product_in" and a "product_out" controllers?
I want urls to be like "movimentation/:to_where/:direction" (in/out) and so draw the views correctly.
Any toughts?
you could have a movimentation_controller with in/out actions and :to_where param. so for the routes you have two choices:
#if you have other REST actions do this:
resources :movimentation do
member do
get :in
get :out
end
end
#or go with a match:
match '/movimentation/in/:to_where' => 'movimentation#in'
match '/movimentation/out/:to_where' => 'movimentation#out'
cheers,
A.
Related
I'm using listings api to get listings, inventory and variations in one shot:
https://openapi.etsy.com/v2/listings/123456789?includes=Inventory,Images,MainImage,Variations,Attributes&api_key=XXXXXXXXX
And I would like in addition the relation between variations and images.
So for that point, the variation-images api is fine:
https://openapi.etsy.com/v2/listings/123456789/variation-images?api_key=XXXXXXXXX
This give me back the following associations : (property_id, value_id, image_id) !
But now when I try to get all-in-one (adding VariationImage to ?includes) :
https://openapi.etsy.com/v2/listings/123456789?includes=Inventory,Images,MainImage,Variations,Attributes,VariationImage&api_key=XXXXXXXXX
I get a 400 response:Model ShopListing has no association named VariationImage
however this association is present in the list of possible associations of the official documentation.
Do you have a tip to get this relation in one shot ?
First, some background:
I have a Company model, a Project model and a Task model. A Project belongs to a company and a Task belongs_to a Project.
The Project model holds several attributes: company_id, date. These attributes uniquely identify a project
I am letting the users create a task by API by POSTing to a URL that contains the details necessary to identify the Project. For example:
POST /projects/<comnpany_name>/<date>/tasks/
In order to make life easier for the users, in case there is no project with the given details, I'd like to create the project on the fly by the given details, and then to create the task and assign it to the project.
...And my problem is:
When there is a problem to create the project, let's say that the company name is not valid, what is the right way to return the error message and communicate to the user?
I'll explain what I mean: I added a create_by_name_and_company_name method to the Project:
def self.create_by_name_and_company_name(name, company_name)
if company = Company.find_by_name(company_name)
project = Project.create(company_id: company.id,
name: name)
else # cannot create this project, trying to communicate the error
project = Project.new(name: name)
project.errors.add(:company, 'must have a valid name')
end
company
end
I was hoping that by returning an unsaved Company object, with errors set, will be a good way communicate the error (This is similar to how rails work when there's a validation error).
The problem is that when calling valid? on the company object, it removed the error I wrote there and adds the regular validation errors (in this case, company can't be blank).
And a bonus question...
And there is a conceptual problem as well: since I'm creating a model by providing parameters that are being used to create the actual attributes, they doesn't always map nicely to the errors[:attr] hash. In this case it is not so bad and I'm using the company field for the company name parameter, but I guess this can get messier when the parameters provided to the create method are less similar to the model attributes.
So what is the preferred approach to tackle that problem? Is there something basically wrong with that approach? if so, what is the preferred approach?
About overriding the default rails validation error message, you need to write your validation constraint like this:
validates_presence_of :name, :message => "must be a valid name"
I figure that it is best to avoid such nesting and stick to a shallower API.
I am very new to RoR so this may be very fundamental. My structure keeps getting a level deeper and I can't figure out how to find the id anymore.
First you have a Company which can have many Users. Users sign in and are authenticated and the current_user is saved in a cookie with the Session.
Since the User has one Company I can always find the Company.id through the current_user.
Next a Company has many Farms. In farms create I can get the company id from the user cookie and the farm id is new so that works, and in farm show Rails knows which farm it is supposed to show. So that level works.
Now I want to add that a Farm has many Blocks. I am adding Blocks through the associated Farm show page, but the Blocks_controller doesn't know what farm page it is on (as far as I can tell, if it can any info is appreciated).
Here is the FarmsController create that works:
def create
company_id = current_user.company_id
#company = Company.find(company_id)
#farm = #company.farms.build(params[:farm])
if #farm.save
flash[:success] = "farm created"
redirect_to root_path
else
render 'pages/home'
end
end
And this code just complains that it doesn't know what id I am talking about:
BlocksController
def create
#farm = Farm.find(params[:id])
#block = #farm.blocks.build(params[:block])
end
This is displaying on the associated Farm show page, so if there is a way to capture the id I would love to know what it is.
Thank you for your time.
The three easiest ways to get that id is to:
Pass in that farm_id using a hidden form field. When creating the link to your blocks/new form just pass in the farm_id ie use a path like new_blocks_path(:id => #farm.id) inside your blocks controller you will want to make sure that the farm_id is set on the Block model.
def new
#block = new Block
#block.farm_id = params[:farm_id]
end
Then if you are using form for the farm_id field (which should probably be of type hidden), it should contain the right id. Now change the first line in the "create" block method to
#farm = Farm.find(params[:block][:farm_id])
You can combine the process of adding the blocks and the farms using nested forms. Take a look at http://railscasts.com/episodes/196-nested-model-form-part-1 for how to do this.
You can use nested RESTful resources to make sure that within the blocks controller you always have access to the farm id. For more information about how to do this try take a look at http://railscasts.com/episodes/139-nested-resources
I have a Transactions object (as a part of a shopping cart) that belongs_to two other objects, Products and Services. Both Products and Services are nested with Transactions to create URLs like /products/1/transactions/new and /services/1/transactions/new. And, the forms are created using form_for [#product, #transaction] do |f| type formats. Note: Products and Services are too different in design and functionality to combine them into a STI-type single object.
My question is: Is there a better way of doing this without STI? And, what's the best way to check in the controller to determine the type of object to act on?
IE in the new action:
if ???
#product = Product.find(params[:product_id])
#transaction = #product.transactions.build
elsif ???
#service = Service.find(params[:service_id])
#transaction = #service.transactions.build
end
On a related note, does anyone know of any tutorials that discuss shopping cart design for Rails 3? I've seen a few in books, but they use sessions to store the entire cart object, which isn't very secure, in my opinion. And, others are overly simplistic.
Any help would be greatly appreciated!
I think you have two basic options here.
(1) Create two transaction types/models: product_transactions and service_transactions. Both can inherit from a common transaction module. This approach allows you to ignore the issue of which, "which kind of transaction am I dealing with?" and focus on the common implementation details in the transaction module. You can then maintain two simpler nested controllers, /products/<id>/transactions and /services/<id>/transactions that don't require type checking.
(2) Move the type checking into the common transaction model. This approach assumes that interactions between the transaction and product or service will be handled via the transaction module, so it won't be your responsibility to know which one you are interacting with. For example:
class Transaction
belongs_to :service
belongs_to :product
def parent
#parent ||= product || service
end
def call_some_action_on_parent
parent.some_action
end
end
You can do something similar in your controller:
#parent = params[:service_id].blank? ? Product.find(params[:product_id]) : Service.find(params[:service_id])
#transaction = #parent.transactions.build(params[:transaction])
The option you settle on should really be a decision based on your needs surrounding the transaction object. If there is a lot of custom code depending on if you are interacting with a product or service you should follow the first approach. If the code is essentially the same you should take the second approach and focus on the contract between a transaction and its parent object (product, service or other) and ignore what the object type is. In essence you are really only interested in whether or not the parent object responds to specific methods, not what kind of object it actually is. As a general rule, when possible, avoid type checking and focus on the responds_to? method instead.
I have a table Category that is a polymorphic model for a bunch of other models. For instance
model Address has shipping, billing,
home, work category
model Phone has home, mobile, work,
fax category
model Product has medical, it
equipment, automotive, aerospace, etc
categories.
What I want to be able to do is something like
Product.all_categories and get and array of all categories that are specific to this model.
Of course I can do something like this for each model in question:
Category.select("name").where("categorizable_type = ?","address")
Also pace_car - which is rails 3 ready, allows me to do something like this:
Category.for_category_type(Address)
But I was wondering if there is a more straightforward / elegant solution to this problem using Active Record iteself - without relying on a gem?
Thank you
I'm not aware of anything built-in to ActiveRecord to give you this, but you could set up that for_category_type method in one line of code in your Category controller:
scope :for_category_type, lambda { |class_name| where("categorizable_type = ?", class_name) }